From 95aac01259db689dac7d8e5bfafb60e8c70cd734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 19 Aug 2020 17:43:23 +0200 Subject: [PATCH] shared: add @known syscall list --- man/systemd.exec.xml | 4 ++++ src/shared/generate-syscall-list.py | 5 +++++ src/shared/meson.build | 11 +++++++++++ src/shared/seccomp-util.c | 6 ++++++ src/shared/seccomp-util.h | 3 ++- src/test/test-seccomp.c | 17 +++++++++++------ 6 files changed, 39 insertions(+), 7 deletions(-) create mode 100755 src/shared/generate-syscall-list.py diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index c339f3b885..6338d8948c 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1933,6 +1933,10 @@ RestrictNamespaces=~cgroup net @timer System calls for scheduling operations by time (alarm2, timer_create2, …) + + @known + All system calls defined by the kernel. This list is defined statically in systemd based on a kernel version that was available when this systmed version was released. It will become progressively more out-of-date as the kernel is updated. + diff --git a/src/shared/generate-syscall-list.py b/src/shared/generate-syscall-list.py new file mode 100755 index 0000000000..13a6ae9241 --- /dev/null +++ b/src/shared/generate-syscall-list.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +import sys + +for line in open(sys.argv[1]): + print('"{}\\0"'.format(line.strip())) diff --git a/src/shared/meson.build b/src/shared/meson.build index d3331bc658..bc97a6df6f 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -262,6 +262,16 @@ endif test_tables_h = files('test-tables.h') shared_sources += test_tables_h +generate_syscall_list = find_program('generate-syscall-list.py') +fname = 'syscall-list.h' +syscall_list_h = custom_target( + fname, + input : 'syscall-names.text', + output : fname, + command : [generate_syscall_list, + '@INPUT@'], + capture : true) + if conf.get('HAVE_ACL') == 1 shared_sources += files('acl-util.c') endif @@ -272,6 +282,7 @@ endif if conf.get('HAVE_SECCOMP') == 1 shared_sources += files('seccomp-util.c') + shared_sources += syscall_list_h endif if conf.get('HAVE_LIBIPTC') == 1 diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 4dee044810..b21d997b9f 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -883,6 +883,12 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "timerfd_settime64\0" "times\0" }, + [SYSCALL_FILTER_SET_KNOWN] = { + .name = "@known", + .help = "All known syscalls declared in the kernel", + .value = +#include "syscall-list.h" + }, }; const SyscallFilterSet *syscall_filter_set_find(const char *name) { diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index ef970434c6..735eda80bd 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -21,7 +21,7 @@ typedef struct SyscallFilterSet { } SyscallFilterSet; enum { - /* Please leave DEFAULT first, but sort the rest alphabetically */ + /* Please leave DEFAULT first and KNOWN last, but sort the rest alphabetically */ SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_AIO, SYSCALL_FILTER_SET_BASIC_IO, @@ -50,6 +50,7 @@ enum { SYSCALL_FILTER_SET_SYNC, SYSCALL_FILTER_SET_SYSTEM_SERVICE, SYSCALL_FILTER_SET_TIMER, + SYSCALL_FILTER_SET_KNOWN, _SYSCALL_FILTER_SET_MAX }; diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c index cebf5a1080..ceb3fe7c81 100644 --- a/src/test/test-seccomp.c +++ b/src/test/test-seccomp.c @@ -121,7 +121,9 @@ static void test_filter_sets(void) { int fd, r; /* If we look at the default set (or one that includes it), allow-list instead of deny-list */ - if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_SYSTEM_SERVICE)) + if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, + SYSCALL_FILTER_SET_SYSTEM_SERVICE, + SYSCALL_FILTER_SET_KNOWN)) r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW, true); else r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN), true); @@ -145,22 +147,25 @@ static void test_filter_sets(void) { } static void test_filter_sets_ordered(void) { - size_t i; - log_info("/* %s */", __func__); /* Ensure "@default" always remains at the beginning of the list */ assert_se(SYSCALL_FILTER_SET_DEFAULT == 0); assert_se(streq(syscall_filter_sets[0].name, "@default")); - for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { + /* Ensure "@known" always remains at the end of the list */ + assert_se(SYSCALL_FILTER_SET_KNOWN == _SYSCALL_FILTER_SET_MAX - 1); + assert_se(streq(syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].name, "@known")); + + for (size_t i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { const char *k, *p = NULL; /* Make sure each group has a description */ assert_se(!isempty(syscall_filter_sets[0].help)); - /* Make sure the groups are ordered alphabetically, except for the first entry */ - assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0); + /* Make sure the groups are ordered alphabetically, except for the first and last entries */ + assert_se(i < 2 || i == _SYSCALL_FILTER_SET_MAX - 1 || + strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0); NULSTR_FOREACH(k, syscall_filter_sets[i].value) {