From 3f27e8483158e50050f839db343bda7a522f686d Mon Sep 17 00:00:00 2001 From: Topi Miettinen Date: Fri, 27 Mar 2020 14:22:20 +0200 Subject: Allow changing error action in seccomp filters Let user specify the action when seccomp filters trigger: - errno name like EPERM (default) or ENOSYS: return errno and let the process continue. - 'kill': kill the process as previous versions The default action is EPERM, but killing can still be specified with syscall:kill syntax or globally with seccomp-error-action=kill. The action can be also overridden /etc/firejail/firejail.config file. Not killing the process weakens Firejail slightly when trying to contain intrusion, but it may also allow tighter filters if the only alternative is to allow a system call. --- src/lib/syscall.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'src/lib/syscall.c') diff --git a/src/lib/syscall.c b/src/lib/syscall.c index 1cf7f2d52..5accdcb65 100644 --- a/src/lib/syscall.c +++ b/src/lib/syscall.c @@ -20,11 +20,16 @@ #define _GNU_SOURCE #include "../include/syscall.h" #include +#include #include #include #include #include #include "../include/common.h" +#include "../include/seccomp.h" + +#define SYSCALL_ERROR INT_MAX +#define ERRNO_KILL -2 typedef struct { const char * const name; @@ -1430,7 +1435,7 @@ static const SyscallGroupList sysgroups[] = { } }; -// return -1 if error, or syscall number +// return SYSCALL_ERROR if error, or syscall number static int syscall_find_name(const char *name) { int i; int elems = sizeof(syslist) / sizeof(syslist[0]); @@ -1439,7 +1444,7 @@ static int syscall_find_name(const char *name) { return syslist[i].nr; } - return -1; + return SYSCALL_ERROR; } static int syscall_find_name_32(const char *name) { @@ -1450,7 +1455,7 @@ static int syscall_find_name_32(const char *name) { return syslist32[i].nr; } - return -1; + return SYSCALL_ERROR; } const char *syscall_find_nr(int nr) { @@ -1538,9 +1543,13 @@ static void syscall_process_name(const char *name, int *syscall_nr, int *error_n *syscall_nr = syscall_find_name_32(syscall_name); } if (error_name) { - *error_nr = errno_find_name(error_name); - if (*error_nr == -1) - *syscall_nr = -1; + if (strcmp(error_name, "kill") == 0) + *error_nr = ERRNO_KILL; + else { + *error_nr = errno_find_name(error_name); + if (*error_nr == -1) + *syscall_nr = SYSCALL_ERROR; + } } free(str); @@ -1589,15 +1598,15 @@ int syscall_check_list(const char *slist, filter_fn *callback, int fd, int arg, ptr++; } syscall_process_name(ptr, &syscall_nr, &error_nr, native); - if (syscall_nr == -1) {;} - else if (callback != NULL) { + if (syscall_nr != SYSCALL_ERROR && callback != NULL) { if (negate) { syscall_nr = -syscall_nr; } - if (error_nr != -1 && fd > 0) { + if (error_nr >= 0 && fd > 0) filter_add_errno(fd, syscall_nr, error_nr, ptrarg, native); - } - else if (error_nr != -1 && fd == 0) { + else if (error_nr == ERRNO_KILL && fd > 0) + filter_add_blacklist_override(fd, syscall_nr, 0, ptrarg, native); + else if (error_nr >= 0 && fd == 0) { callback(fd, syscall_nr, error_nr, ptrarg, native); } else { -- cgit v1.2.3-54-g00ecf