seccomp: tighten checking of seccomp filter creation
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 20 Sep 2018 12:19:41 +0000 (14:19 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 24 Sep 2018 15:21:09 +0000 (17:21 +0200)
In seccomp code, the code is changed to propagate errors which are about
anything other than unknown/unimplemented syscalls. I *think* such errors
should not happen in normal usage, but so far we would summarilly ignore all
errors, so that part is uncertain. If it turns out that other errors occur and
should be ignored, this should be added later.

In nspawn, we would count the number of added filters, but didn't use this for
anything. Drop that part.

The comments suggested that seccomp_add_syscall_filter_item() returned negative
if the syscall is unknown, but this wasn't true: it returns 0.

The error at this point can only be if the syscall was known but couldn't be
added. If the error comes from our internal whitelist in nspawn, treat this as
error, because it means that our internal table is wrong. If the error comes
from user arguments, warn and ignore. (If some syscall is not known at current
architecture, it is still silently ignored.)

src/nspawn/nspawn-seccomp.c
src/shared/seccomp-util.c

index b56c5b0..e7ef80f 100644 (file)
@@ -140,7 +140,7 @@ static int seccomp_add_default_syscall_filter(
                  */
         };
 
-        int r, c = 0;
+        int r;
         size_t i;
         char **p;
 
@@ -150,21 +150,17 @@ static int seccomp_add_default_syscall_filter(
 
                 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));
-                else
-                        c++;
+                        return log_error_errno(r, "Failed to add syscall filter item %s: %m", whitelist[i].name);
         }
 
         STRV_FOREACH(p, syscall_whitelist) {
                 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
-                        c++;
+                        log_warning_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m",
+                                          *p, seccomp_arch_to_string(arch));
         }
 
-        return c;
+        return 0;
 }
 
 int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **syscall_blacklist) {
index c69b0e8..ca55441 100644 (file)
@@ -891,9 +891,13 @@ int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name,
                 r = seccomp_rule_add_exact(seccomp, action, id, 0);
                 if (r < 0) {
                         /* If the system call is not known on this architecture, then that's fine, let's ignore it */
-                        if (log_missing)
-                                log_debug_errno(r, "Failed to add rule for system call %s() / %d, ignoring: %m",
-                                                name, id);
+                        bool ignore = r == -EDOM;
+
+                        if (!ignore || log_missing)
+                                log_debug_errno(r, "Failed to add rule for system call %s() / %d%s: %m",
+                                                name, id, ignore ? ", ignoring" : "");
+                        if (!ignore)
+                                return r;
                 }
 
                 return 0;
@@ -941,10 +945,8 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter
                         return r;
 
                 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;
-                }
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to add filter set: %m");
 
                 r = seccomp_load(seccomp);
                 if (IN_SET(r, -EPERM, -EACCES))
@@ -989,11 +991,15 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u
                         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;
+                                bool ignore;
 
                                 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);
+                                ignore = r == -EDOM;
+                                if (!ignore || log_missing)
+                                        log_debug_errno(r, "Failed to add rule for system call %s() / %d%s: %m",
+                                                        strna(n), id, ignore ? ", ignoring" : "");
+                                if (!ignore)
+                                        return r;
                         }
                 }