summaryrefslogtreecommitdiff
path: root/src/analyze
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyze')
-rw-r--r--src/analyze/analyze.c81
1 files changed, 79 insertions, 2 deletions
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 0c53a8e21f..89f0891b86 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;