// i386 filter installed on amd64 architectures void seccomp_filter_32(void) { // hardcoded syscall values struct sock_filter filter[] = { VALIDATE_ARCHITECTURE_32, EXAMINE_SYSCALL, BLACKLIST(21), // mount BLACKLIST(52), // umount2 BLACKLIST(26), // ptrace BLACKLIST(283), // kexec_load BLACKLIST(342), // open_by_handle_at BLACKLIST(128), // init_module BLACKLIST(350), // finit_module BLACKLIST(129), // delete_module BLACKLIST(110), // iopl BLACKLIST(101), // ioperm BLACKLIST(87), // swapon BLACKLIST(115), // swapoff BLACKLIST(103), // syslog BLACKLIST(347), // process_vm_readv BLACKLIST(348), // process_vm_writev BLACKLIST(135), // sysfs BLACKLIST(149), // _sysctl BLACKLIST(124), // adjtimex BLACKLIST(343), // clock_adjtime BLACKLIST(253), // lookup_dcookie BLACKLIST(336), // perf_event_open BLACKLIST(338), // fanotify_init BLACKLIST(349), // kcmp BLACKLIST(286), // add_key BLACKLIST(287), // request_key BLACKLIST(288), // keyctl BLACKLIST(86), // uselib BLACKLIST(51), // acct BLACKLIST(123), // modify_ldt BLACKLIST(217), // pivot_root BLACKLIST(245), // io_setup BLACKLIST(246), // io_destroy BLACKLIST(247), // io_getevents BLACKLIST(248), // io_submit BLACKLIST(249), // io_cancel BLACKLIST(257), // remap_file_pages BLACKLIST(274), // mbind BLACKLIST(275), // get_mempolicy BLACKLIST(276), // set_mempolicy BLACKLIST(294), // migrate_pages BLACKLIST(317), // move_pages BLACKLIST(316), // vmsplice BLACKLIST(61), // chroot BLACKLIST(88), // reboot BLACKLIST(169), // nfsservctl BLACKLIST(130), // get_kernel_syms RETURN_ALLOW }; struct sock_fprog prog = { .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), .filter = filter, }; if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { ; } else if (arg_debug) { printf("Dual i386/amd64 seccomp filter configured\n"); } } // amd64 filter installed on i386 architectures void seccomp_filter_64(void) { // hardcoded syscall values struct sock_filter filter[] = { VALIDATE_ARCHITECTURE_64, EXAMINE_SYSCALL, BLACKLIST(165), // mount BLACKLIST(166), // umount2 BLACKLIST(101), // ptrace BLACKLIST(246), // kexec_load BLACKLIST(304), // open_by_handle_at BLACKLIST(175), // init_module BLACKLIST(313), // finit_module BLACKLIST(176), // delete_module BLACKLIST(172), // iopl BLACKLIST(173), // ioperm BLACKLIST(167), // swapon BLACKLIST(168), // swapoff BLACKLIST(103), // syslog BLACKLIST(310), // process_vm_readv BLACKLIST(311), // process_vm_writev BLACKLIST(139), // sysfs BLACKLIST(156), // _sysctl BLACKLIST(159), // adjtimex BLACKLIST(305), // clock_adjtime BLACKLIST(212), // lookup_dcookie BLACKLIST(298), // perf_event_open BLACKLIST(300), // fanotify_init BLACKLIST(312), // kcmp BLACKLIST(248), // add_key BLACKLIST(249), // request_key BLACKLIST(250), // keyctl BLACKLIST(134), // uselib BLACKLIST(163), // acct BLACKLIST(154), // modify_ldt BLACKLIST(155), // pivot_root BLACKLIST(206), // io_setup BLACKLIST(207), // io_destroy BLACKLIST(208), // io_getevents BLACKLIST(209), // io_submit BLACKLIST(210), // io_cancel BLACKLIST(216), // remap_file_pages BLACKLIST(237), // mbind BLACKLIST(239), // get_mempolicy BLACKLIST(238), // set_mempolicy BLACKLIST(256), // migrate_pages BLACKLIST(279), // move_pages BLACKLIST(278), // vmsplice BLACKLIST(161), // chroot BLACKLIST(184), // tuxcall BLACKLIST(169), // reboot BLACKLIST(180), // nfsservctl BLACKLIST(177), // get_kernel_syms RETURN_ALLOW }; struct sock_fprog prog = { .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), .filter = filter, }; if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { ; } else if (arg_debug) { printf("Dual i386/amd64 seccomp filter configured\n"); } } // drop filter for seccomp option int seccomp_filter_drop(int enforce_seccomp) { filter_init(); // default seccomp if (cfg.seccomp_list_drop == NULL) { #if defined(__x86_64__) seccomp_filter_32(); #endif #if defined(__i386__) seccomp_filter_64(); #endif #ifdef SYS_mount filter_add_blacklist(SYS_mount, 0); #endif #ifdef SYS_umount2 filter_add_blacklist(SYS_umount2, 0); #endif #ifdef SYS_ptrace filter_add_blacklist(SYS_ptrace, 0); #endif #ifdef SYS_kexec_load filter_add_blacklist(SYS_kexec_load, 0); #endif #ifdef SYS_kexec_file_load filter_add_blacklist(SYS_kexec_file_load, 0); #endif #ifdef SYS_open_by_handle_at filter_add_blacklist(SYS_open_by_handle_at, 0); #endif #ifdef SYS_init_module filter_add_blacklist(SYS_init_module, 0); #endif #ifdef SYS_finit_module // introduced in 2013 filter_add_blacklist(SYS_finit_module, 0); #endif #ifdef SYS_delete_module filter_add_blacklist(SYS_delete_module, 0); #endif #ifdef SYS_iopl filter_add_blacklist(SYS_iopl, 0); #endif #ifdef SYS_ioperm filter_add_blacklist(SYS_ioperm, 0); #endif #ifdef SYS_ni_syscall // new io permissions call on arm devices filter_add_blacklist(SYS_ni_syscall, 0); #endif #ifdef SYS_swapon filter_add_blacklist(SYS_swapon, 0); #endif #ifdef SYS_swapoff filter_add_blacklist(SYS_swapoff, 0); #endif #ifdef SYS_syslog filter_add_blacklist(SYS_syslog, 0); #endif #ifdef SYS_process_vm_readv filter_add_blacklist(SYS_process_vm_readv, 0); #endif #ifdef SYS_process_vm_writev filter_add_blacklist(SYS_process_vm_writev, 0); #endif // mknod removed in 0.9.29 - it brakes Zotero extension //#ifdef SYS_mknod // filter_add_blacklist(SYS_mknod, 0); //#endif // new syscalls in 0.9,23 #ifdef SYS_sysfs filter_add_blacklist(SYS_sysfs, 0); #endif #ifdef SYS__sysctl filter_add_blacklist(SYS__sysctl, 0); #endif #ifdef SYS_adjtimex filter_add_blacklist(SYS_adjtimex, 0); #endif #ifdef SYS_clock_adjtime filter_add_blacklist(SYS_clock_adjtime, 0); #endif #ifdef SYS_lookup_dcookie filter_add_blacklist(SYS_lookup_dcookie, 0); #endif #ifdef SYS_perf_event_open filter_add_blacklist(SYS_perf_event_open, 0); #endif #ifdef SYS_fanotify_init filter_add_blacklist(SYS_fanotify_init, 0); #endif #ifdef SYS_kcmp filter_add_blacklist(SYS_kcmp, 0); #endif // 0.9.32 #ifdef SYS_add_key filter_add_blacklist(SYS_add_key, 0); #endif #ifdef SYS_request_key filter_add_blacklist(SYS_request_key, 0); #endif #ifdef SYS_keyctl filter_add_blacklist(SYS_keyctl, 0); #endif #ifdef SYS_uselib filter_add_blacklist(SYS_uselib, 0); #endif #ifdef SYS_acct filter_add_blacklist(SYS_acct, 0); #endif #ifdef SYS_modify_ldt filter_add_blacklist(SYS_modify_ldt, 0); #endif //#ifdef SYS_unshare // filter_add_blacklist(SYS_unshare, 0); //#endif #ifdef SYS_pivot_root filter_add_blacklist(SYS_pivot_root, 0); #endif //#ifdef SYS_quotactl // filter_add_blacklist(SYS_quotactl, 0); //#endif #ifdef SYS_io_setup filter_add_blacklist(SYS_io_setup, 0); #endif #ifdef SYS_io_destroy filter_add_blacklist(SYS_io_destroy, 0); #endif #ifdef SYS_io_getevents filter_add_blacklist(SYS_io_getevents, 0); #endif #ifdef SYS_io_submit filter_add_blacklist(SYS_io_submit, 0); #endif #ifdef SYS_io_cancel filter_add_blacklist(SYS_io_cancel, 0); #endif #ifdef SYS_remap_file_pages filter_add_blacklist(SYS_remap_file_pages, 0); #endif #ifdef SYS_mbind filter_add_blacklist(SYS_mbind, 0); #endif #ifdef SYS_get_mempolicy filter_add_blacklist(SYS_get_mempolicy, 0); #endif #ifdef SYS_set_mempolicy filter_add_blacklist(SYS_set_mempolicy, 0); #endif #ifdef SYS_migrate_pages filter_add_blacklist(SYS_migrate_pages, 0); #endif #ifdef SYS_move_pages filter_add_blacklist(SYS_move_pages, 0); #endif #ifdef SYS_vmsplice filter_add_blacklist(SYS_vmsplice, 0); #endif #ifdef SYS_chroot filter_add_blacklist(SYS_chroot, 0); #endif //#ifdef SYS_set_robust_list // filter_add_blacklist(SYS_set_robust_list, 0); //#endif //#ifdef SYS_get_robust_list // filter_add_blacklist(SYS_get_robust_list, 0); //#endif // CHECK_SECCOMP(seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(clone), 1, // SCMP_A0(SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER))); // 0.9.39 #ifdef SYS_tuxcall filter_add_blacklist(SYS_tuxcall, 0); #endif #ifdef SYS_reboot filter_add_blacklist(SYS_reboot, 0); #endif #ifdef SYS_nfsservctl filter_add_blacklist(SYS_nfsservctl, 0); #endif #ifdef SYS_get_kernel_syms filter_add_blacklist(SYS_get_kernel_syms, 0); #endif } // default seccomp filter with additional drop list if (cfg.seccomp_list && cfg.seccomp_list_drop == NULL) { if (syscall_check_list(cfg.seccomp_list, filter_add_blacklist, 0)) { fprintf(stderr, "Error: cannot load seccomp filter\n"); exit(1); } } // drop list else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) { if (syscall_check_list(cfg.seccomp_list_drop, filter_add_blacklist, 0)) { fprintf(stderr, "Error: cannot load seccomp filter\n"); exit(1); } } filter_end_blacklist(); if (arg_debug) filter_debug(); // save seccomp filter in /tmp/firejail/mnt/seccomp // in order to use it in --join operations write_seccomp_file(); struct sock_fprog prog = { .len = sfilter_index, .filter = sfilter, }; if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { if (enforce_seccomp) { fprintf(stderr, "Error: a seccomp-enabled Linux kernel is required, exiting...\n"); exit(1); } else fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n"); return 1; } return 0; } // keep filter for seccomp option int seccomp_filter_keep(void) { filter_init(); // these 4 syscalls are used by firejail after the seccomp filter is initialized filter_add_whitelist(SYS_setuid, 0); filter_add_whitelist(SYS_setgid, 0); filter_add_whitelist(SYS_setgroups, 0); filter_add_whitelist(SYS_dup, 0); // apply keep list if (cfg.seccomp_list_keep) { if (syscall_check_list(cfg.seccomp_list_keep, filter_add_whitelist, 0)) { fprintf(stderr, "Error: cannot load seccomp filter\n"); exit(1); } } filter_end_whitelist(); if (arg_debug) filter_debug(); // save seccomp filter in /tmp/firejail/mnt/seccomp // in order to use it in --join operations write_seccomp_file(); struct sock_fprog prog = { .len = sfilter_index, .filter = sfilter, }; if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n"); return 1; } else if (arg_debug) { printf("seccomp enabled\n"); } return 0; }
// drop filter for seccomp option int seccomp_filter_drop(int enforce_seccomp) { // default seccomp if (cfg.seccomp_list_drop == NULL && cfg.seccomp_list == NULL) { #if defined(__x86_64__) seccomp_filter_32(); #endif #if defined(__i386__) seccomp_filter_64(); #endif } // default seccomp filter with additional drop list else if (cfg.seccomp_list && cfg.seccomp_list_drop == NULL) { #if defined(__x86_64__) seccomp_filter_32(); #endif #if defined(__i386__) seccomp_filter_64(); #endif if (arg_debug) printf("Build default+drop seccomp filter\n"); // build the seccomp filter as a regular user int rv; if (arg_allow_debuggers) rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 6, PATH_FSECCOMP, "default", "drop", RUN_SECCOMP_CFG, cfg.seccomp_list, "allow-debuggers"); else rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5, PATH_FSECCOMP, "default", "drop", RUN_SECCOMP_CFG, cfg.seccomp_list); if (rv) exit(rv); } // drop list without defaults - secondary filters are not installed else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) { if (arg_debug) printf("Build drop seccomp filter\n"); // build the seccomp filter as a regular user int rv; if (arg_allow_debuggers) rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5, PATH_FSECCOMP, "drop", RUN_SECCOMP_CFG, cfg.seccomp_list_drop, "allow-debuggers"); else rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4, PATH_FSECCOMP, "drop", RUN_SECCOMP_CFG, cfg.seccomp_list_drop); if (rv) exit(rv); } else { assert(0); } // load the filter if (seccomp_load(RUN_SECCOMP_CFG) == 0) { if (arg_debug) printf("seccomp filter configured\n"); } else if (enforce_seccomp) { fprintf(stderr, "Error: a seccomp-enabled Linux kernel is required, exiting...\n"); exit(1); } if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0) sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FSECCOMP, "print", RUN_SECCOMP_CFG); return seccomp_load(RUN_SECCOMP_CFG); }