]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
analyze: split out "syscall-filter" verb
authorLennart Poettering <lennart@poettering.net>
Mon, 21 Feb 2022 09:30:53 +0000 (10:30 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 21 Feb 2022 16:22:23 +0000 (17:22 +0100)
src/analyze/analyze-syscall-filter.c [new file with mode: 0644]
src/analyze/analyze-syscall-filter.h [new file with mode: 0644]
src/analyze/analyze.c
src/analyze/meson.build

diff --git a/src/analyze/analyze-syscall-filter.c b/src/analyze/analyze-syscall-filter.c
new file mode 100644 (file)
index 0000000..eea7a98
--- /dev/null
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "analyze-syscall-filter.h"
+#include "analyze.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "nulstr-util.h"
+#include "seccomp-util.h"
+#include "set.h"
+#include "strv.h"
+#include "terminal-util.h"
+
+#if HAVE_SECCOMP
+
+static int load_kernel_syscalls(Set **ret) {
+        _cleanup_set_free_ Set *syscalls = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        int r;
+
+        /* Let's read the available system calls from the list of available tracing events. Slightly dirty,
+         * but good enough for analysis purposes. */
+
+        f = fopen("/sys/kernel/tracing/available_events", "re");
+        if (!f) {
+                /* We tried the non-debugfs mount point and that didn't work. If it wasn't mounted, maybe the
+                 * old debugfs mount point works? */
+                f = fopen("/sys/kernel/debug/tracing/available_events", "re");
+                if (!f)
+                        return log_full_errno(IN_SET(errno, EPERM, EACCES, ENOENT) ? LOG_DEBUG : LOG_WARNING, errno,
+                                              "Can't read open tracefs' available_events file: %m");
+        }
+
+        for (;;) {
+                _cleanup_free_ char *line = NULL;
+                const char *e;
+
+                r = read_line(f, LONG_LINE_MAX, &line);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to read system call list: %m");
+                if (r == 0)
+                        break;
+
+                e = startswith(line, "syscalls:sys_enter_");
+                if (!e)
+                        continue;
+
+                /* These are named differently inside the kernel than their external name for historical
+                 * reasons. Let's hide them here. */
+                if (STR_IN_SET(e, "newuname", "newfstat", "newstat", "newlstat", "sysctl"))
+                        continue;
+
+                r = set_put_strdup(&syscalls, e);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to add system call to list: %m");
+        }
+
+        *ret = TAKE_PTR(syscalls);
+        return 0;
+}
+
+static void syscall_set_remove(Set *s, const SyscallFilterSet *set) {
+        const char *syscall;
+
+        if (!set)
+                return;
+
+        NULSTR_FOREACH(syscall, set->value) {
+                if (syscall[0] == '@')
+                        continue;
+
+                free(set_remove(s, syscall));
+        }
+}
+
+static void dump_syscall_filter(const SyscallFilterSet *set) {
+        const char *syscall;
+
+        printf("%s%s%s\n"
+               "    # %s\n",
+               ansi_highlight(),
+               set->name,
+               ansi_normal(),
+               set->help);
+
+        NULSTR_FOREACH(syscall, set->value)
+                printf("    %s%s%s\n", syscall[0] == '@' ? ansi_underline() : "", syscall, ansi_normal());
+}
+
+int dump_syscall_filters(int argc, char *argv[], void *userdata) {
+        bool first = true;
+
+        pager_open(arg_pager_flags);
+
+        if (strv_isempty(strv_skip(argv, 1))) {
+                _cleanup_set_free_ Set *kernel = NULL, *known = NULL;
+                const char *sys;
+                int k = 0;  /* explicit initialization to appease gcc */
+
+                NULSTR_FOREACH(sys, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value)
+                        if (set_put_strdup(&known, sys) < 0)
+                                return log_oom();
+
+                if (!arg_quiet)
+                        k = load_kernel_syscalls(&kernel);
+
+                for (int i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
+                        const SyscallFilterSet *set = syscall_filter_sets + i;
+                        if (!first)
+                                puts("");
+
+                        dump_syscall_filter(set);
+                        syscall_set_remove(kernel, set);
+                        if (i != SYSCALL_FILTER_SET_KNOWN)
+                                syscall_set_remove(known, set);
+                        first = false;
+                }
+
+                if (arg_quiet)  /* Let's not show the extra stuff in quiet mode */
+                        return 0;
+
+                if (!set_isempty(known)) {
+                        _cleanup_free_ char **l = NULL;
+                        char **syscall;
+
+                        printf("\n"
+                               "# %sUngrouped System Calls%s (known but not included in any of the groups except @known):\n",
+                               ansi_highlight(), ansi_normal());
+
+                        l = set_get_strv(known);
+                        if (!l)
+                                return log_oom();
+
+                        strv_sort(l);
+
+                        STRV_FOREACH(syscall, l)
+                                printf("#   %s\n", *syscall);
+                }
+
+                if (k < 0) {
+                        fputc('\n', stdout);
+                        fflush(stdout);
+                        if (!arg_quiet)
+                                log_notice_errno(k, "# Not showing unlisted system calls, couldn't retrieve kernel system call list: %m");
+                } else if (!set_isempty(kernel)) {
+                        _cleanup_free_ char **l = NULL;
+                        char **syscall;
+
+                        printf("\n"
+                               "# %sUnlisted System Calls%s (supported by the local kernel, but not included in any of the groups listed above):\n",
+                               ansi_highlight(), ansi_normal());
+
+                        l = set_get_strv(kernel);
+                        if (!l)
+                                return log_oom();
+
+                        strv_sort(l);
+
+                        STRV_FOREACH(syscall, l)
+                                printf("#   %s\n", *syscall);
+                }
+        } else {
+                char **name;
+
+                STRV_FOREACH(name, strv_skip(argv, 1)) {
+                        const SyscallFilterSet *set;
+
+                        if (!first)
+                                puts("");
+
+                        set = syscall_filter_set_find(*name);
+                        if (!set) {
+                                /* make sure the error appears below normal output */
+                                fflush(stdout);
+
+                                return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+                                                       "Filter set \"%s\" not found.", *name);
+                        }
+
+                        dump_syscall_filter(set);
+                        first = false;
+                }
+        }
+
+        return 0;
+}
+
+#else
+int dump_syscall_filters(int argc, char *argv[], void *userdata) {
+        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Not compiled with syscall filters, sorry.");
+}
+#endif
diff --git a/src/analyze/analyze-syscall-filter.h b/src/analyze/analyze-syscall-filter.h
new file mode 100644 (file)
index 0000000..3704875
--- /dev/null
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+int dump_syscall_filters(int argc, char *argv[], void *userdata);
index 2af62f48c4dbb0eafbebcb4c238d878d209dad1c..a9288c336c3877a4f52a1e649c5c31296d33cefa 100644 (file)
@@ -18,6 +18,7 @@
 #include "analyze-elf.h"
 #include "analyze-filesystems.h"
 #include "analyze-security.h"
+#include "analyze-syscall-filter.h"
 #include "analyze-timespan.h"
 #include "analyze-timestamp.h"
 #include "analyze-verify.h"
@@ -1632,187 +1633,6 @@ static int dump_capabilities(int argc, char *argv[], void *userdata) {
         return table_print(table, NULL);
 }
 
-#if HAVE_SECCOMP
-
-static int load_kernel_syscalls(Set **ret) {
-        _cleanup_set_free_ Set *syscalls = NULL;
-        _cleanup_fclose_ FILE *f = NULL;
-        int r;
-
-        /* Let's read the available system calls from the list of available tracing events. Slightly dirty,
-         * but good enough for analysis purposes. */
-
-        f = fopen("/sys/kernel/tracing/available_events", "re");
-        if (!f) {
-                /* We tried the non-debugfs mount point and that didn't work. If it wasn't mounted, maybe the
-                 * old debugfs mount point works? */
-                f = fopen("/sys/kernel/debug/tracing/available_events", "re");
-                if (!f)
-                        return log_full_errno(IN_SET(errno, EPERM, EACCES, ENOENT) ? LOG_DEBUG : LOG_WARNING, errno,
-                                              "Can't read open tracefs' available_events file: %m");
-        }
-
-        for (;;) {
-                _cleanup_free_ char *line = NULL;
-                const char *e;
-
-                r = read_line(f, LONG_LINE_MAX, &line);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to read system call list: %m");
-                if (r == 0)
-                        break;
-
-                e = startswith(line, "syscalls:sys_enter_");
-                if (!e)
-                        continue;
-
-                /* These are named differently inside the kernel than their external name for historical
-                 * reasons. Let's hide them here. */
-                if (STR_IN_SET(e, "newuname", "newfstat", "newstat", "newlstat", "sysctl"))
-                        continue;
-
-                r = set_put_strdup(&syscalls, e);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to add system call to list: %m");
-        }
-
-        *ret = TAKE_PTR(syscalls);
-        return 0;
-}
-
-static void syscall_set_remove(Set *s, const SyscallFilterSet *set) {
-        const char *syscall;
-
-        if (!set)
-                return;
-
-        NULSTR_FOREACH(syscall, set->value) {
-                if (syscall[0] == '@')
-                        continue;
-
-                free(set_remove(s, syscall));
-        }
-}
-
-static void dump_syscall_filter(const SyscallFilterSet *set) {
-        const char *syscall;
-
-        printf("%s%s%s\n"
-               "    # %s\n",
-               ansi_highlight(),
-               set->name,
-               ansi_normal(),
-               set->help);
-
-        NULSTR_FOREACH(syscall, set->value)
-                printf("    %s%s%s\n", syscall[0] == '@' ? ansi_underline() : "", syscall, ansi_normal());
-}
-
-static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
-        bool first = true;
-
-        pager_open(arg_pager_flags);
-
-        if (strv_isempty(strv_skip(argv, 1))) {
-                _cleanup_set_free_ Set *kernel = NULL, *known = NULL;
-                const char *sys;
-                int k = 0;  /* explicit initialization to appease gcc */
-
-                NULSTR_FOREACH(sys, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value)
-                        if (set_put_strdup(&known, sys) < 0)
-                                return log_oom();
-
-                if (!arg_quiet)
-                        k = load_kernel_syscalls(&kernel);
-
-                for (int i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
-                        const SyscallFilterSet *set = syscall_filter_sets + i;
-                        if (!first)
-                                puts("");
-
-                        dump_syscall_filter(set);
-                        syscall_set_remove(kernel, set);
-                        if (i != SYSCALL_FILTER_SET_KNOWN)
-                                syscall_set_remove(known, set);
-                        first = false;
-                }
-
-                if (arg_quiet)  /* Let's not show the extra stuff in quiet mode */
-                        return 0;
-
-                if (!set_isempty(known)) {
-                        _cleanup_free_ char **l = NULL;
-                        char **syscall;
-
-                        printf("\n"
-                               "# %sUngrouped System Calls%s (known but not included in any of the groups except @known):\n",
-                               ansi_highlight(), ansi_normal());
-
-                        l = set_get_strv(known);
-                        if (!l)
-                                return log_oom();
-
-                        strv_sort(l);
-
-                        STRV_FOREACH(syscall, l)
-                                printf("#   %s\n", *syscall);
-                }
-
-                if (k < 0) {
-                        fputc('\n', stdout);
-                        fflush(stdout);
-                        if (!arg_quiet)
-                                log_notice_errno(k, "# Not showing unlisted system calls, couldn't retrieve kernel system call list: %m");
-                } else if (!set_isempty(kernel)) {
-                        _cleanup_free_ char **l = NULL;
-                        char **syscall;
-
-                        printf("\n"
-                               "# %sUnlisted System Calls%s (supported by the local kernel, but not included in any of the groups listed above):\n",
-                               ansi_highlight(), ansi_normal());
-
-                        l = set_get_strv(kernel);
-                        if (!l)
-                                return log_oom();
-
-                        strv_sort(l);
-
-                        STRV_FOREACH(syscall, l)
-                                printf("#   %s\n", *syscall);
-                }
-        } else {
-                char **name;
-
-                STRV_FOREACH(name, strv_skip(argv, 1)) {
-                        const SyscallFilterSet *set;
-
-                        if (!first)
-                                puts("");
-
-                        set = syscall_filter_set_find(*name);
-                        if (!set) {
-                                /* make sure the error appears below normal output */
-                                fflush(stdout);
-
-                                return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
-                                                       "Filter set \"%s\" not found.", *name);
-                        }
-
-                        dump_syscall_filter(set);
-                        first = false;
-                }
-        }
-
-        return 0;
-}
-
-#else
-static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
-        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Not compiled with syscall filters, sorry.");
-}
-#endif
-
-
 void time_parsing_hint(const char *p, bool calendar, bool timestamp, bool timespan) {
         if (calendar && calendar_spec_from_string(p, NULL) >= 0)
                 log_notice("Hint: this expression is a valid calendar specification. "
index f5950c1feb46bb9ea9e2fd2b5047782a185e5bff..00197d312928b6658c1d47cdd466e44997e3ed11 100644 (file)
@@ -11,6 +11,8 @@ systemd_analyze_sources = files('''
         analyze-filesystems.h
         analyze-security.c
         analyze-security.h
+        analyze-syscall-filter.c
+        analyze-syscall-filter.h
         analyze-timespan.c
         analyze-timespan.h
         analyze-timestamp.c