aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/firejail.h19
-rw-r--r--src/firejail/main.c51
-rw-r--r--src/firejail/profile.c12
-rw-r--r--src/firejail/protocol.c240
-rw-r--r--src/firejail/sandbox.c21
-rw-r--r--src/firejail/seccomp.c18
-rw-r--r--src/firejail/seccomp.h16
-rwxr-xr-xsrc/tools/syscall_testbin0 -> 8702 bytes
-rw-r--r--src/tools/syscall_test.c70
-rwxr-xr-xsrc/tools/syscall_test32bin0 -> 6566 bytes
10 files changed, 398 insertions, 49 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index ab2fedbd8..e79cc4a2c 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -107,6 +107,13 @@ typedef struct config_t {
107 uint32_t dns2; 107 uint32_t dns2;
108 uint32_t dns3; 108 uint32_t dns3;
109 109
110 // seccomp
111 char *seccomp_list;// optional seccomp list on top of default filter
112 char *seccomp_list_drop; // seccomp drop list
113 char *seccomp_list_keep; // seccomp keep list
114 char **seccomp_list_errno; // seccomp errno[nr] lists
115 char *protocol; // protocol list
116
110 // rlimits 117 // rlimits
111 unsigned rlimit_nofile; 118 unsigned rlimit_nofile;
112 unsigned rlimit_nproc; 119 unsigned rlimit_nproc;
@@ -152,10 +159,6 @@ extern int arg_zsh; // use zsh as default shell
152extern int arg_csh; // use csh as default shell 159extern int arg_csh; // use csh as default shell
153 160
154extern int arg_seccomp; // enable default seccomp filter 161extern int arg_seccomp; // enable default seccomp filter
155extern char *arg_seccomp_list;// optional seccomp list on top of default filter
156extern char *arg_seccomp_list_drop; // seccomp drop list
157extern char *arg_seccomp_list_keep; // seccomp keep list
158extern char **arg_seccomp_list_errno; // seccomp errno[nr] lists
159 162
160extern int arg_caps_default_filter; // enable default capabilities filter 163extern int arg_caps_default_filter; // enable default capabilities filter
161extern int arg_caps_drop; // drop list 164extern int arg_caps_drop; // drop list
@@ -355,7 +358,7 @@ void caps_print_filter_name(const char *name);
355const char *syscall_find_nr(int nr); 358const char *syscall_find_nr(int nr);
356// return -1 if error, 0 if no error 359// return -1 if error, 0 if no error
357int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg); 360int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg);
358// print all available syscalls 361// print all available syscallsseccomp
359void syscall_print(void); 362void syscall_print(void);
360 363
361// fs_trace.c 364// fs_trace.c
@@ -425,5 +428,11 @@ void pulseaudio_disable(void);
425void fs_check_bin_list(void); 428void fs_check_bin_list(void);
426void fs_private_bin_list(void); 429void fs_private_bin_list(void);
427 430
431// protocol.c
432void protocol_list();
433void protocol_print_filter_name(const char *name);
434void protocol_print_filter(pid_t pid);
435void protocol_store(const char *prlist);
436void protocol_filter(void);
428#endif 437#endif
429 438
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 8d11caef3..e39a41502 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -58,10 +58,6 @@ int arg_zsh = 0; // use zsh as default shell
58int arg_csh = 0; // use csh as default shell 58int arg_csh = 0; // use csh as default shell
59 59
60int arg_seccomp = 0; // enable default seccomp filter 60int arg_seccomp = 0; // enable default seccomp filter
61char *arg_seccomp_list = NULL; // optional seccomp list on top of default filter
62char *arg_seccomp_list_drop = NULL; // seccomp drop list
63char *arg_seccomp_list_keep = NULL; // seccomp keep list
64char **arg_seccomp_list_errno = NULL; // seccomp errno[nr] lists
65 61
66int arg_caps_default_filter = 0; // enable default capabilities filter 62int arg_caps_default_filter = 0; // enable default capabilities filter
67int arg_caps_drop = 0; // drop list 63int arg_caps_drop = 0; // drop list
@@ -312,7 +308,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
312 exit(0); 308 exit(0);
313 } 309 }
314 else if (strncmp(argv[i], "--seccomp.print=", 16) == 0) { 310 else if (strncmp(argv[i], "--seccomp.print=", 16) == 0) {
315 // join sandbox by pid or by name 311 // print seccomp filter for a sandbox specified by pid or by name
316 pid_t pid; 312 pid_t pid;
317 if (read_pid(argv[i] + 16, &pid) == 0) 313 if (read_pid(argv[i] + 16, &pid) == 0)
318 seccomp_print_filter(pid); 314 seccomp_print_filter(pid);
@@ -320,6 +316,19 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
320 seccomp_print_filter_name(argv[i] + 16); 316 seccomp_print_filter_name(argv[i] + 16);
321 exit(0); 317 exit(0);
322 } 318 }
319 else if (strcmp(argv[i], "--debug-protocols") == 0) {
320 protocol_list();
321 exit(0);
322 }
323 else if (strncmp(argv[i], "--protocol.print=", 17) == 0) {
324 // print seccomp filter for a sandbox specified by pid or by name
325 pid_t pid;
326 if (read_pid(argv[i] + 17, &pid) == 0)
327 protocol_print_filter(pid);
328 else
329 protocol_print_filter_name(argv[i] + 17);
330 exit(0);
331 }
323#endif 332#endif
324 else if (strncmp(argv[i], "--caps.print=", 13) == 0) { 333 else if (strncmp(argv[i], "--caps.print=", 13) == 0) {
325 // join sandbox by pid or by name 334 // join sandbox by pid or by name
@@ -455,6 +464,8 @@ int main(int argc, char **argv) {
455 // filtering 464 // filtering
456 //************************************* 465 //*************************************
457#ifdef HAVE_SECCOMP 466#ifdef HAVE_SECCOMP
467 else if (strncmp(argv[i], "--protocol=", 11) == 0)
468 protocol_store(argv[i] + 11);
458 else if (strcmp(argv[i], "--seccomp") == 0) { 469 else if (strcmp(argv[i], "--seccomp") == 0) {
459 if (arg_seccomp) { 470 if (arg_seccomp) {
460 fprintf(stderr, "Error: seccomp already enabled\n"); 471 fprintf(stderr, "Error: seccomp already enabled\n");
@@ -468,8 +479,8 @@ int main(int argc, char **argv) {
468 exit(1); 479 exit(1);
469 } 480 }
470 arg_seccomp = 1; 481 arg_seccomp = 1;
471 arg_seccomp_list = strdup(argv[i] + 10); 482 cfg.seccomp_list = strdup(argv[i] + 10);
472 if (!arg_seccomp_list) 483 if (!cfg.seccomp_list)
473 errExit("strdup"); 484 errExit("strdup");
474 } 485 }
475 else if (strncmp(argv[i], "--seccomp.drop=", 15) == 0) { 486 else if (strncmp(argv[i], "--seccomp.drop=", 15) == 0) {
@@ -478,8 +489,8 @@ int main(int argc, char **argv) {
478 exit(1); 489 exit(1);
479 } 490 }
480 arg_seccomp = 1; 491 arg_seccomp = 1;
481 arg_seccomp_list_drop = strdup(argv[i] + 15); 492 cfg.seccomp_list_drop = strdup(argv[i] + 15);
482 if (!arg_seccomp_list_drop) 493 if (!cfg.seccomp_list_drop)
483 errExit("strdup"); 494 errExit("strdup");
484 } 495 }
485 else if (strncmp(argv[i], "--seccomp.keep=", 15) == 0) { 496 else if (strncmp(argv[i], "--seccomp.keep=", 15) == 0) {
@@ -488,12 +499,12 @@ int main(int argc, char **argv) {
488 exit(1); 499 exit(1);
489 } 500 }
490 arg_seccomp = 1; 501 arg_seccomp = 1;
491 arg_seccomp_list_keep = strdup(argv[i] + 15); 502 cfg.seccomp_list_keep = strdup(argv[i] + 15);
492 if (!arg_seccomp_list_keep) 503 if (!cfg.seccomp_list_keep)
493 errExit("strdup"); 504 errExit("strdup");
494 } 505 }
495 else if (strncmp(argv[i], "--seccomp.e", 11) == 0 && strchr(argv[i], '=')) { 506 else if (strncmp(argv[i], "--seccomp.e", 11) == 0 && strchr(argv[i], '=')) {
496 if (arg_seccomp && !arg_seccomp_list_errno) { 507 if (arg_seccomp && !cfg.seccomp_list_errno) {
497 fprintf(stderr, "Error: seccomp already enabled\n"); 508 fprintf(stderr, "Error: seccomp already enabled\n");
498 exit(1); 509 exit(1);
499 } 510 }
@@ -506,17 +517,17 @@ int main(int argc, char **argv) {
506 exit(1); 517 exit(1);
507 } 518 }
508 519
509 if (!arg_seccomp_list_errno) 520 if (!cfg.seccomp_list_errno)
510 arg_seccomp_list_errno = calloc(highest_errno+1, sizeof(arg_seccomp_list_errno[0])); 521 cfg.seccomp_list_errno = calloc(highest_errno+1, sizeof(cfg.seccomp_list_errno[0]));
511 522
512 if (arg_seccomp_list_errno[nr]) { 523 if (cfg.seccomp_list_errno[nr]) {
513 fprintf(stderr, "Error: errno %s already configured\n", errnoname); 524 fprintf(stderr, "Error: errno %s already configured\n", errnoname);
514 free(errnoname); 525 free(errnoname);
515 exit(1); 526 exit(1);
516 } 527 }
517 arg_seccomp = 1; 528 arg_seccomp = 1;
518 arg_seccomp_list_errno[nr] = strdup(eq+1); 529 cfg.seccomp_list_errno[nr] = strdup(eq+1);
519 if (!arg_seccomp_list_errno[nr]) 530 if (!cfg.seccomp_list_errno[nr])
520 errExit("strdup"); 531 errExit("strdup");
521 free(errnoname); 532 free(errnoname);
522 } 533 }
@@ -1393,10 +1404,10 @@ int main(int argc, char **argv) {
1393 1404
1394 // free globals 1405 // free globals
1395#ifdef HAVE_SECCOMP 1406#ifdef HAVE_SECCOMP
1396 if (arg_seccomp_list_errno) { 1407 if (cfg.seccomp_list_errno) {
1397 for (i = 0; i < highest_errno; i++) 1408 for (i = 0; i < highest_errno; i++)
1398 free(arg_seccomp_list_errno[i]); 1409 free(cfg.seccomp_list_errno[i]);
1399 free(arg_seccomp_list_errno); 1410 free(cfg.seccomp_list_errno);
1400 } 1411 }
1401#endif 1412#endif
1402 1413
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 3edeabee9..1fadab1fa 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -160,8 +160,8 @@ int profile_check_line(char *ptr, int lineno) {
160 if (strncmp(ptr, "seccomp ", 8) == 0) { 160 if (strncmp(ptr, "seccomp ", 8) == 0) {
161 arg_seccomp = 1; 161 arg_seccomp = 1;
162#ifdef HAVE_SECCOMP 162#ifdef HAVE_SECCOMP
163 arg_seccomp_list = strdup(ptr + 8); 163 cfg.seccomp_list = strdup(ptr + 8);
164 if (!arg_seccomp_list) 164 if (!cfg.seccomp_list)
165 errExit("strdup"); 165 errExit("strdup");
166#endif 166#endif
167 return 0; 167 return 0;
@@ -171,8 +171,8 @@ int profile_check_line(char *ptr, int lineno) {
171 if (strncmp(ptr, "seccomp.drop ", 13) == 0) { 171 if (strncmp(ptr, "seccomp.drop ", 13) == 0) {
172 arg_seccomp = 1; 172 arg_seccomp = 1;
173#ifdef HAVE_SECCOMP 173#ifdef HAVE_SECCOMP
174 arg_seccomp_list_drop = strdup(ptr + 13); 174 cfg.seccomp_list_drop = strdup(ptr + 13);
175 if (!arg_seccomp_list_drop) 175 if (!cfg.seccomp_list_drop)
176 errExit("strdup"); 176 errExit("strdup");
177#endif 177#endif
178 return 0; 178 return 0;
@@ -182,8 +182,8 @@ int profile_check_line(char *ptr, int lineno) {
182 if (strncmp(ptr, "seccomp.keep ", 13) == 0) { 182 if (strncmp(ptr, "seccomp.keep ", 13) == 0) {
183 arg_seccomp = 1; 183 arg_seccomp = 1;
184#ifdef HAVE_SECCOMP 184#ifdef HAVE_SECCOMP
185 arg_seccomp_list_keep= strdup(ptr + 13); 185 cfg.seccomp_list_keep= strdup(ptr + 13);
186 if (!arg_seccomp_list_keep) 186 if (!cfg.seccomp_list_keep)
187 errExit("strdup"); 187 errExit("strdup");
188#endif 188#endif
189 return 0; 189 return 0;
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c
new file mode 100644
index 000000000..098661339
--- /dev/null
+++ b/src/firejail/protocol.c
@@ -0,0 +1,240 @@
1/*
2 * Copyright (C) 2014, 2015 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#ifdef HAVE_SECCOMP
22#include "firejail.h"
23#include "seccomp.h"
24#include <sys/types.h>
25#include <sys/socket.h>
26
27static char *protocol[] = {
28 "unix",
29 "inet",
30 "inet6",
31 "netlink",
32 "packet",
33 NULL
34};
35
36static struct sock_filter protocol_filter_command[] = {
37 WHITELIST(AF_UNIX),
38 WHITELIST(AF_INET),
39 WHITELIST(AF_INET6),
40 WHITELIST(AF_NETLINK),
41 WHITELIST(AF_PACKET)
42};
43// Note: protocol[] and protocol_filter_command are synchronized
44
45// command length
46struct sock_filter whitelist[] = {
47 WHITELIST(AF_UNIX)
48};
49unsigned whitelist_len = sizeof(whitelist) / sizeof(struct sock_filter);
50
51
52
53static int is_protocol(const char *p) {
54 int i = 0;
55 while (protocol[i] != NULL) {
56 if (strcmp(protocol[i], p) == 0)
57 return 1;
58 i++;
59 }
60
61 return 0;
62}
63
64static struct sock_filter *find_protocol_domain(const char *p) {
65 int i = 0;
66 while (protocol[i] != NULL) {
67 if (strcmp(protocol[i], p) == 0)
68 return &protocol_filter_command[i * whitelist_len];
69 i++;
70 }
71
72 return NULL;
73}
74
75// --debug-protocols
76void protocol_list(void) {
77 int i = 0;
78 while (protocol[i] != NULL) {
79 printf("%s, ", protocol[i]);
80 i++;
81 }
82 printf("\n");
83}
84
85// --protocol.print
86void protocol_print_filter_name(const char *name) {
87 (void) name;
88//todo
89}
90
91// --protocol.print
92void protocol_print_filter(pid_t pid) {
93 (void) pid;
94//todo
95}
96
97// check protocol list and store it in cfg structure
98void protocol_store(const char *prlist) {
99 assert(prlist);
100
101 // temporary list
102 char *tmplist = strdup(prlist);
103 if (!tmplist)
104 errExit("strdup");
105
106 // check list
107 char *token = strtok(tmplist, ",");
108 if (!token)
109 goto errout;
110
111 while (token) {
112 if (!is_protocol(token))
113 goto errout;
114 token = strtok(NULL, ",");
115 }
116 free(tmplist);
117
118 // store list
119 cfg.protocol = strdup(prlist);
120 if (!cfg.protocol)
121 errExit("strdup");
122 return;
123
124errout:
125 fprintf(stderr, "Error: invalid protocol list\n");
126 exit(1);
127}
128
129// install protocol filter
130void protocol_filter(void) {
131 assert(cfg.protocol);
132
133 // build the filter
134
135 struct sock_filter filter[32]; // big enough
136 memset(&filter[0], 0, sizeof(filter));
137 uint8_t *ptr = (uint8_t *) &filter[0];
138
139 // header
140 struct sock_filter filter_start[] = {
141 VALIDATE_ARCHITECTURE,
142 EXAMINE_SYSCALL,
143 ONLY(SYS_socket),
144 EXAMINE_ARGUMENT(0)
145 };
146 memcpy(ptr, &filter_start[0], sizeof(filter_start));
147 ptr += sizeof(filter_start);
148
149#if 0
150printf("entries %u\n", (unsigned) (sizeof(filter_start) / sizeof(struct sock_filter)));
151{
152 unsigned j;
153 unsigned char *ptr2 = (unsigned char *) &filter[0];
154 for (j = 0; j < sizeof(filter); j++, ptr2++) {
155 if ((j % (sizeof(struct sock_filter))) == 0)
156 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
157 printf("%02x, ", (*ptr2) & 0xff);
158 }
159 printf("\n");
160}
161#endif
162
163printf("whitelist_len %u, struct sock_filter len %u\n", whitelist_len, (unsigned) sizeof(struct sock_filter));
164
165 // parse list and add commands
166 char *tmplist = strdup(cfg.protocol);
167 if (!tmplist)
168 errExit("strdup");
169 char *token = strtok(tmplist, ",");
170 if (!token)
171 errExit("strtok");
172
173 while (token) {
174 struct sock_filter *domain = find_protocol_domain(token);
175 assert(domain);
176 memcpy(ptr, domain, whitelist_len * sizeof(struct sock_filter));
177 ptr += whitelist_len * sizeof(struct sock_filter);
178 token = strtok(NULL, ",");
179
180#if 0
181printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
182{
183 unsigned j;
184 unsigned char *ptr2 = (unsigned char *) &filter[0];
185 for (j = 0; j < sizeof(filter); j++, ptr2++) {
186 if ((j % (sizeof(struct sock_filter))) == 0)
187 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
188 printf("%02x, ", (*ptr2) & 0xff);
189 }
190 printf("\n");
191}
192#endif
193
194
195 }
196 free(tmplist);
197
198 // add end of filter
199 struct sock_filter filter_end[] = {
200 RETURN_ERRNO(ENOTSUP)
201 };
202 memcpy(ptr, &filter_end[0], sizeof(filter_end));
203 ptr += sizeof(filter_end);
204
205#if 0
206printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
207{
208 unsigned j;
209 unsigned char *ptr2 = (unsigned char *) &filter[0];
210 for (j = 0; j < sizeof(filter); j++, ptr2++) {
211 if ((j % (sizeof(struct sock_filter))) == 0)
212 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
213 printf("%02x, ", (*ptr2) & 0xff);
214 }
215 printf("\n");
216}
217#endif
218
219 // install filter
220 unsigned short entries = (unsigned short) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter);
221 struct sock_fprog prog = {
222 .len = entries,
223 .filter = filter,
224 };
225
226 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
227 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
228 return;
229 }
230 else if (arg_debug) {
231 printf("seccomp protocol filter enabled\n");
232 }
233
234#if defined(__x86_64__)
235
236#endif
237
238}
239
240#endif
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 3c5a176e6..427b3fc09 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -190,13 +190,13 @@ int sandbox(void* sandbox_arg) {
190 // force default seccomp inside the chroot, no keep or drop list 190 // force default seccomp inside the chroot, no keep or drop list
191 // the list build on top of the default drop list is kept intact 191 // the list build on top of the default drop list is kept intact
192 arg_seccomp = 1; 192 arg_seccomp = 1;
193 if (arg_seccomp_list_drop) { 193 if (cfg.seccomp_list_drop) {
194 free(arg_seccomp_list_drop); 194 free(cfg.seccomp_list_drop);
195 arg_seccomp_list_drop = NULL; 195 cfg.seccomp_list_drop = NULL;
196 } 196 }
197 if (arg_seccomp_list_keep) { 197 if (cfg.seccomp_list_keep) {
198 free(arg_seccomp_list_keep); 198 free(cfg.seccomp_list_keep);
199 arg_seccomp_list_keep = NULL; 199 cfg.seccomp_list_keep = NULL;
200 } 200 }
201 201
202 // disable all capabilities 202 // disable all capabilities
@@ -426,11 +426,16 @@ int sandbox(void* sandbox_arg) {
426 426
427 // set seccomp 427 // set seccomp
428#ifdef HAVE_SECCOMP 428#ifdef HAVE_SECCOMP
429 // install protocol filter
430 if (cfg.protocol) {
431 protocol_filter();
432 }
433
429 // if a keep list is available, disregard the drop list 434 // if a keep list is available, disregard the drop list
430 if (arg_seccomp == 1) { 435 if (arg_seccomp == 1) {
431 if (arg_seccomp_list_keep) 436 if (cfg.seccomp_list_keep)
432 seccomp_filter_keep(); // this will also save the fmyilter to MNT_DIR/seccomp file 437 seccomp_filter_keep(); // this will also save the fmyilter to MNT_DIR/seccomp file
433 else if (arg_seccomp_list_errno) 438 else if (cfg.seccomp_list_errno)
434 seccomp_filter_errno(); // this will also save the filter to MNT_DIR/seccomp file 439 seccomp_filter_errno(); // this will also save the filter to MNT_DIR/seccomp file
435 else 440 else
436 seccomp_filter_drop(); // this will also save the filter to MNT_DIR/seccomp file 441 seccomp_filter_drop(); // this will also save the filter to MNT_DIR/seccomp file
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index 29c87b18b..dd7b8d344 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -343,7 +343,7 @@ int seccomp_filter_drop(void) {
343 filter_init(); 343 filter_init();
344 344
345 // default seccomp 345 // default seccomp
346 if (arg_seccomp_list_drop == NULL) { 346 if (cfg.seccomp_list_drop == NULL) {
347#ifdef SYS_mount 347#ifdef SYS_mount
348 filter_add_blacklist(SYS_mount, 0); 348 filter_add_blacklist(SYS_mount, 0);
349#endif 349#endif
@@ -507,15 +507,15 @@ int seccomp_filter_drop(void) {
507 } 507 }
508 508
509 // default seccomp filter with additional drop list 509 // default seccomp filter with additional drop list
510 if (arg_seccomp_list && arg_seccomp_list_drop == NULL) { 510 if (cfg.seccomp_list && cfg.seccomp_list_drop == NULL) {
511 if (syscall_check_list(arg_seccomp_list, filter_add_blacklist, 0)) { 511 if (syscall_check_list(cfg.seccomp_list, filter_add_blacklist, 0)) {
512 fprintf(stderr, "Error: cannot load seccomp filter\n"); 512 fprintf(stderr, "Error: cannot load seccomp filter\n");
513 exit(1); 513 exit(1);
514 } 514 }
515 } 515 }
516 // drop list 516 // drop list
517 else if (arg_seccomp_list == NULL && arg_seccomp_list_drop) { 517 else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) {
518 if (syscall_check_list(arg_seccomp_list_drop, filter_add_blacklist, 0)) { 518 if (syscall_check_list(cfg.seccomp_list_drop, filter_add_blacklist, 0)) {
519 fprintf(stderr, "Error: cannot load seccomp filter\n"); 519 fprintf(stderr, "Error: cannot load seccomp filter\n");
520 exit(1); 520 exit(1);
521 } 521 }
@@ -558,8 +558,8 @@ int seccomp_filter_keep(void) {
558 filter_add_whitelist(SYS_dup, 0); 558 filter_add_whitelist(SYS_dup, 0);
559 559
560 // apply keep list 560 // apply keep list
561 if (arg_seccomp_list_keep) { 561 if (cfg.seccomp_list_keep) {
562 if (syscall_check_list(arg_seccomp_list_keep, filter_add_whitelist, 0)) { 562 if (syscall_check_list(cfg.seccomp_list_keep, filter_add_whitelist, 0)) {
563 fprintf(stderr, "Error: cannot load seccomp filter\n"); 563 fprintf(stderr, "Error: cannot load seccomp filter\n");
564 exit(1); 564 exit(1);
565 } 565 }
@@ -599,8 +599,8 @@ int seccomp_filter_errno(void) {
599 // apply errno list 599 // apply errno list
600 600
601 for (i = 0; i < higest_errno; i++) { 601 for (i = 0; i < higest_errno; i++) {
602 if (arg_seccomp_list_errno[i]) { 602 if (cfg.seccomp_list_errno[i]) {
603 if (syscall_check_list(arg_seccomp_list_errno[i], filter_add_errno, i)) { 603 if (syscall_check_list(cfg.seccomp_list_errno[i], filter_add_errno, i)) {
604 fprintf(stderr, "Error: cannot load seccomp filter\n"); 604 fprintf(stderr, "Error: cannot load seccomp filter\n");
605 exit(1); 605 exit(1);
606 } 606 }
diff --git a/src/firejail/seccomp.h b/src/firejail/seccomp.h
index 19684d4a9..b83fe87ce 100644
--- a/src/firejail/seccomp.h
+++ b/src/firejail/seccomp.h
@@ -92,15 +92,26 @@ struct seccomp_data {
92# define ARCH_NR 0 92# define ARCH_NR 0
93#endif 93#endif
94 94
95
96#define VALIDATE_ARCHITECTURE \ 95#define VALIDATE_ARCHITECTURE \
97 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ 96 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \
98 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ 97 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \
99 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) 98 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
100 99
100#define VALIDATE_ARCHITECTURE_32_64 \
101 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \
102 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \
103 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
104
101#define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 105#define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
102 (offsetof(struct seccomp_data, nr))) 106 (offsetof(struct seccomp_data, nr)))
103 107
108#define EXAMINE_ARGUMENT(nr) BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
109 (offsetof(struct seccomp_data, args[nr])))
110
111#define ONLY(syscall_nr) \
112 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 1, 0), \
113 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
114
104#define BLACKLIST(syscall_nr) \ 115#define BLACKLIST(syscall_nr) \
105 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ 116 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \
106 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) 117 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
@@ -116,6 +127,9 @@ struct seccomp_data {
116#define RETURN_ALLOW \ 127#define RETURN_ALLOW \
117 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) 128 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
118 129
130#define RETURN_ERRNO(nr) \
131 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr)
132
119#define KILL_PROCESS \ 133#define KILL_PROCESS \
120 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) 134 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
121 135
diff --git a/src/tools/syscall_test b/src/tools/syscall_test
new file mode 100755
index 000000000..21db21ae0
--- /dev/null
+++ b/src/tools/syscall_test
Binary files differ
diff --git a/src/tools/syscall_test.c b/src/tools/syscall_test.c
new file mode 100644
index 000000000..47c27978b
--- /dev/null
+++ b/src/tools/syscall_test.c
@@ -0,0 +1,70 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include <unistd.h>
4#include <sys/types.h>
5#include <sys/socket.h>
6#include <linux/netlink.h>
7#include <net/ethernet.h>
8
9int main(int argc, char **argv) {
10 if (argc != 2) {
11 printf("Usage: test [sleep|socket|mkdir]\n");
12 return 1;
13 }
14
15 if (strcmp(argv[1], "sleep") == 0) {
16 printf("before sleep\n");
17 sleep(1);
18 printf("after sleep\n");
19 }
20 else if (strcmp(argv[1], "socket") == 0) {
21 int sock;
22
23 printf("testing socket AF_INET\n");
24 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
25 perror("socket");
26 }
27 else
28 close(sock);
29
30 printf("testing socket AF_INET6\n");
31 if ((sock = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
32 perror("socket");
33 }
34 else
35 close(sock);
36
37 printf("testing socket AF_NETLINK\n");
38 if ((sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
39 perror("socket");
40 }
41 else
42 close(sock);
43
44 printf("testing socket AF_UNIX\n");
45 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
46 perror("socket");
47 }
48 else
49 close(sock);
50
51 // root needed to be able to handle this
52 printf("testing socket AF_PACKETX\n");
53 if ((sock = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP))) < 0) {
54 perror("socket");
55 }
56 else
57 close(sock);
58 printf("after socket\n");
59 }
60 else if (strcmp(argv[1], "mkdir") == 0) {
61 printf("before mkdir\n");
62 mkdir("tmp", 0777);
63 printf("after mkdir\n");
64 }
65 else {
66 fprintf(stderr, "Error: invalid argument\n");
67 return 1;
68 }
69 return 0;
70}
diff --git a/src/tools/syscall_test32 b/src/tools/syscall_test32
new file mode 100755
index 000000000..5d027f5dd
--- /dev/null
+++ b/src/tools/syscall_test32
Binary files differ