]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
analyze-security: always save syscall name
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 15 Jun 2022 16:23:20 +0000 (01:23 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 17 Jun 2022 03:37:56 +0000 (12:37 +0900)
This reverts dd51e725df9aec2847482131ef601e0215b371a0 and fixes bugs
introduced by 1624114d74f55ad9791b7624b08d89d2339a68b3.

Previously,
- On online scan, the syscall filter was a string Hashmap, but it
  might contain syscall name with errno or error action. Hence, we need
  to drop the errno or error action in the string.
- On offline scan, the syscall filter was a Hashmap of syscall ID, so
  hashmap_contains() with syscall name did not work. We need to convert
  syscall IDs to syscall names.
- If hashmap_contains() in syscall_names_in_filter() is true, then
  the syscall is allowed when the list is an allow-list, and vice versa.
  Hence, the condition in syscall_names_in_filter() was errnously
  inverted by dd51e725df9aec2847482131ef601e0215b371a0.

This makes syscalls are always stored with its name, instead of ID,
and also correct the condition.

Fixes #23663.

src/analyze/analyze-security.c

index 5b4d4caf46af3e06c6241b755d826d1252ba2db1..9255f4cb896f8a8178229179553f8c8663c76987 100644 (file)
@@ -105,7 +105,7 @@ typedef struct SecurityInfo {
         Set *system_call_architectures;
 
         bool system_call_filter_allow_list;
-        Hashmap *system_call_filter;
+        Set *system_call_filter;
 
         mode_t _umask;
 } SecurityInfo;
@@ -172,8 +172,7 @@ static SecurityInfo *security_info_free(SecurityInfo *i) {
 
         strv_free(i->supplementary_groups);
         set_free(i->system_call_architectures);
-
-        hashmap_free(i->system_call_filter);
+        set_free(i->system_call_filter);
 
         return mfree(i);
 }
@@ -567,12 +566,10 @@ static int assess_system_call_architectures(
         return 0;
 }
 
-static bool syscall_names_in_filter(Hashmap *s, bool allow_list, const SyscallFilterSet *f, const char **ret_offending_syscall) {
+static bool syscall_names_in_filter(Set *s, bool allow_list, const SyscallFilterSet *f, const char **ret_offending_syscall) {
         const char *syscall;
 
         NULSTR_FOREACH(syscall, f->value) {
-                int id;
-
                 if (syscall[0] == '@') {
                         const SyscallFilterSet *g;
 
@@ -584,11 +581,10 @@ static bool syscall_names_in_filter(Hashmap *s, bool allow_list, const SyscallFi
                 }
 
                 /* Let's see if the system call actually exists on this platform, before complaining */
-                id = seccomp_syscall_resolve_name(syscall);
-                if (id < 0)
+                if (seccomp_syscall_resolve_name(syscall) < 0)
                         continue;
 
-                if (hashmap_contains(s, syscall) != allow_list) {
+                if (set_contains(s, syscall) == allow_list) {
                         log_debug("Offending syscall filter item: %s", syscall);
                         if (ret_offending_syscall)
                                 *ret_offending_syscall = syscall;
@@ -619,7 +615,7 @@ static int assess_system_call_filter(
         uint64_t b;
         int r;
 
-        if (!info->system_call_filter_allow_list && hashmap_isempty(info->system_call_filter)) {
+        if (!info->system_call_filter_allow_list && set_isempty(info->system_call_filter)) {
                 r = free_and_strdup(&d, "Service does not filter system calls");
                 b = 10;
         } else {
@@ -2139,9 +2135,8 @@ static int property_read_system_call_filter(
                 if (r == 0)
                         break;
 
-                /* The actual ExecContext stores the system call id as the map value, which we don't
-                 * need. So we assign NULL to all values here. */
-                r = hashmap_put_strdup(&info->system_call_filter, name, NULL);
+                /* ignore errno or action after colon */
+                r = set_put_strndup(&info->system_call_filter, name, strchrnul(name, ':') - name);
                 if (r < 0)
                         return r;
         }
@@ -2589,14 +2584,24 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
                         if (set_put_strdup(&info->system_call_architectures, name) < 0)
                                 return log_oom();
                 }
-#endif
 
                 info->system_call_filter_allow_list = c->syscall_allow_list;
-                if (c->syscall_filter) {
-                        info->system_call_filter = hashmap_copy(c->syscall_filter);
-                        if (!info->system_call_filter)
+
+                void *id, *num;
+                HASHMAP_FOREACH_KEY(num, id, c->syscall_filter) {
+                        _cleanup_free_ char *name = NULL;
+
+                        if (info->system_call_filter_allow_list && PTR_TO_INT(num) >= 0)
+                                continue;
+
+                        name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
+                        if (!name)
+                                continue;
+
+                        if (set_ensure_consume(&info->system_call_filter, &string_hash_ops_free, TAKE_PTR(name)) < 0)
                                 return log_oom();
                 }
+#endif
         }
 
         if (g) {