summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/seccomp.c4
-rw-r--r--src/fseccomp/fseccomp.h2
-rw-r--r--src/fseccomp/seccomp.c12
-rw-r--r--src/fseccomp/seccomp_file.c48
-rw-r--r--src/fseccomp/syscall.c10
-rw-r--r--src/man/firejail.txt23
6 files changed, 79 insertions, 20 deletions
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index 81ab18aa1..50fc0384c 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -48,10 +48,10 @@ char *seccomp_check_list(const char *str) {
48 const char *ptr1 = str; 48 const char *ptr1 = str;
49 char *ptr2 = rv; 49 char *ptr2 = rv;
50 while (*ptr1 != '\0') { 50 while (*ptr1 != '\0') {
51 if (isalnum(*ptr1) || *ptr1 == '_' || *ptr1 == ',' || *ptr1 == ':' || *ptr1 == '@' || *ptr1 == '-') 51 if (isalnum(*ptr1) || *ptr1 == '_' || *ptr1 == ',' || *ptr1 == ':' || *ptr1 == '@' || *ptr1 == '-' || *ptr1 == '!')
52 *ptr2++ = *ptr1++; 52 *ptr2++ = *ptr1++;
53 else { 53 else {
54 fprintf(stderr, "Error: invalid syscall list\n"); 54 fprintf(stderr, "Error: invalid syscall list entry %s\n", str);
55 exit(1); 55 exit(1);
56 } 56 }
57 } 57 }
diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h
index 593963e76..e1579d098 100644
--- a/src/fseccomp/fseccomp.h
+++ b/src/fseccomp/fseccomp.h
@@ -52,7 +52,9 @@ void seccomp_secondary_block(const char *fname);
52void write_to_file(int fd, const void *data, int size); 52void write_to_file(int fd, const void *data, int size);
53void filter_init(int fd); 53void filter_init(int fd);
54void filter_add_whitelist(int fd, int syscall, int arg, void *ptrarg); 54void filter_add_whitelist(int fd, int syscall, int arg, void *ptrarg);
55void filter_add_whitelist_for_excluded(int fd, int syscall, int arg, void *ptrarg);
55void filter_add_blacklist(int fd, int syscall, int arg, void *ptrarg); 56void filter_add_blacklist(int fd, int syscall, int arg, void *ptrarg);
57void filter_add_blacklist_for_excluded(int fd, int syscall, int arg, void *ptrarg);
56void filter_add_errno(int fd, int syscall, int arg, void *ptrarg); 58void filter_add_errno(int fd, int syscall, int arg, void *ptrarg);
57void filter_end_blacklist(int fd); 59void filter_end_blacklist(int fd);
58void filter_end_whitelist(int fd); 60void filter_end_whitelist(int fd);
diff --git a/src/fseccomp/seccomp.c b/src/fseccomp/seccomp.c
index 2a719725e..95c20d388 100644
--- a/src/fseccomp/seccomp.c
+++ b/src/fseccomp/seccomp.c
@@ -80,6 +80,10 @@ void seccomp_drop(const char *fname1, const char *fname2, char *list, int allow_
80 80
81 // build pre-exec filter: don't blacklist any syscalls in @default-keep 81 // build pre-exec filter: don't blacklist any syscalls in @default-keep
82 filter_init(fd); 82 filter_init(fd);
83
84 // allow exceptions in form of !syscall
85 syscall_check_list(list, filter_add_whitelist_for_excluded, fd, 0, NULL);
86
83 char *prelist, *postlist; 87 char *prelist, *postlist;
84 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist); 88 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist);
85 if (prelist) 89 if (prelist)
@@ -128,6 +132,10 @@ void seccomp_default_drop(const char *fname1, const char *fname2, char *list, in
128 // build pre-exec filter: blacklist @default, don't blacklist 132 // build pre-exec filter: blacklist @default, don't blacklist
129 // any listed syscalls in @default-keep 133 // any listed syscalls in @default-keep
130 filter_init(fd); 134 filter_init(fd);
135
136 // allow exceptions in form of !syscall
137 syscall_check_list(list, filter_add_whitelist_for_excluded, fd, 0, NULL);
138
131 add_default_list(fd, allow_debuggers); 139 add_default_list(fd, allow_debuggers);
132 char *prelist, *postlist; 140 char *prelist, *postlist;
133 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist); 141 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist);
@@ -175,6 +183,10 @@ void seccomp_keep(const char *fname1, const char *fname2, char *list) {
175 183
176 // build pre-exec filter: whitelist also @default-keep 184 // build pre-exec filter: whitelist also @default-keep
177 filter_init(fd); 185 filter_init(fd);
186
187 // allow exceptions in form of !syscall
188 syscall_check_list(list, filter_add_blacklist_for_excluded, fd, 0, NULL);
189
178 // these syscalls are used by firejail after the seccomp filter is initialized 190 // these syscalls are used by firejail after the seccomp filter is initialized
179 int r; 191 int r;
180 r = syscall_check_list("@default-keep", filter_add_whitelist, fd, 0, NULL); 192 r = syscall_check_list("@default-keep", filter_add_whitelist, fd, 0, NULL);
diff --git a/src/fseccomp/seccomp_file.c b/src/fseccomp/seccomp_file.c
index 2e1f317ed..266ef0c55 100644
--- a/src/fseccomp/seccomp_file.c
+++ b/src/fseccomp/seccomp_file.c
@@ -60,26 +60,58 @@ void filter_init(int fd) {
60 write_to_file(fd, filter, sizeof(filter)); 60 write_to_file(fd, filter, sizeof(filter));
61} 61}
62 62
63void filter_add_whitelist(int fd, int syscall, int arg, void *ptrarg) { 63static void write_whitelist(int fd, int syscall) {
64 (void) arg;
65 (void) ptrarg;
66
67 struct sock_filter filter[] = { 64 struct sock_filter filter[] = {
68 WHITELIST(syscall) 65 WHITELIST(syscall)
69 }; 66 };
70 write_to_file(fd, filter, sizeof(filter)); 67 write_to_file(fd, filter, sizeof(filter));
71} 68}
72 69
73void filter_add_blacklist(int fd, int syscall, int arg, void *ptrarg) { 70static void write_blacklist(int fd, int syscall) {
74 (void) arg;
75 (void) ptrarg;
76
77 struct sock_filter filter[] = { 71 struct sock_filter filter[] = {
78 BLACKLIST(syscall) 72 BLACKLIST(syscall)
79 }; 73 };
80 write_to_file(fd, filter, sizeof(filter)); 74 write_to_file(fd, filter, sizeof(filter));
81} 75}
82 76
77void filter_add_whitelist(int fd, int syscall, int arg, void *ptrarg) {
78 (void) arg;
79 (void) ptrarg;
80
81 if (syscall >= 0) {
82 write_whitelist(fd, syscall);
83 }
84}
85
86// handle seccomp list exceptions (seccomp x,y,!z)
87void filter_add_whitelist_for_excluded(int fd, int syscall, int arg, void *ptrarg) {
88 (void) arg;
89 (void) ptrarg;
90
91 if (syscall < 0) {
92 write_whitelist(fd, -syscall);
93 }
94}
95
96void filter_add_blacklist(int fd, int syscall, int arg, void *ptrarg) {
97 (void) arg;
98 (void) ptrarg;
99
100 if (syscall >= 0) {
101 write_blacklist(fd, syscall);
102 }
103}
104
105// handle seccomp list exceptions (seccomp x,y,!z)
106void filter_add_blacklist_for_excluded(int fd, int syscall, int arg, void *ptrarg) {
107 (void) arg;
108 (void) ptrarg;
109
110 if (syscall < 0) {
111 write_blacklist(fd, -syscall);
112 }
113}
114
83void filter_add_errno(int fd, int syscall, int arg, void *ptrarg) { 115void filter_add_errno(int fd, int syscall, int arg, void *ptrarg) {
84 (void) ptrarg; 116 (void) ptrarg;
85 struct sock_filter filter[] = { 117 struct sock_filter filter[] = {
diff --git a/src/fseccomp/syscall.c b/src/fseccomp/syscall.c
index 3b698d2dd..d31b719d6 100644
--- a/src/fseccomp/syscall.c
+++ b/src/fseccomp/syscall.c
@@ -497,9 +497,17 @@ int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall,
497 syscall_check_list(new_list, callback, fd, arg, ptrarg); 497 syscall_check_list(new_list, callback, fd, arg, ptrarg);
498 } 498 }
499 else { 499 else {
500 bool negate = false;
501 if (*ptr == '!') {
502 negate = true;
503 ptr++;
504 }
500 syscall_process_name(ptr, &syscall_nr, &error_nr); 505 syscall_process_name(ptr, &syscall_nr, &error_nr);
501 if (syscall_nr == -1) {;} 506 if (syscall_nr == -1) {;}
502 else if (callback != NULL) { 507 else if (callback != NULL) {
508 if (negate) {
509 syscall_nr = -syscall_nr;
510 }
503 if (error_nr != -1 && fd != 0) { 511 if (error_nr != -1 && fd != 0) {
504 filter_add_errno(fd, syscall_nr, error_nr, ptrarg); 512 filter_add_errno(fd, syscall_nr, error_nr, ptrarg);
505 } 513 }
@@ -522,7 +530,7 @@ static void find_syscall(int fd, int syscall, int arg, void *ptrarg) {
522 (void)fd; 530 (void)fd;
523 (void) arg; 531 (void) arg;
524 SyscallCheckList *ptr = ptrarg; 532 SyscallCheckList *ptr = ptrarg;
525 if (syscall == ptr->syscall) 533 if (abs(syscall) == ptr->syscall)
526 ptr->found = true; 534 ptr->found = true;
527} 535}
528 536
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 86b76f58f..afff3d5fa 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -1780,7 +1780,8 @@ system call groups are defined: @clock, @cpu-emulation, @debug,
1780@default, @default-nodebuggers, @default-keep, @module, @obsolete, 1780@default, @default-nodebuggers, @default-keep, @module, @obsolete,
1781@privileged, @raw-io, @reboot, @resources and @swap. In addition, a 1781@privileged, @raw-io, @reboot, @resources and @swap. In addition, a
1782system call can be specified by its number instead of name with prefix 1782system call can be specified by its number instead of name with prefix
1783$, so for example $165 would be equal to mount on i386. 1783$, so for example $165 would be equal to mount on i386. Exceptions
1784can be allowed with prefix !.
1784 1785
1785.br 1786.br
1786System architecture is strictly imposed only if flag 1787System architecture is strictly imposed only if flag
@@ -1798,8 +1799,10 @@ Example:
1798.br 1799.br
1799$ firejail \-\-seccomp 1800$ firejail \-\-seccomp
1800.TP 1801.TP
1801\fB\-\-seccomp=syscall,@group 1802\fB\-\-seccomp=syscall,@group,!syscall2
1802Enable seccomp filter, blacklist the default list (@default) and the syscalls or syscall groups specified by the command. 1803Enable seccomp filter, whitelist "syscall2", but blacklist the default
1804list (@default) and the syscalls or syscall groups specified by the
1805command.
1803.br 1806.br
1804 1807
1805.br 1808.br
@@ -1863,8 +1866,9 @@ domain with personality(2) system call.
1863.br 1866.br
1864 1867
1865.TP 1868.TP
1866\fB\-\-seccomp.drop=syscall,@group 1869\fB\-\-seccomp.drop=syscall,@group,!syscall2
1867Enable seccomp filter, and blacklist the syscalls or the syscall groups specified by the command. 1870Enable seccomp filter, whitelist "syscall2" but blacklist the
1871syscalls or the syscall groups specified by the command.
1868.br 1872.br
1869 1873
1870.br 1874.br
@@ -1899,10 +1903,11 @@ rm: cannot remove `testfile': Operation not permitted
1899 1903
1900 1904
1901.TP 1905.TP
1902\fB\-\-seccomp.keep=syscall,syscall,syscall 1906\fB\-\-seccomp.keep=syscall,@group,!syscall2
1903Enable seccomp filter, and whitelist the syscalls specified by the 1907Enable seccomp filter, blacklist "syscall2" but whitelist the
1904command. The system calls needed by Firejail (group @default-keep: 1908syscalls or the syscall groups specified by the command. The system
1905prctl, execve) are handled with the preload library. 1909calls needed by Firejail (group @default-keep: prctl, execve) are
1910handled with the preload library.
1906.br 1911.br
1907 1912
1908.br 1913.br