diff options
author | netblue30 <netblue30@yahoo.com> | 2015-10-28 22:02:45 -0400 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2015-10-28 22:02:45 -0400 |
commit | b12c846f58e7c78b81b4923aa4191536fe6ad2b8 (patch) | |
tree | c518c8e807bb7723cdce3815ecbacc6a826a38c1 | |
parent | enable --protocol by default in profiles (diff) | |
download | firejail-b12c846f58e7c78b81b4923aa4191536fe6ad2b8.tar.gz firejail-b12c846f58e7c78b81b4923aa4191536fe6ad2b8.tar.zst firejail-b12c846f58e7c78b81b4923aa4191536fe6ad2b8.zip |
dual i386/amd64 seccomp support for --seccomp option
-rw-r--r-- | src/firejail/protocol.c | 27 | ||||
-rw-r--r-- | src/firejail/seccomp.c | 67 | ||||
-rw-r--r-- | src/firejail/seccomp.h | 28 | ||||
-rwxr-xr-x | src/tools/syscall_test | bin | 8702 -> 9552 bytes | |||
-rw-r--r-- | src/tools/syscall_test.c | 10 | ||||
-rwxr-xr-x | src/tools/syscall_test32 | bin | 6566 -> 6868 bytes | |||
-rwxr-xr-x | test/test.sh | 3 |
7 files changed, 124 insertions, 11 deletions
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c index ba784fc2e..e71daaad8 100644 --- a/src/firejail/protocol.c +++ b/src/firejail/protocol.c | |||
@@ -18,6 +18,33 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /* | ||
22 | struct sock_filter filter[] = { | ||
23 | VALIDATE_ARCHITECTURE, | ||
24 | EXAMINE_SYSCALL, | ||
25 | ONLY(SYS_socket), | ||
26 | EXAMINE_ARGUMENT(0), // allow only AF_INET and AF_INET6, drop everything else | ||
27 | WHITELIST(AF_INET), | ||
28 | WHITELIST(AF_INET6), | ||
29 | WHITELIST(AF_PACKET), | ||
30 | RETURN_ERRNO(ENOTSUP) | ||
31 | }; | ||
32 | struct sock_fprog prog = { | ||
33 | .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), | ||
34 | .filter = filter, | ||
35 | }; | ||
36 | |||
37 | |||
38 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { | ||
39 | perror("prctl(NO_NEW_PRIVS)"); | ||
40 | return 1; | ||
41 | } | ||
42 | if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { | ||
43 | perror("prctl"); | ||
44 | return 1; | ||
45 | } | ||
46 | */ | ||
47 | |||
21 | #ifdef HAVE_SECCOMP | 48 | #ifdef HAVE_SECCOMP |
22 | #include "firejail.h" | 49 | #include "firejail.h" |
23 | #include "seccomp.h" | 50 | #include "seccomp.h" |
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 984059bf8..6ab3ae56e 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c | |||
@@ -337,6 +337,69 @@ static void read_seccomp_file(char *file_name) { | |||
337 | filter_debug(); | 337 | filter_debug(); |
338 | } | 338 | } |
339 | 339 | ||
340 | // i386t filter installed on amd64 architectures | ||
341 | void seccomp_filter_32(void) { | ||
342 | // hardcoded syscall values | ||
343 | struct sock_filter filter[] = { | ||
344 | VALIDATE_ARCHITECTURE_32, | ||
345 | EXAMINE_SYSCALL, | ||
346 | BLACKLIST(21), // mount | ||
347 | BLACKLIST(52), // umount2 | ||
348 | BLACKLIST(26), // ptrace | ||
349 | BLACKLIST(283), // kexec_load | ||
350 | BLACKLIST(342), // open_by_handle_at | ||
351 | BLACKLIST(128), // init_module | ||
352 | BLACKLIST(350), // finit_module | ||
353 | BLACKLIST(129), // delete_module | ||
354 | BLACKLIST(110), // iopl | ||
355 | BLACKLIST(101), // ioperm | ||
356 | BLACKLIST(87), // swapon | ||
357 | BLACKLIST(115), // swapoff | ||
358 | BLACKLIST(103), // syslog | ||
359 | BLACKLIST(347), // process_vm_readv | ||
360 | BLACKLIST(348), // process_vm_writev | ||
361 | BLACKLIST(135), // sysfs | ||
362 | BLACKLIST(149), // _sysctl | ||
363 | BLACKLIST(124), // adjtimex | ||
364 | BLACKLIST(343), // clock_adjtime | ||
365 | BLACKLIST(253), // lookup_dcookie | ||
366 | BLACKLIST(336), // perf_event_open | ||
367 | BLACKLIST(338), // fanotify_init | ||
368 | BLACKLIST(349), // kcmp | ||
369 | BLACKLIST(286), // add_key | ||
370 | BLACKLIST(287), // request_key | ||
371 | BLACKLIST(288), // keyctl | ||
372 | BLACKLIST(86), // uselib | ||
373 | BLACKLIST(51), // acct | ||
374 | BLACKLIST(123), // modify_ldt | ||
375 | BLACKLIST(217), // pivot_root | ||
376 | BLACKLIST(245), // io_setup | ||
377 | BLACKLIST(246), // io_destroy | ||
378 | BLACKLIST(247), // io_getevents | ||
379 | BLACKLIST(248), // io_submit | ||
380 | BLACKLIST(249), // io_cancel | ||
381 | BLACKLIST(257), // remap_file_pages | ||
382 | BLACKLIST(274), // mbind | ||
383 | BLACKLIST(275), // get_mempolicy | ||
384 | BLACKLIST(276), // set_mempolicy | ||
385 | BLACKLIST(294), // migrate_pages | ||
386 | BLACKLIST(317), // move_pages | ||
387 | BLACKLIST(316), // vmsplice | ||
388 | RETURN_ALLOW | ||
389 | }; | ||
390 | |||
391 | struct sock_fprog prog = { | ||
392 | .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), | ||
393 | .filter = filter, | ||
394 | }; | ||
395 | |||
396 | if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { | ||
397 | ; | ||
398 | } | ||
399 | else if (arg_debug) { | ||
400 | printf("dual i386/amd64 seccomp filter\n"); | ||
401 | } | ||
402 | } | ||
340 | 403 | ||
341 | // drop filter for seccomp option | 404 | // drop filter for seccomp option |
342 | int seccomp_filter_drop(void) { | 405 | int seccomp_filter_drop(void) { |
@@ -344,6 +407,10 @@ int seccomp_filter_drop(void) { | |||
344 | 407 | ||
345 | // default seccomp | 408 | // default seccomp |
346 | if (cfg.seccomp_list_drop == NULL) { | 409 | if (cfg.seccomp_list_drop == NULL) { |
410 | #if defined(__x86_64__) | ||
411 | seccomp_filter_32(); | ||
412 | #endif | ||
413 | |||
347 | #ifdef SYS_mount | 414 | #ifdef SYS_mount |
348 | filter_add_blacklist(SYS_mount, 0); | 415 | filter_add_blacklist(SYS_mount, 0); |
349 | #endif | 416 | #endif |
diff --git a/src/firejail/seccomp.h b/src/firejail/seccomp.h index b83fe87ce..6fbc6a590 100644 --- a/src/firejail/seccomp.h +++ b/src/firejail/seccomp.h | |||
@@ -29,26 +29,34 @@ | |||
29 | BLACKLIST(SYS_kexec_load), // loading a different kernel | 29 | BLACKLIST(SYS_kexec_load), // loading a different kernel |
30 | BLACKLIST(SYS_open_by_handle_at), // open by handle | 30 | BLACKLIST(SYS_open_by_handle_at), // open by handle |
31 | BLACKLIST(SYS_init_module), // kernel module handling | 31 | BLACKLIST(SYS_init_module), // kernel module handling |
32 | #ifdef SYS_finit_module // introduced in 2013 | ||
33 | BLACKLIST(SYS_finit_module), | 32 | BLACKLIST(SYS_finit_module), |
34 | #endif | ||
35 | BLACKLIST(SYS_delete_module), | 33 | BLACKLIST(SYS_delete_module), |
36 | BLACKLIST(SYS_iopl), // io permisions | 34 | BLACKLIST(SYS_iopl), // io permisions |
37 | #ifdef SYS_ioperm | ||
38 | BLACKLIST(SYS_ioperm), | 35 | BLACKLIST(SYS_ioperm), |
39 | #endif | ||
40 | SYS_iopl | ||
41 | BLACKLIST(SYS_iopl), // io permisions | 36 | BLACKLIST(SYS_iopl), // io permisions |
42 | #endif | ||
43 | #ifdef SYS_ni_syscall), // new io permisions call on arm devices | ||
44 | BLACKLIST(SYS_ni_syscall), | 37 | BLACKLIST(SYS_ni_syscall), |
45 | #endif | ||
46 | BLACKLIST(SYS_swapon), // swap on/off | 38 | BLACKLIST(SYS_swapon), // swap on/off |
47 | BLACKLIST(SYS_swapoff), | 39 | BLACKLIST(SYS_swapoff), |
48 | BLACKLIST(SYS_syslog), // kernel printk control | 40 | BLACKLIST(SYS_syslog), // kernel printk control |
49 | RETURN_ALLOW | 41 | RETURN_ALLOW |
50 | }; | 42 | }; |
43 | |||
44 | struct sock_fprog prog = { | ||
45 | .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), | ||
46 | .filter = filter, | ||
47 | }; | ||
48 | |||
49 | |||
50 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { | ||
51 | perror("prctl(NO_NEW_PRIVS)"); | ||
52 | return 1; | ||
53 | } | ||
54 | if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { | ||
55 | perror("prctl"); | ||
56 | return 1; | ||
57 | } | ||
51 | */ | 58 | */ |
59 | |||
52 | #ifndef SECCOMP_H | 60 | #ifndef SECCOMP_H |
53 | #define SECCOMP_H | 61 | #define SECCOMP_H |
54 | #include <errno.h> | 62 | #include <errno.h> |
@@ -97,9 +105,9 @@ struct seccomp_data { | |||
97 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ | 105 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ |
98 | BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) | 106 | BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) |
99 | 107 | ||
100 | #define VALIDATE_ARCHITECTURE_32_64 \ | 108 | #define VALIDATE_ARCHITECTURE_32 \ |
101 | BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ | 109 | 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), \ | 110 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, AUDIT_ARCH_I386, 1, 0), \ |
103 | BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) | 111 | BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) |
104 | 112 | ||
105 | #define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ | 113 | #define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ |
diff --git a/src/tools/syscall_test b/src/tools/syscall_test index 21db21ae0..bf29c5b99 100755 --- a/src/tools/syscall_test +++ b/src/tools/syscall_test | |||
Binary files differ | |||
diff --git a/src/tools/syscall_test.c b/src/tools/syscall_test.c index 47c27978b..b3f43c755 100644 --- a/src/tools/syscall_test.c +++ b/src/tools/syscall_test.c | |||
@@ -5,10 +5,11 @@ | |||
5 | #include <sys/socket.h> | 5 | #include <sys/socket.h> |
6 | #include <linux/netlink.h> | 6 | #include <linux/netlink.h> |
7 | #include <net/ethernet.h> | 7 | #include <net/ethernet.h> |
8 | #include <sys/mount.h> | ||
8 | 9 | ||
9 | int main(int argc, char **argv) { | 10 | int main(int argc, char **argv) { |
10 | if (argc != 2) { | 11 | if (argc != 2) { |
11 | printf("Usage: test [sleep|socket|mkdir]\n"); | 12 | printf("Usage: test [sleep|socket|mkdir|mount]\n"); |
12 | return 1; | 13 | return 1; |
13 | } | 14 | } |
14 | 15 | ||
@@ -62,6 +63,13 @@ int main(int argc, char **argv) { | |||
62 | mkdir("tmp", 0777); | 63 | mkdir("tmp", 0777); |
63 | printf("after mkdir\n"); | 64 | printf("after mkdir\n"); |
64 | } | 65 | } |
66 | else if (strcmp(argv[1], "mount") == 0) { | ||
67 | printf("before mount\n"); | ||
68 | if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) { | ||
69 | perror("mount"); | ||
70 | } | ||
71 | printf("after mount\n"); | ||
72 | } | ||
65 | else { | 73 | else { |
66 | fprintf(stderr, "Error: invalid argument\n"); | 74 | fprintf(stderr, "Error: invalid argument\n"); |
67 | return 1; | 75 | return 1; |
diff --git a/src/tools/syscall_test32 b/src/tools/syscall_test32 index 5d027f5dd..8d72f58c4 100755 --- a/src/tools/syscall_test32 +++ b/src/tools/syscall_test32 | |||
Binary files differ | |||
diff --git a/test/test.sh b/test/test.sh index 8e673911e..61e5cce35 100755 --- a/test/test.sh +++ b/test/test.sh | |||
@@ -348,6 +348,9 @@ echo "TESTING: seccomp empty" | |||
348 | echo "TESTING: seccomp bad empty" | 348 | echo "TESTING: seccomp bad empty" |
349 | ./seccomp-bad-empty.exp | 349 | ./seccomp-bad-empty.exp |
350 | 350 | ||
351 | echo "TESTING: seccomp dual filter" | ||
352 | ./seccomp-dualfilter.exp | ||
353 | |||
351 | echo "TESTING: read/write /var/tmp" | 354 | echo "TESTING: read/write /var/tmp" |
352 | ./fs_var_tmp.exp | 355 | ./fs_var_tmp.exp |
353 | 356 | ||