aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/seccomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/seccomp.c')
-rw-r--r--src/firejail/seccomp.c144
1 files changed, 110 insertions, 34 deletions
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index 47988dbf4..4f6b7b326 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -109,6 +109,10 @@ struct seccomp_data {
109 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ 109 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \
110 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) 110 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
111 111
112#define ERRNO(syscall_nr, nr) \
113 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \
114 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr)
115
112#define RETURN_ALLOW \ 116#define RETURN_ALLOW \
113 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) 117 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
114 118
@@ -157,6 +161,11 @@ void filter_debug(void) {
157 printf(" BLACKLIST %d %s\n", *nr, syscall_find_nr(*nr)); 161 printf(" BLACKLIST %d %s\n", *nr, syscall_find_nr(*nr));
158 i += 2; 162 i += 2;
159 } 163 }
164 else if (*ptr == 0x15 && *(ptr +14) == 0x5 && *(ptr + 15) == 0) {
165 int err = *(ptr + 13) << 8 | *(ptr + 12);
166 printf(" ERRNO %d %s %d %s\n", *nr, syscall_find_nr(*nr), err, errno_find_nr(err));
167 i += 2;
168 }
160 else if (*ptr == 0x06 && *(ptr +6) == 0 && *(ptr + 7) == 0 ) { 169 else if (*ptr == 0x06 && *(ptr +6) == 0 && *(ptr + 7) == 0 ) {
161 printf(" KILL_PROCESS\n"); 170 printf(" KILL_PROCESS\n");
162 i++; 171 i++;
@@ -216,7 +225,7 @@ static void filter_realloc(void) {
216 sfilter_alloc_size += SECSIZE; 225 sfilter_alloc_size += SECSIZE;
217} 226}
218 227
219static void filter_add_whitelist(int syscall) { 228static void filter_add_whitelist(int syscall, int arg) {
220 assert(sfilter); 229 assert(sfilter);
221 assert(sfilter_alloc_size); 230 assert(sfilter_alloc_size);
222 assert(sfilter_index); 231 assert(sfilter_index);
@@ -242,7 +251,7 @@ static void filter_add_whitelist(int syscall) {
242 sfilter_index += sizeof(filter) / sizeof(struct sock_filter); 251 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
243} 252}
244 253
245static void filter_add_blacklist(int syscall) { 254static void filter_add_blacklist(int syscall, int arg) {
246 assert(sfilter); 255 assert(sfilter);
247 assert(sfilter_alloc_size); 256 assert(sfilter_alloc_size);
248 assert(sfilter_index); 257 assert(sfilter_index);
@@ -268,6 +277,32 @@ static void filter_add_blacklist(int syscall) {
268 sfilter_index += sizeof(filter) / sizeof(struct sock_filter); 277 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
269} 278}
270 279
280static void filter_add_errno(int syscall, int arg) {
281 assert(sfilter);
282 assert(sfilter_alloc_size);
283 assert(sfilter_index);
284// if (arg_debug)
285// printf("Errno syscall %d %d %s\n", syscall, arg, syscall_find_nr(syscall));
286
287 if ((sfilter_index + 2) > sfilter_alloc_size)
288 filter_realloc();
289
290 struct sock_filter filter[] = {
291 ERRNO(syscall, arg)
292 };
293#if 0
294{
295 int i;
296 unsigned char *ptr = (unsigned char *) &filter[0];
297 for (i = 0; i < sizeof(filter); i++, ptr++)
298 printf("%x, ", (*ptr) & 0xff);
299 printf("\n");
300}
301#endif
302 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
303 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
304}
305
271static void filter_end_blacklist(void) { 306static void filter_end_blacklist(void) {
272 assert(sfilter); 307 assert(sfilter);
273 assert(sfilter_alloc_size); 308 assert(sfilter_alloc_size);
@@ -405,96 +440,96 @@ int seccomp_filter_drop(void) {
405 // default seccomp 440 // default seccomp
406 if (arg_seccomp_list_drop == NULL) { 441 if (arg_seccomp_list_drop == NULL) {
407#ifdef SYS_mount 442#ifdef SYS_mount
408 filter_add_blacklist(SYS_mount); 443 filter_add_blacklist(SYS_mount, 0);
409#endif 444#endif
410#ifdef SYS_umount2 445#ifdef SYS_umount2
411 filter_add_blacklist(SYS_umount2); 446 filter_add_blacklist(SYS_umount2, 0);
412#endif 447#endif
413#ifdef SYS_ptrace 448#ifdef SYS_ptrace
414 filter_add_blacklist(SYS_ptrace); 449 filter_add_blacklist(SYS_ptrace, 0);
415#endif 450#endif
416#ifdef SYS_kexec_load 451#ifdef SYS_kexec_load
417 filter_add_blacklist(SYS_kexec_load); 452 filter_add_blacklist(SYS_kexec_load, 0);
418#endif 453#endif
419#ifdef SYS_open_by_handle_at 454#ifdef SYS_open_by_handle_at
420 filter_add_blacklist(SYS_open_by_handle_at); 455 filter_add_blacklist(SYS_open_by_handle_at, 0);
421#endif 456#endif
422#ifdef SYS_init_module 457#ifdef SYS_init_module
423 filter_add_blacklist(SYS_init_module); 458 filter_add_blacklist(SYS_init_module, 0);
424#endif 459#endif
425#ifdef SYS_finit_module // introduced in 2013 460#ifdef SYS_finit_module // introduced in 2013
426 filter_add_blacklist(SYS_finit_module); 461 filter_add_blacklist(SYS_finit_module, 0);
427#endif 462#endif
428#ifdef SYS_delete_module 463#ifdef SYS_delete_module
429 filter_add_blacklist(SYS_delete_module); 464 filter_add_blacklist(SYS_delete_module, 0);
430#endif 465#endif
431#ifdef SYS_iopl 466#ifdef SYS_iopl
432 filter_add_blacklist(SYS_iopl); 467 filter_add_blacklist(SYS_iopl, 0);
433#endif 468#endif
434#ifdef SYS_ioperm 469#ifdef SYS_ioperm
435 filter_add_blacklist(SYS_ioperm); 470 filter_add_blacklist(SYS_ioperm, 0);
436#endif 471#endif
437#ifdef SYS_ni_syscall // new io permisions call on arm devices 472#ifdef SYS_ni_syscall // new io permisions call on arm devices
438 filter_add_blacklist(SYS_ni_syscall); 473 filter_add_blacklist(SYS_ni_syscall, 0);
439#endif 474#endif
440#ifdef SYS_swapon 475#ifdef SYS_swapon
441 filter_add_blacklist(SYS_swapon); 476 filter_add_blacklist(SYS_swapon, 0);
442#endif 477#endif
443#ifdef SYS_swapoff 478#ifdef SYS_swapoff
444 filter_add_blacklist(SYS_swapoff); 479 filter_add_blacklist(SYS_swapoff, 0);
445#endif 480#endif
446#ifdef SYS_syslog 481#ifdef SYS_syslog
447 filter_add_blacklist(SYS_syslog); 482 filter_add_blacklist(SYS_syslog, 0);
448#endif 483#endif
449#ifdef SYS_process_vm_readv 484#ifdef SYS_process_vm_readv
450 filter_add_blacklist(SYS_process_vm_readv); 485 filter_add_blacklist(SYS_process_vm_readv, 0);
451#endif 486#endif
452#ifdef SYS_process_vm_writev 487#ifdef SYS_process_vm_writev
453 filter_add_blacklist(SYS_process_vm_writev); 488 filter_add_blacklist(SYS_process_vm_writev, 0);
454#endif 489#endif
455 490
456// mknod removed in 0.9.29 491// mknod removed in 0.9.29
457//#ifdef SYS_mknod 492//#ifdef SYS_mknod
458// filter_add_blacklist(SYS_mknod); 493// filter_add_blacklist(SYS_mknod, 0);
459//#endif 494//#endif
460 495
461 // new syscalls in 0.9,23 496 // new syscalls in 0.9,23
462#ifdef SYS_sysfs 497#ifdef SYS_sysfs
463 filter_add_blacklist(SYS_sysfs); 498 filter_add_blacklist(SYS_sysfs, 0);
464#endif 499#endif
465#ifdef SYS__sysctl 500#ifdef SYS__sysctl
466 filter_add_blacklist(SYS__sysctl); 501 filter_add_blacklist(SYS__sysctl, 0);
467#endif 502#endif
468#ifdef SYS_adjtimex 503#ifdef SYS_adjtimex
469 filter_add_blacklist(SYS_adjtimex); 504 filter_add_blacklist(SYS_adjtimex, 0);
470#endif 505#endif
471#ifdef SYS_clock_adjtime 506#ifdef SYS_clock_adjtime
472 filter_add_blacklist(SYS_clock_adjtime); 507 filter_add_blacklist(SYS_clock_adjtime, 0);
473#endif 508#endif
474#ifdef SYS_lookup_dcookie 509#ifdef SYS_lookup_dcookie
475 filter_add_blacklist(SYS_lookup_dcookie); 510 filter_add_blacklist(SYS_lookup_dcookie, 0);
476#endif 511#endif
477#ifdef SYS_perf_event_open 512#ifdef SYS_perf_event_open
478 filter_add_blacklist(SYS_perf_event_open); 513 filter_add_blacklist(SYS_perf_event_open, 0);
479#endif 514#endif
480#ifdef SYS_fanotify_init 515#ifdef SYS_fanotify_init
481 filter_add_blacklist(SYS_fanotify_init); 516 filter_add_blacklist(SYS_fanotify_init, 0);
482#endif 517#endif
483#ifdef SYS_kcmp 518#ifdef SYS_kcmp
484 filter_add_blacklist(SYS_kcmp); 519 filter_add_blacklist(SYS_kcmp, 0);
485#endif 520#endif
486 } 521 }
487 522
488 // default seccomp filter with additional drop list 523 // default seccomp filter with additional drop list
489 if (arg_seccomp_list && arg_seccomp_list_drop == NULL) { 524 if (arg_seccomp_list && arg_seccomp_list_drop == NULL) {
490 if (syscall_check_list(arg_seccomp_list, filter_add_blacklist)) { 525 if (syscall_check_list(arg_seccomp_list, filter_add_blacklist, 0)) {
491 fprintf(stderr, "Error: cannot load seccomp filter\n"); 526 fprintf(stderr, "Error: cannot load seccomp filter\n");
492 exit(1); 527 exit(1);
493 } 528 }
494 } 529 }
495 // drop list 530 // drop list
496 else if (arg_seccomp_list == NULL && arg_seccomp_list_drop) { 531 else if (arg_seccomp_list == NULL && arg_seccomp_list_drop) {
497 if (syscall_check_list(arg_seccomp_list_drop, filter_add_blacklist)) { 532 if (syscall_check_list(arg_seccomp_list_drop, filter_add_blacklist, 0)) {
498 fprintf(stderr, "Error: cannot load seccomp filter\n"); 533 fprintf(stderr, "Error: cannot load seccomp filter\n");
499 exit(1); 534 exit(1);
500 } 535 }
@@ -531,14 +566,14 @@ int seccomp_filter_keep(void) {
531 filter_init(); 566 filter_init();
532 567
533 // these 4 syscalls are used by firejail after the seccomp filter is initialized 568 // these 4 syscalls are used by firejail after the seccomp filter is initialized
534 filter_add_whitelist(SYS_setuid); 569 filter_add_whitelist(SYS_setuid, 0);
535 filter_add_whitelist(SYS_setgid); 570 filter_add_whitelist(SYS_setgid, 0);
536 filter_add_whitelist(SYS_setgroups); 571 filter_add_whitelist(SYS_setgroups, 0);
537 filter_add_whitelist(SYS_dup); 572 filter_add_whitelist(SYS_dup, 0);
538 573
539 // apply keep list 574 // apply keep list
540 if (arg_seccomp_list_keep) { 575 if (arg_seccomp_list_keep) {
541 if (syscall_check_list(arg_seccomp_list_keep, filter_add_whitelist)) { 576 if (syscall_check_list(arg_seccomp_list_keep, filter_add_whitelist, 0)) {
542 fprintf(stderr, "Error: cannot load seccomp filter\n"); 577 fprintf(stderr, "Error: cannot load seccomp filter\n");
543 exit(1); 578 exit(1);
544 } 579 }
@@ -569,6 +604,47 @@ int seccomp_filter_keep(void) {
569 return 0; 604 return 0;
570} 605}
571 606
607// errno filter for seccomp option
608int seccomp_filter_errno(void) {
609 int i;
610 int higest_errno = errno_highest_nr();
611 filter_init();
612
613 // apply errno list
614
615 for (i = 0; i < higest_errno; i++) {
616 if (arg_seccomp_list_errno[i]) {
617 if (syscall_check_list(arg_seccomp_list_errno[i], filter_add_errno, i)) {
618 fprintf(stderr, "Error: cannot load seccomp filter\n");
619 exit(1);
620 }
621 }
622 }
623
624 filter_end_blacklist();
625 if (arg_debug)
626 filter_debug();
627
628 // save seccomp filter in /tmp/firejail/mnt/seccomp
629 // in order to use it in --join operations
630 write_seccomp_file();
631
632 struct sock_fprog prog = {
633 .len = sfilter_index,
634 .filter = sfilter,
635 };
636
637 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
638 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
639 return 1;
640 }
641 else if (arg_debug) {
642 printf("seccomp enabled\n");
643 }
644
645 return 0;
646}
647
572 648
573 649
574void seccomp_set(void) { 650void seccomp_set(void) {