From 0040969e439dbddb76bc190900b453b71e895068 Mon Sep 17 00:00:00 2001 From: Topi Miettinen Date: Sun, 31 Jan 2021 00:15:31 +0200 Subject: Seccomp error action fixes fsec-optimize: Optimize BPF with current seccomp error action, not just KILL fseccomp: use correct BPF code for errno action firejail: honor seccomp error action for X32 and secondary filters, rebuild filters if the error action is changed Closes: #3933 Signed-off-by: Topi Miettinen --- src/firejail/sbox.c | 2 +- src/firejail/seccomp.c | 46 ++++++++++++++++++++++++++++++---------- src/fsec-optimize/Makefile.in | 2 +- src/fsec-optimize/main.c | 17 +++++++++++++++ src/fsec-optimize/optimizer.c | 6 +++--- src/fseccomp/main.c | 2 +- src/fseccomp/seccomp_secondary.c | 2 +- src/include/seccomp.h | 10 ++++----- 8 files changed, 63 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c index a2aaa86eb..c3d3bd72c 100644 --- a/src/firejail/sbox.c +++ b/src/firejail/sbox.c @@ -120,7 +120,7 @@ static int __attribute__((noreturn)) sbox_do_exec_v(unsigned filtermask, char * // handle X32 ABI BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, X32_SYSCALL_BIT, 1, 0), BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 1, 0), - RETURN_ERRNO(EPERM), + KILL_OR_RETURN_ERRNO, #endif // syscall list diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index e47e6c910..808dd4c37 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c @@ -208,7 +208,7 @@ int seccomp_filter_drop(bool native) { // - seccomp if (cfg.seccomp_list_drop == NULL) { // default seccomp if error action is not changed - if (cfg.seccomp_list == NULL && cfg.seccomp_error_action) { + if (cfg.seccomp_list == NULL && arg_seccomp_error_action == DEFAULT_SECCOMP_ERROR_ACTION) { if (arg_seccomp_block_secondary) seccomp_filter_block_secondary(); else { @@ -221,11 +221,29 @@ int seccomp_filter_drop(bool native) { } // default seccomp filter with additional drop list else { // cfg.seccomp_list != NULL - if (arg_seccomp_block_secondary) + int rv; + + if (arg_seccomp_block_secondary) { + if (arg_seccomp_error_action != DEFAULT_SECCOMP_ERROR_ACTION) { + if (arg_debug) + printf("Rebuild secondary block seccomp filter\n"); + rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4, + PATH_FSECCOMP, "secondary", "block", RUN_SECCOMP_BLOCK_SECONDARY); + if (rv) + exit(rv); + } seccomp_filter_block_secondary(); - else { + } else { #if defined(__x86_64__) #if defined(__LP64__) + if (arg_seccomp_error_action != DEFAULT_SECCOMP_ERROR_ACTION) { + if (arg_debug) + printf("Rebuild 32 bit seccomp filter\n"); + rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4, + PATH_FSECCOMP, "secondary", "32", RUN_SECCOMP_32); + if (rv) + exit(rv); + } seccomp_filter_32(); #endif #endif @@ -242,16 +260,22 @@ int seccomp_filter_drop(bool native) { list = cfg.seccomp_list32; } - if (list == NULL) - list = ""; // build the seccomp filter as a regular user - int rv; - if (arg_allow_debuggers) - rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 7, - PATH_FSECCOMP, command, "drop", filter, postexec_filter, list, "allow-debuggers"); + if (list) + if (arg_allow_debuggers) + rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 7, + PATH_FSECCOMP, command, "drop", filter, postexec_filter, list, "allow-debuggers"); + else + rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 6, + PATH_FSECCOMP, command, "drop", filter, postexec_filter, list); else - rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 6, - PATH_FSECCOMP, command, "drop", filter, postexec_filter, list); + if (arg_allow_debuggers) + rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4, + PATH_FSECCOMP, command, filter, "allow-debuggers"); + else + rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, + PATH_FSECCOMP, command, filter); + if (rv) exit(rv); diff --git a/src/fsec-optimize/Makefile.in b/src/fsec-optimize/Makefile.in index b6a28fdd8..cc5ac7e35 100644 --- a/src/fsec-optimize/Makefile.in +++ b/src/fsec-optimize/Makefile.in @@ -6,7 +6,7 @@ include ../common.mk $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ fsec-optimize: $(OBJS) ../lib/common.o ../lib/libnetlink.o - $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o $(LIBS) $(EXTRA_LDFLAGS) clean:; rm -fr *.o fsec-optimize *.gcov *.gcda *.gcno *.plist diff --git a/src/fsec-optimize/main.c b/src/fsec-optimize/main.c index 74aebc9e0..c64587068 100644 --- a/src/fsec-optimize/main.c +++ b/src/fsec-optimize/main.c @@ -18,6 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "fsec_optimize.h" +#include "../include/syscall.h" + +int arg_seccomp_error_action = SECCOMP_RET_ERRNO | EPERM; // error action: errno, log or kill static void usage(void) { printf("Usage:\n"); @@ -46,6 +49,20 @@ printf("\n"); warn_dumpable(); + 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 if (strcmp(error_action, "log") == 0) + arg_seccomp_error_action = SECCOMP_RET_LOG; + 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; + } + } + char *fname = argv[1]; // open input file diff --git a/src/fsec-optimize/optimizer.c b/src/fsec-optimize/optimizer.c index 776beaa75..eb777f13b 100644 --- a/src/fsec-optimize/optimizer.c +++ b/src/fsec-optimize/optimizer.c @@ -33,7 +33,7 @@ static inline int is_blacklist(struct sock_filter *bpf) { if (bpf->code == BPF_JMP + BPF_JEQ + BPF_K && (bpf + 1)->code == BPF_RET + BPF_K && - (bpf + 1)->k == SECCOMP_RET_KILL ) + (bpf + 1)->k == (__u32)arg_seccomp_error_action) return 1; return 0; } @@ -89,9 +89,9 @@ static int optimize_blacklists(struct sock_filter *filter, int entries) { } } - // step 3: add the new ret KILL, and recalculate entries + // step 3: add the new ret KILL/LOG/ERRNO, and recalculate entries filter_step2[j].code = BPF_RET + BPF_K; - filter_step2[j].k = SECCOMP_RET_KILL; + filter_step2[j].k = arg_seccomp_error_action; entries = j + 1; // step 4: recalculate jumps diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c index c8259b079..f47efb5e8 100644 --- a/src/fseccomp/main.c +++ b/src/fseccomp/main.c @@ -20,7 +20,7 @@ #include "fseccomp.h" #include "../include/seccomp.h" int arg_quiet = 0; -int arg_seccomp_error_action = EPERM; // error action: errno, log or kill +int arg_seccomp_error_action = SECCOMP_RET_ERRNO | EPERM; // error action: errno, log or kill static void usage(void) { printf("Usage:\n"); diff --git a/src/fseccomp/seccomp_secondary.c b/src/fseccomp/seccomp_secondary.c index f024859d3..b8e8d0a89 100644 --- a/src/fseccomp/seccomp_secondary.c +++ b/src/fseccomp/seccomp_secondary.c @@ -126,7 +126,7 @@ void seccomp_secondary_block(const char *fname) { EXAMINE_SYSCALL, #if defined(__x86_64__) // block x32 - HANDLE_X32_KILL, + HANDLE_X32, #endif // block personality(2) where domain != PER_LINUX or 0xffffffff (query current personality) // 0: if personality(2), continue to 1, else goto 7 (allow) diff --git a/src/include/seccomp.h b/src/include/seccomp.h index 90db16d39..b3b75c2d1 100644 --- a/src/include/seccomp.h +++ b/src/include/seccomp.h @@ -201,7 +201,7 @@ #define VALIDATE_ARCHITECTURE_KILL \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) + KILL_OR_RETURN_ERRNO #define VALIDATE_ARCHITECTURE_64 \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ @@ -222,11 +222,7 @@ #define HANDLE_X32 \ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, X32_SYSCALL_BIT, 1, 0), \ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 1, 0), \ - RETURN_ERRNO(EPERM) -#define HANDLE_X32_KILL \ - BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, X32_SYSCALL_BIT, 1, 0), \ - BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 1, 0), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) + KILL_OR_RETURN_ERRNO #endif #define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ @@ -258,6 +254,8 @@ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr) extern int arg_seccomp_error_action; // error action: errno, log or kill +#define DEFAULT_SECCOMP_ERROR_ACTION EPERM + #define KILL_OR_RETURN_ERRNO \ BPF_STMT(BPF_RET+BPF_K, arg_seccomp_error_action) -- cgit v1.2.3-70-g09d2