From 34ee8e03f58c4c51c3aa29f553e06570d0654db2 Mon Sep 17 00:00:00 2001 From: Topi Miettinen Date: Sun, 6 Aug 2017 21:58:35 +0300 Subject: Seccomp: system call grouping and call numbers --- src/fseccomp/fseccomp.h | 3 +- src/fseccomp/seccomp.c | 317 ++---------------------------------------- src/fseccomp/syscall.c | 356 +++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 351 insertions(+), 325 deletions(-) (limited to 'src/fseccomp') diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h index 157b71011..0db670380 100644 --- a/src/fseccomp/fseccomp.h +++ b/src/fseccomp/fseccomp.h @@ -31,8 +31,7 @@ extern int arg_quiet; // syscall.c void syscall_print(void); int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg); -int syscall_find_name(const char *name); -char *syscall_find_nr(int nr); +const char *syscall_find_nr(int nr); // errno.c void errno_print(void); diff --git a/src/fseccomp/seccomp.c b/src/fseccomp/seccomp.c index a30a9e00b..a3db46aad 100644 --- a/src/fseccomp/seccomp.c +++ b/src/fseccomp/seccomp.c @@ -25,319 +25,24 @@ #include static void add_default_list(int fd, int allow_debuggers) { -#ifdef SYS_mount - filter_add_blacklist(fd, SYS_mount, 0); -#endif -#ifdef SYS_umount2 - filter_add_blacklist(fd, SYS_umount2, 0); -#endif + int r; + if (!allow_debuggers) + r = syscall_check_list("@default-nodebuggers", filter_add_blacklist, fd, 0); + else + r = syscall_check_list("@default", filter_add_blacklist, fd, 0); - if (!allow_debuggers) { -#ifdef SYS_ptrace - filter_add_blacklist(fd, SYS_ptrace, 0); -#endif - } - -#ifdef SYS_kexec_load - filter_add_blacklist(fd, SYS_kexec_load, 0); -#endif -#ifdef SYS_kexec_file_load - filter_add_blacklist(fd, SYS_kexec_file_load, 0); -#endif -#ifdef SYS_open_by_handle_at - filter_add_blacklist(fd, SYS_open_by_handle_at, 0); -#endif -#ifdef SYS_name_to_handle_at - filter_add_blacklist(fd, SYS_name_to_handle_at, 0); -#endif -#ifdef SYS_init_module - filter_add_blacklist(fd, SYS_init_module, 0); -#endif -#ifdef SYS_finit_module - filter_add_blacklist(fd, SYS_finit_module, 0); -#endif -#ifdef SYS_create_module - filter_add_blacklist(fd, SYS_create_module, 0); -#endif -#ifdef SYS_delete_module - filter_add_blacklist(fd, SYS_delete_module, 0); -#endif -#ifdef SYS_iopl - filter_add_blacklist(fd, SYS_iopl, 0); -#endif -#ifdef SYS_ioperm - filter_add_blacklist(fd, SYS_ioperm, 0); -#endif -#ifdef SYS_ioprio_set - filter_add_blacklist(fd, SYS_ioprio_set, 0); -#endif -#ifdef SYS_ni_syscall - filter_add_blacklist(fd, SYS_ni_syscall, 0); -#endif -#ifdef SYS_swapon - filter_add_blacklist(fd, SYS_swapon, 0); -#endif -#ifdef SYS_swapoff - filter_add_blacklist(fd, SYS_swapoff, 0); -#endif -#ifdef SYS_syslog - filter_add_blacklist(fd, SYS_syslog, 0); -#endif - - if (!allow_debuggers) { -#ifdef SYS_process_vm_readv - filter_add_blacklist(fd, SYS_process_vm_readv, 0); -#endif - } - -#ifdef SYS_process_vm_writev - filter_add_blacklist(fd, SYS_process_vm_writev, 0); -#endif + assert(r == 0); //#ifdef SYS_mknod - emoved in 0.9.29 - it breaks Zotero extension // filter_add_blacklist(SYS_mknod, 0); //#endif -#ifdef SYS_sysfs - filter_add_blacklist(fd, SYS_sysfs, 0); -#endif -#ifdef SYS__sysctl - filter_add_blacklist(fd, SYS__sysctl, 0); -#endif -#ifdef SYS_adjtimex - filter_add_blacklist(fd, SYS_adjtimex, 0); -#endif -#ifdef SYS_clock_adjtime - filter_add_blacklist(fd, SYS_clock_adjtime, 0); -#endif -#ifdef SYS_lookup_dcookie - filter_add_blacklist(fd, SYS_lookup_dcookie, 0); -#endif -#ifdef SYS_perf_event_open - filter_add_blacklist(fd, SYS_perf_event_open, 0); -#endif -#ifdef SYS_fanotify_init - filter_add_blacklist(fd, SYS_fanotify_init, 0); -#endif -#ifdef SYS_kcmp - filter_add_blacklist(fd, SYS_kcmp, 0); -#endif -#ifdef SYS_add_key - filter_add_blacklist(fd, SYS_add_key, 0); -#endif -#ifdef SYS_request_key - filter_add_blacklist(fd, SYS_request_key, 0); -#endif -#ifdef SYS_keyctl - filter_add_blacklist(fd, SYS_keyctl, 0); -#endif -#ifdef SYS_uselib - filter_add_blacklist(fd, SYS_uselib, 0); -#endif -#ifdef SYS_acct - filter_add_blacklist(fd, SYS_acct, 0); -#endif -#ifdef SYS_modify_ldt - filter_add_blacklist(fd, SYS_modify_ldt, 0); -#endif -#ifdef SYS_pivot_root - filter_add_blacklist(fd, SYS_pivot_root, 0); -#endif -#ifdef SYS_io_setup - filter_add_blacklist(fd, SYS_io_setup, 0); -#endif -#ifdef SYS_io_destroy - filter_add_blacklist(fd, SYS_io_destroy, 0); -#endif -#ifdef SYS_io_getevents - filter_add_blacklist(fd, SYS_io_getevents, 0); -#endif -#ifdef SYS_io_submit - filter_add_blacklist(fd, SYS_io_submit, 0); -#endif -#ifdef SYS_io_cancel - filter_add_blacklist(fd, SYS_io_cancel, 0); -#endif -#ifdef SYS_remap_file_pages - filter_add_blacklist(fd, SYS_remap_file_pages, 0); -#endif -#ifdef SYS_mbind - filter_add_blacklist(fd, SYS_mbind, 0); -#endif - // breaking Firefox nightly when playing youtube videos // TODO: test again when firefox sandbox is finally released //#ifdef SYS_get_mempolicy // filter_add_blacklist(fd, SYS_get_mempolicy, 0); //#endif - -#ifdef SYS_set_mempolicy - filter_add_blacklist(fd, SYS_set_mempolicy, 0); -#endif -#ifdef SYS_migrate_pages - filter_add_blacklist(fd, SYS_migrate_pages, 0); -#endif -#ifdef SYS_move_pages - filter_add_blacklist(fd, SYS_move_pages, 0); -#endif -#ifdef SYS_vmsplice - filter_add_blacklist(fd, SYS_vmsplice, 0); -#endif -#ifdef SYS_chroot - filter_add_blacklist(fd, SYS_chroot, 0); -#endif -#ifdef SYS_tuxcall - filter_add_blacklist(fd, SYS_tuxcall, 0); -#endif -#ifdef SYS_reboot - filter_add_blacklist(fd, SYS_reboot, 0); -#endif -#ifdef SYS_nfsservctl - filter_add_blacklist(fd, SYS_nfsservctl, 0); -#endif -#ifdef SYS_get_kernel_syms - filter_add_blacklist(fd, SYS_get_kernel_syms, 0); -#endif - -// 0.9.45 -#ifdef SYS_bpf - filter_add_blacklist(fd, SYS_bpf, 0); -#endif -#ifdef SYS_clock_settime - filter_add_blacklist(fd, SYS_clock_settime, 0); -#endif -//#ifdef SYS_clone - in use by Firejail -// filter_add_blacklist(fd, SYS_clone, 0); -//#endif -#ifdef SYS_personality - filter_add_blacklist(fd, SYS_personality, 0); -#endif -#ifdef SYS_process_vm_writev - filter_add_blacklist(fd, SYS_process_vm_writev, 0); -#endif -#ifdef SYS_query_module - filter_add_blacklist(fd, SYS_query_module, 0); -#endif //#ifdef SYS_quotactl - in use by Firefox // filter_add_blacklist(fd, SYS_quotactl, 0); //#endif -//#ifdef SYS_setns - in use by Firejail -// filter_add_blacklist(fd, SYS_setns, 0); -//#endif -#ifdef SYS_settimeofday - filter_add_blacklist(fd, SYS_settimeofday, 0); -#endif -#ifdef SYS_stime - filter_add_blacklist(fd, SYS_stime, 0); -#endif -#ifdef SYS_umount - filter_add_blacklist(fd, SYS_umount, 0); -#endif -//#ifdef SYS_unshare - in use by Firejail -// filter_add_blacklist(fd, SYS_unshare, 0); -//#endif -#ifdef SYS_userfaultfd - filter_add_blacklist(fd, SYS_userfaultfd, 0); -#endif -#ifdef SYS_ustat - filter_add_blacklist(fd, SYS_ustat, 0); -#endif -#ifdef SYS_vm86 - filter_add_blacklist(fd, SYS_vm86, 0); -#endif -#ifdef SYS_vm86old - filter_add_blacklist(fd, SYS_vm86old, 0); -#endif - -#ifdef SYS_afs_syscall - filter_add_blacklist(fd, SYS_afs_syscall, 0); -#endif -#ifdef SYS_bdflush - filter_add_blacklist(fd, SYS_bdflush, 0); -#endif -#ifdef SYS_break - filter_add_blacklist(fd, SYS_break, 0); -#endif -#ifdef SYS_ftime - filter_add_blacklist(fd, SYS_ftime, 0); -#endif -#ifdef SYS_getpmsg - filter_add_blacklist(fd, SYS_getpmsg, 0); -#endif -#ifdef SYS_gtty - filter_add_blacklist(fd, SYS_gtty, 0); -#endif -#ifdef SYS_lock - filter_add_blacklist(fd, SYS_lock, 0); -#endif -#ifdef SYS_mpx - filter_add_blacklist(fd, SYS_mpx, 0); -#endif -#ifdef SYS_pciconfig_iobase - filter_add_blacklist(fd, SYS_pciconfig_iobase, 0); -#endif -#ifdef SYS_pciconfig_read - filter_add_blacklist(fd, SYS_pciconfig_read, 0); -#endif -#ifdef SYS_pciconfig_write - filter_add_blacklist(fd, SYS_pciconfig_write, 0); -#endif -#ifdef SYS_prof - filter_add_blacklist(fd, SYS_prof, 0); -#endif -#ifdef SYS_profil - filter_add_blacklist(fd, SYS_profil, 0); -#endif -#ifdef SYS_putpmsg - filter_add_blacklist(fd, SYS_putpmsg, 0); -#endif -#ifdef SYS_rtas - filter_add_blacklist(fd, SYS_rtas, 0); -#endif -#ifdef SYS_s390_runtime_instr - filter_add_blacklist(fd, SYS_s390_runtime_instr, 0); -#endif -#ifdef SYS_s390_mmio_read - filter_add_blacklist(fd, SYS_s390_mmio_read, 0); -#endif -#ifdef SYS_s390_mmio_write - filter_add_blacklist(fd, SYS_s390_mmio_write, 0); -#endif -#ifdef SYS_security - filter_add_blacklist(fd, SYS_security, 0); -#endif -#ifdef SYS_setdomainname - filter_add_blacklist(fd, SYS_setdomainname, 0); -#endif -#ifdef SYS_sethostname - filter_add_blacklist(fd, SYS_sethostname, 0); -#endif -#ifdef SYS_sgetmask - filter_add_blacklist(fd, SYS_sgetmask, 0); -#endif -#ifdef SYS_ssetmask - filter_add_blacklist(fd, SYS_ssetmask, 0); -#endif -#ifdef SYS_stty - filter_add_blacklist(fd, SYS_stty, 0); -#endif -#ifdef SYS_subpage_prot - filter_add_blacklist(fd, SYS_subpage_prot, 0); -#endif -#ifdef SYS_switch_endian - filter_add_blacklist(fd, SYS_switch_endian, 0); -#endif -#ifdef SYS_sys_debug_setcontext - filter_add_blacklist(fd, SYS_sys_debug_setcontext, 0); -#endif -#ifdef SYS_ulimit - filter_add_blacklist(fd, SYS_ulimit, 0); -#endif -#ifdef SYS_vhangup - filter_add_blacklist(fd, SYS_vhangup, 0); -#endif -#ifdef SYS_vserver - filter_add_blacklist(fd, SYS_vserver, 0); -#endif - } // default list @@ -418,12 +123,10 @@ void seccomp_keep(const char *fname, char *list) { // build filter filter_init(fd); - // these 4 syscalls are used by firejail after the seccomp filter is initialized - filter_add_whitelist(fd, SYS_setuid, 0); - filter_add_whitelist(fd, SYS_setgid, 0); - filter_add_whitelist(fd, SYS_setgroups, 0); - filter_add_whitelist(fd, SYS_dup, 0); - filter_add_whitelist(fd, SYS_prctl, 0); + // these syscalls are used by firejail after the seccomp filter is initialized + int r; + r = syscall_check_list("@default-keep", filter_add_whitelist, fd, 0); + assert(r == 0); if (syscall_check_list(list, filter_add_whitelist, fd, 0)) { fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n"); diff --git a/src/fseccomp/syscall.c b/src/fseccomp/syscall.c index 0a86dade0..ecf057ee0 100644 --- a/src/fseccomp/syscall.c +++ b/src/fseccomp/syscall.c @@ -21,11 +21,16 @@ #include typedef struct { - char *name; + const char * const name; int nr; } SyscallEntry; -static SyscallEntry syslist[] = { +typedef struct { + const char * const name; + const char * const list; +} SyscallGroupList; + +static const SyscallEntry syslist[] = { // // code generated using tools/extract-syscall // @@ -35,8 +40,302 @@ static SyscallEntry syslist[] = { // }; // end of syslist +static const SyscallGroupList sysgroups[] = { + { .name = "@default", .list = +#ifdef SYS_mount + "mount," +#endif +#ifdef SYS_umount2 + "umount2," +#endif +#ifdef SYS_kexec_load + "kexec_load," +#endif +#ifdef SYS_kexec_file_load + "kexec_file_load," +#endif +#ifdef SYS_open_by_handle_at + "open_by_handle_at," +#endif +#ifdef SYS_name_to_handle_at + "name_to_handle_at," +#endif +#ifdef SYS_init_module + "init_module," +#endif +#ifdef SYS_finit_module + "finit_module," +#endif +#ifdef SYS_create_module + "create_module," +#endif +#ifdef SYS_delete_module + "delete_module," +#endif +#ifdef SYS_iopl + "iopl," +#endif +#ifdef SYS_ioperm + "ioperm," +#endif +#ifdef SYS_ioprio_set + "ioprio_set," +#endif +#ifdef SYS_ni_syscall + "ni_syscall," +#endif +#ifdef SYS_swapon + "swapon," +#endif +#ifdef SYS_swapoff + "swapoff," +#endif +#ifdef SYS_syslog + "syslog," +#endif +#ifdef SYS_process_vm_writev + "process_vm_writev," +#endif +#ifdef SYS_sysfs + "sysfs," +#endif +#ifdef SYS__sysctl + "_sysctl," +#endif +#ifdef SYS_adjtimex + "adjtimex," +#endif +#ifdef SYS_clock_adjtime + "clock_adjtime," +#endif +#ifdef SYS_lookup_dcookie + "lookup_dcookie," +#endif +#ifdef SYS_perf_event_open + "perf_event_open," +#endif +#ifdef SYS_fanotify_init + "fanotify_init," +#endif +#ifdef SYS_kcmp + "kcmp," +#endif +#ifdef SYS_add_key + "add_key," +#endif +#ifdef SYS_request_key + "request_key," +#endif +#ifdef SYS_keyctl + "keyctl," +#endif +#ifdef SYS_uselib + "uselib," +#endif +#ifdef SYS_acct + "acct," +#endif +#ifdef SYS_modify_ldt + "modify_ldt," +#endif +#ifdef SYS_pivot_root + "pivot_root," +#endif +#ifdef SYS_io_setup + "io_setup," +#endif +#ifdef SYS_io_destroy + "io_destroy," +#endif +#ifdef SYS_io_getevents + "io_getevents," +#endif +#ifdef SYS_io_submit + "io_submit," +#endif +#ifdef SYS_io_cancel + "io_cancel," +#endif +#ifdef SYS_remap_file_pages + "remap_file_pages," +#endif +#ifdef SYS_mbind + "mbind," +#endif +#ifdef SYS_set_mempolicy + "set_mempolicy," +#endif +#ifdef SYS_migrate_pages + "migrate_pages," +#endif +#ifdef SYS_move_pages + "move_pages," +#endif +#ifdef SYS_vmsplice + "vmsplice," +#endif +#ifdef SYS_chroot + "chroot," +#endif +#ifdef SYS_tuxcall + "tuxcall," +#endif +#ifdef SYS_reboot + "reboot," +#endif +#ifdef SYS_nfsservctl + "nfsservctl," +#endif +#ifdef SYS_get_kernel_syms + "get_kernel_syms," +#endif +#ifdef SYS_bpf + "bpf," +#endif +#ifdef SYS_clock_settime + "clock_settime," +#endif +#ifdef SYS_personality + "personality," +#endif +#ifdef SYS_process_vm_writev + "process_vm_writev," +#endif +#ifdef SYS_query_module + "query_module," +#endif +#ifdef SYS_settimeofday + "settimeofday," +#endif +#ifdef SYS_stime + "stime," +#endif +#ifdef SYS_umount + "umount," +#endif +#ifdef SYS_userfaultfd + "userfaultfd," +#endif +#ifdef SYS_ustat + "ustat," +#endif +#ifdef SYS_vm86 + "vm86," +#endif +#ifdef SYS_vm86old + "vm86old," +#endif +#ifdef SYS_afs_syscall + "afs_syscall," +#endif +#ifdef SYS_bdflush + "bdflush," +#endif +#ifdef SYS_break + "break," +#endif +#ifdef SYS_ftime + "ftime," +#endif +#ifdef SYS_getpmsg + "getpmsg," +#endif +#ifdef SYS_gtty + "gtty," +#endif +#ifdef SYS_lock + "lock," +#endif +#ifdef SYS_mpx + "mpx," +#endif +#ifdef SYS_pciconfig_iobase + "pciconfig_iobase," +#endif +#ifdef SYS_pciconfig_read + "pciconfig_read," +#endif +#ifdef SYS_pciconfig_write + "pciconfig_write," +#endif +#ifdef SYS_prof + "prof," +#endif +#ifdef SYS_profil + "profil," +#endif +#ifdef SYS_putpmsg + "putpmsg," +#endif +#ifdef SYS_rtas + "rtas," +#endif +#ifdef SYS_s390_runtime_instr + "s390_runtime_instr," +#endif +#ifdef SYS_s390_mmio_read + "s390_mmio_read," +#endif +#ifdef SYS_s390_mmio_write + "s390_mmio_write," +#endif +#ifdef SYS_security + "security," +#endif +#ifdef SYS_setdomainname + "setdomainname," +#endif +#ifdef SYS_sethostname + "sethostname," +#endif +#ifdef SYS_sgetmask + "sgetmask," +#endif +#ifdef SYS_ssetmask + "ssetmask," +#endif +#ifdef SYS_stty + "stty," +#endif +#ifdef SYS_subpage_prot + "subpage_prot," +#endif +#ifdef SYS_switch_endian + "switch_endian," +#endif +#ifdef SYS_sys_debug_setcontext + "sys_debug_setcontext," +#endif +#ifdef SYS_ulimit + "ulimit," +#endif +#ifdef SYS_vhangup + "vhangup," +#endif +#ifdef SYS_vserver + "vserver" +#endif + }, + { .name = "@default-nodebuggers", .list = + "@default," +#ifdef SYS_ptrace + "ptrace," +#endif +#ifdef SYS_process_vm_readv + "process_vm_readv" +#endif + }, + { .name = "@default-keep", .list = + "dup," + "prctl," + "setgid," + "setgroups," + "setuid" + } +}; + // return -1 if error, or syscall number -int syscall_find_name(const char *name) { +static int syscall_find_name(const char *name) { int i; int elems = sizeof(syslist) / sizeof(syslist[0]); for (i = 0; i < elems; i++) { @@ -47,7 +346,7 @@ int syscall_find_name(const char *name) { return -1; } -char *syscall_find_nr(int nr) { +const char *syscall_find_nr(int nr) { int i; int elems = sizeof(syslist) / sizeof(syslist[0]); for (i = 0; i < elems; i++) { @@ -67,6 +366,17 @@ void syscall_print(void) { printf("\n"); } +static const char *syscall_find_group(const char *name) { + int i; + int elems = sizeof(sysgroups) / sizeof(sysgroups[0]); + for (i = 0; i < elems; i++) { + if (strcmp(name, sysgroups[i].name) == 0) + return sysgroups[i].list; + } + + return NULL; +} + // allowed input: // - syscall // - syscall(error) @@ -92,7 +402,10 @@ static void syscall_process_name(const char *name, int *syscall_nr, int *error_n goto error; } - *syscall_nr = syscall_find_name(syscall_name); + if (*syscall_name == '$') + *syscall_nr = strtol(syscall_name + 1, NULL, 0); + else + *syscall_nr = syscall_find_name(syscall_name); if (error_name) { *error_nr = errno_find_name(error_name); if (*error_nr == -1) @@ -120,7 +433,8 @@ int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, if (!str) errExit("strdup"); - char *ptr =strtok(str, ","); + char *saveptr; + char *ptr = strtok_r(str, ",", &saveptr); if (ptr == NULL) { fprintf(stderr, "Error fseccomp: empty syscall lists are not allowed\n"); exit(1); @@ -129,18 +443,28 @@ int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, while (ptr) { int syscall_nr; int error_nr; - syscall_process_name(ptr, &syscall_nr, &error_nr); - if (syscall_nr == -1) { - if (!arg_quiet) - fprintf(stderr, "Warning fseccomp: syscall \"%s\" not available on this platform\n", ptr); + if (*ptr == '@') { + const char *new_list = syscall_find_group(ptr); + if (!new_list) { + fprintf(stderr, "Error fseccomp: unknown syscall group %s\n", ptr); + exit(1); + } + syscall_check_list(new_list, callback, fd, arg); } - else if (callback != NULL) { - if (error_nr != -1) - filter_add_errno(fd, syscall_nr, error_nr); - else - callback(fd, syscall_nr, arg); + else { + syscall_process_name(ptr, &syscall_nr, &error_nr); + if (syscall_nr == -1) { + if (!arg_quiet) + fprintf(stderr, "Warning fseccomp: syscall \"%s\" not available on this platform\n", ptr); + } + else if (callback != NULL) { + if (error_nr != -1) + filter_add_errno(fd, syscall_nr, error_nr); + else + callback(fd, syscall_nr, arg); + } } - ptr = strtok(NULL, ","); + ptr = strtok_r(NULL, ",", &saveptr); } free(str); -- cgit v1.2.3-54-g00ecf