diff --git a/src/core/execute.c b/src/core/execute.c index 8ac69d1..ffb92dd 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1415,7 +1415,7 @@ static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_ return r; } - return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action); + return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action, false); } static int apply_syscall_archs(const Unit *u, const ExecContext *c) { @@ -1498,7 +1498,7 @@ static int apply_protect_kernel_modules(const Unit *u, const ExecContext *c) { if (skip_seccomp_unavailable(u, "ProtectKernelModules=")) return 0; - return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM)); + return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM), false); } static int apply_private_devices(const Unit *u, const ExecContext *c) { @@ -1513,7 +1513,7 @@ static int apply_private_devices(const Unit *u, const ExecContext *c) { if (skip_seccomp_unavailable(u, "PrivateDevices=")) return 0; - return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM)); + return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM), false); } static int apply_restrict_namespaces(const Unit *u, const ExecContext *c) { diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c index eb1964b..b56c5b0 100644 --- a/src/nspawn/nspawn-seccomp.c +++ b/src/nspawn/nspawn-seccomp.c @@ -148,7 +148,7 @@ static int seccomp_add_default_syscall_filter( if (whitelist[i].capability != 0 && (cap_list_retain & (1ULL << whitelist[i].capability)) == 0) continue; - r = seccomp_add_syscall_filter_item(ctx, whitelist[i].name, SCMP_ACT_ALLOW, syscall_blacklist); + r = seccomp_add_syscall_filter_item(ctx, whitelist[i].name, SCMP_ACT_ALLOW, syscall_blacklist, false); if (r < 0) /* If the system call is not known on this architecture, then that's fine, let's ignore it */ log_debug_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", whitelist[i].name, seccomp_arch_to_string(arch)); @@ -157,7 +157,7 @@ static int seccomp_add_default_syscall_filter( } STRV_FOREACH(p, syscall_whitelist) { - r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist); + r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist, false); if (r < 0) log_debug_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", *p, seccomp_arch_to_string(arch)); else diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index c433cb9..92910ac 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -857,11 +857,9 @@ const SyscallFilterSet *syscall_filter_set_find(const char *name) { return NULL; } -static int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action, char **exclude); - -int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, uint32_t action, char **exclude) { - int r; +static int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action, char **exclude, bool log_missing); +int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, uint32_t action, char **exclude, bool log_missing) { assert(seccomp); assert(name); @@ -877,32 +875,36 @@ int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, return -EINVAL; } - r = seccomp_add_syscall_filter_set(seccomp, other, action, exclude); - if (r < 0) - return r; + return seccomp_add_syscall_filter_set(seccomp, other, action, exclude, log_missing); + } else { - int id; + int id, r; id = seccomp_syscall_resolve_name(name); if (id == __NR_SCMP_ERROR) { - log_debug("System call %s is not known, ignoring.", name); + if (log_missing) + log_debug("System call %s is not known, ignoring.", name); return 0; } r = seccomp_rule_add_exact(seccomp, action, id, 0); - if (r < 0) + if (r < 0) { /* If the system call is not known on this architecture, then that's fine, let's ignore it */ - log_debug_errno(r, "Failed to add rule for system call %s() / %d, ignoring: %m", name, id); - } + if (log_missing) + log_debug_errno(r, "Failed to add rule for system call %s() / %d, ignoring: %m", + name, id); + } - return 0; + return 0; + } } static int seccomp_add_syscall_filter_set( scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action, - char **exclude) { + char **exclude, + bool log_missing) { const char *sys; int r; @@ -911,7 +913,7 @@ static int seccomp_add_syscall_filter_set( assert(set); NULSTR_FOREACH(sys, set->value) { - r = seccomp_add_syscall_filter_item(seccomp, sys, action, exclude); + r = seccomp_add_syscall_filter_item(seccomp, sys, action, exclude, log_missing); if (r < 0) return r; } @@ -919,7 +921,7 @@ static int seccomp_add_syscall_filter_set( return 0; } -int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action) { +int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action, bool log_missing) { uint32_t arch; int r; @@ -937,7 +939,7 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter if (r < 0) return r; - r = seccomp_add_syscall_filter_set(seccomp, set, action, NULL); + r = seccomp_add_syscall_filter_set(seccomp, set, action, NULL, log_missing); if (r < 0) { log_debug_errno(r, "Failed to add filter set, ignoring: %m"); continue; @@ -953,7 +955,7 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter return 0; } -int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action) { +int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action, bool log_missing) { uint32_t arch; int r; @@ -966,7 +968,7 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u SECCOMP_FOREACH_LOCAL_ARCH(arch) { _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; Iterator i; - void *id, *val; + void *syscall_id, *val; log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); @@ -974,20 +976,23 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u if (r < 0) return r; - HASHMAP_FOREACH_KEY(val, id, set, i) { + HASHMAP_FOREACH_KEY(val, syscall_id, set, i) { uint32_t a = action; - int e = PTR_TO_INT(val); + int id = PTR_TO_INT(syscall_id) - 1; + int error = PTR_TO_INT(val); - if (action != SCMP_ACT_ALLOW && e >= 0) - a = SCMP_ACT_ERRNO(e); + if (action != SCMP_ACT_ALLOW && error >= 0) + a = SCMP_ACT_ERRNO(error); - r = seccomp_rule_add_exact(seccomp, a, PTR_TO_INT(id) - 1, 0); + r = seccomp_rule_add_exact(seccomp, a, id, 0); if (r < 0) { /* If the system call is not known on this architecture, then that's fine, let's ignore it */ _cleanup_free_ char *n = NULL; - n = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1); - log_debug_errno(r, "Failed to add rule for system call %s() / %d, ignoring: %m", strna(n), PTR_TO_INT(id) - 1); + n = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, id); + if (log_missing) + log_debug_errno(r, "Failed to add rule for system call %s() / %d, ignoring: %m", + strna(n), id); } } diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index eac857a..d8a36c4 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -58,10 +58,10 @@ const SyscallFilterSet *syscall_filter_set_find(const char *name); int seccomp_filter_set_add(Hashmap *s, bool b, const SyscallFilterSet *set); -int seccomp_add_syscall_filter_item(scmp_filter_ctx *ctx, const char *name, uint32_t action, char **exclude); +int seccomp_add_syscall_filter_item(scmp_filter_ctx *ctx, const char *name, uint32_t action, char **exclude, bool log_missing); -int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action); -int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action); +int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action, bool log_missing); +int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action, bool log_missing); typedef enum SeccompParseFlags { SECCOMP_PARSE_INVERT = 1 << 0, diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c index d82cb5c..d177515 100644 --- a/src/test/test-seccomp.c +++ b/src/test/test-seccomp.c @@ -104,11 +104,11 @@ static void test_filter_sets(void) { if (pid == 0) { /* Child? */ int fd; - /* if we look at the default set (or one that includes it), whitelist instead of blacklist */ + /* If we look at the default set (or one that includes it), whitelist instead of blacklist */ if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_SYSTEM_SERVICE)) - r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW); + r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW, true); else - r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN)); + r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN), true); if (r < 0) _exit(EXIT_FAILURE); @@ -515,7 +515,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(access("/", F_OK) >= 0); assert_se(poll(NULL, 0, 0) == 0); - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL, true) >= 0); assert_se(access("/", F_OK) >= 0); assert_se(poll(NULL, 0, 0) == 0); @@ -526,7 +526,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0); #endif - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0); assert_se(access("/", F_OK) < 0); assert_se(errno == EUCLEAN); @@ -542,7 +542,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0); #endif - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0); assert_se(access("/", F_OK) < 0); assert_se(errno == EILSEQ); @@ -558,7 +558,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0); #endif - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0); assert_se(access("/", F_OK) < 0); assert_se(errno == EILSEQ); @@ -575,7 +575,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0); #endif - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0); assert_se(access("/", F_OK) < 0); assert_se(errno == EILSEQ);