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/fseccomp/main.c | 13 +++++++++++++ src/fseccomp/seccomp.c | 20 ++++++++++---------- src/fseccomp/seccomp_file.c | 15 ++++++++++++++- src/fseccomp/seccomp_secondary.c | 2 +- 4 files changed, 38 insertions(+), 12 deletions(-) (limited to 'src/fseccomp') diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c index b3161a6db..98e32cdf4 100644 --- a/src/fseccomp/main.c +++ b/src/fseccomp/main.c @@ -18,7 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "fseccomp.h" +#include "../include/seccomp.h" int arg_quiet = 0; +int arg_seccomp_error_action = EPERM; // error action: errno or kill static void usage(void) { printf("Usage:\n"); @@ -67,6 +69,17 @@ printf("\n"); if (quiet && strcmp(quiet, "yes") == 0) arg_quiet = 1; + char *error_action = getenv("FIREJAIL_SECCOMP_ERROR_ACTION"); + if (error_action) + if (strcmp(error_action, "kill") == 0) + arg_seccomp_error_action = SECCOMP_RET_KILL; + else { + arg_seccomp_error_action = errno_find_name(error_action); + if (arg_seccomp_error_action == -1) + errExit("seccomp-error-action: unknown errno"); + arg_seccomp_error_action |= SECCOMP_RET_ERRNO; + } + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { usage(); return 0; diff --git a/src/fseccomp/seccomp.c b/src/fseccomp/seccomp.c index 0db7b5954..e808538b0 100644 --- a/src/fseccomp/seccomp.c +++ b/src/fseccomp/seccomp.c @@ -255,7 +255,7 @@ void memory_deny_write_execute(const char *fname) { EXAMINE_ARGUMENT(2), BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_WRITE|PROT_EXEC), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_WRITE|PROT_EXEC, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, RETURN_ALLOW, #endif @@ -264,7 +264,7 @@ void memory_deny_write_execute(const char *fname) { EXAMINE_ARGUMENT(2), BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, RETURN_ALLOW, // same for pkey_mprotect(,,PROT_EXEC), where available @@ -273,7 +273,7 @@ void memory_deny_write_execute(const char *fname) { EXAMINE_ARGUMENT(2), BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, RETURN_ALLOW, #endif @@ -284,7 +284,7 @@ void memory_deny_write_execute(const char *fname) { EXAMINE_ARGUMENT(2), BPF_STMT(BPF_ALU+BPF_AND+BPF_K, SHM_EXEC), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SHM_EXEC, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, RETURN_ALLOW, #endif #ifdef SYS_memfd_create @@ -292,7 +292,7 @@ void memory_deny_write_execute(const char *fname) { // arbitrary memory contents which can be later mapped // as executable BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_memfd_create, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, RETURN_ALLOW #endif }; @@ -327,7 +327,7 @@ void memory_deny_write_execute_32(const char *fname) { EXAMINE_ARGUMENT(2), BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_WRITE|PROT_EXEC), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_WRITE|PROT_EXEC, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, RETURN_ALLOW, #endif #ifdef mprotect_32 @@ -336,7 +336,7 @@ void memory_deny_write_execute_32(const char *fname) { EXAMINE_ARGUMENT(2), BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, RETURN_ALLOW, #endif #ifdef pkey_mprotect_32 @@ -345,7 +345,7 @@ void memory_deny_write_execute_32(const char *fname) { EXAMINE_ARGUMENT(2), BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, RETURN_ALLOW, #endif @@ -355,7 +355,7 @@ void memory_deny_write_execute_32(const char *fname) { EXAMINE_ARGUMENT(2), BPF_STMT(BPF_ALU+BPF_AND+BPF_K, SHM_EXEC), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SHM_EXEC, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, RETURN_ALLOW, #endif #ifdef memfd_create_32 @@ -363,7 +363,7 @@ void memory_deny_write_execute_32(const char *fname) { // arbitrary memory contents which can be later mapped // as executable BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, memfd_create_32, 0, 1), - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, #endif #endif RETURN_ALLOW diff --git a/src/fseccomp/seccomp_file.c b/src/fseccomp/seccomp_file.c index 872b41261..9e8ceb898 100644 --- a/src/fseccomp/seccomp_file.c +++ b/src/fseccomp/seccomp_file.c @@ -112,6 +112,19 @@ void filter_add_blacklist(int fd, int syscall, int arg, void *ptrarg, bool nativ } } +void filter_add_blacklist_override(int fd, int syscall, int arg, void *ptrarg, bool native) { + (void) arg; + (void) ptrarg; + (void) native; + + if (syscall >= 0) { + int saved_error_action = arg_seccomp_error_action; + arg_seccomp_error_action = SECCOMP_RET_KILL; + write_blacklist(fd, syscall); + arg_seccomp_error_action = saved_error_action; + } +} + // handle seccomp list exceptions (seccomp x,y,!z) void filter_add_blacklist_for_excluded(int fd, int syscall, int arg, void *ptrarg, bool native) { (void) arg; @@ -142,7 +155,7 @@ void filter_end_blacklist(int fd) { void filter_end_whitelist(int fd) { struct sock_filter filter[] = { - KILL_PROCESS + KILL_OR_RETURN_ERRNO }; write_to_file(fd, filter, sizeof(filter)); } diff --git a/src/fseccomp/seccomp_secondary.c b/src/fseccomp/seccomp_secondary.c index 9a00d1884..f024859d3 100644 --- a/src/fseccomp/seccomp_secondary.c +++ b/src/fseccomp/seccomp_secondary.c @@ -142,7 +142,7 @@ void seccomp_secondary_block(const char *fname) { // 5: if MSW(arg0) == 0, goto 7 (allow) else continue to 6 (kill) BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, jmp_from_to(5, 7), 0), // 6: - KILL_PROCESS, + KILL_OR_RETURN_ERRNO, // 7: RETURN_ALLOW }; -- cgit v1.2.3-54-g00ecf