From cdf6258c2ee414b38b4a6f63a635acbe709ac524 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Nov 2018 19:40:45 +0100 Subject: [PATCH 1/3] analyze: show list of syscalls the kernel supports but not included in any group in the output This is quite useful for making sure our list is complete. --- src/analyze/analyze.c | 81 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 0c53a8e21f3..89f0891b868 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -21,6 +21,7 @@ #include "conf-files.h" #include "copy.h" #include "fd-util.h" +#include "fileio.h" #include "glob-util.h" #include "hashmap.h" #include "locale-util.h" @@ -1497,6 +1498,61 @@ static int dump_unit_paths(int argc, char *argv[], void *userdata) { } #if HAVE_SECCOMP + +static int load_kernel_syscalls(Set **ret) { + _cleanup_(set_free_freep) 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/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 /sys/kernel/debug/tracing/available_events: %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_ensure_allocated(&syscalls, &string_hash_ops); + if (r < 0) + return log_oom(); + + 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 kernel_syscalls_remove(Set *s, const SyscallFilterSet *set) { + const char *syscall; + + NULSTR_FOREACH(syscall, set->value) { + if (syscall[0] == '@') + continue; + + (void) set_remove(s, syscall); + } +} + static void dump_syscall_filter(const SyscallFilterSet *set) { const char *syscall; @@ -1512,14 +1568,35 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) { (void) pager_open(arg_pager_flags); if (strv_isempty(strv_skip(argv, 1))) { - int i; + _cleanup_(set_free_freep) Set *kernel = NULL; + int i, k; + + k = load_kernel_syscalls(&kernel); for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { + const SyscallFilterSet *set = syscall_filter_sets + i; if (!first) puts(""); - dump_syscall_filter(syscall_filter_sets + i); + + dump_syscall_filter(set); + kernel_syscalls_remove(kernel, set); first = false; } + + if (k < 0) { + fputc('\n', stdout); + fflush(stdout); + log_notice_errno(k, "# Not showing unlisted system calls, couldn't retrieve kernel system call list: %m"); + } else if (!set_isempty(kernel)) { + const char *syscall; + Iterator j; + + printf("\n" + "# Unlisted System Calls (supported by the local kernel, but not included in any of the groups listed above):\n"); + + SET_FOREACH(syscall, kernel, j) + printf("# %s\n", syscall); + } } else { char **name; From a05cfe230f7c65e1fb7e84453f308ad91af9c65f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Nov 2018 19:53:49 +0100 Subject: [PATCH 2/3] seccomp: add some missing syscalls to filter sets --- src/shared/seccomp-util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 54280f59169..e00001288da 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -308,6 +308,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "io_cancel\0" "io_destroy\0" "io_getevents\0" + "io_pgetevents\0" "io_setup\0" "io_submit\0" }, @@ -619,7 +620,9 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "bpf\0" "capset\0" "chroot\0" + "fanotify_init\0" "nfsservctl\0" + "open_by_handle_at\0" "pivot_root\0" "quotactl\0" "setdomainname\0" From a9bfb3eff2859dd2d187fc38308bfc05b270c869 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Nov 2018 19:59:27 +0100 Subject: [PATCH 3/3] analyze: add some minimal ANSI highlighting of syscall-filter output --- src/analyze/analyze.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 89f0891b868..f82c5023d52 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -1556,10 +1556,18 @@ static void kernel_syscalls_remove(Set *s, const SyscallFilterSet *set) { static void dump_syscall_filter(const SyscallFilterSet *set) { const char *syscall; - printf("%s\n", set->name); - printf(" # %s\n", set->help); + printf("%s%s%s\n" + " # %s\n", + ansi_highlight(), + set->name, + ansi_normal(), + set->help); + NULSTR_FOREACH(syscall, set->value) - printf(" %s\n", syscall); + printf(" %s%s%s\n", + syscall[0] == '@' ? ansi_underline() : "", + syscall, + ansi_normal()); } static int dump_syscall_filters(int argc, char *argv[], void *userdata) { @@ -1592,7 +1600,8 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) { Iterator j; printf("\n" - "# Unlisted System Calls (supported by the local kernel, but not included in any of the groups listed above):\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()); SET_FOREACH(syscall, kernel, j) printf("# %s\n", syscall);