diff options
Diffstat (limited to 'src/test/test-seccomp.c')
-rw-r--r-- | src/test/test-seccomp.c | 205 |
1 files changed, 142 insertions, 63 deletions
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c index d82cb5c1c5..fbfeedd536 100644 --- a/src/test/test-seccomp.c +++ b/src/test/test-seccomp.c @@ -20,6 +20,7 @@ #include "seccomp-util.h" #include "set.h" #include "string-util.h" +#include "tests.h" #include "util.h" #include "virt.h" @@ -35,6 +36,8 @@ static void test_seccomp_arch_to_string(void) { uint32_t a, b; const char *name; + log_info("/* %s */", __func__); + a = seccomp_arch_native(); assert_se(a > 0); name = seccomp_arch_to_string(a); @@ -46,6 +49,8 @@ static void test_seccomp_arch_to_string(void) { static void test_architecture_table(void) { const char *n, *n2; + log_info("/* %s */", __func__); + NULSTR_FOREACH(n, "native\0" "x86\0" @@ -74,6 +79,8 @@ static void test_architecture_table(void) { } static void test_syscall_filter_set_find(void) { + log_info("/* %s */", __func__); + assert_se(!syscall_filter_set_find(NULL)); assert_se(!syscall_filter_set_find("")); assert_se(!syscall_filter_set_find("quux")); @@ -88,10 +95,16 @@ static void test_filter_sets(void) { unsigned i; int r; - if (!is_seccomp_available()) + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); return; + } for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { pid_t pid; @@ -104,11 +117,11 @@ static void test_filter_sets(void) { if (pid == 0) { /* Child? */ int fd; - /* if we look at the default set (or one that includes it), whitelist instead of blacklist */ + /* If we look at the default set (or one that includes it), whitelist instead of blacklist */ if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_SYSTEM_SERVICE)) - r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW); + 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)); + r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN), true); if (r < 0) _exit(EXIT_FAILURE); @@ -128,11 +141,50 @@ 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++) { + 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); + + NULSTR_FOREACH(k, syscall_filter_sets[i].value) { + + /* Ensure each syscall list is in itself ordered, but groups before names */ + assert_se(!p || + (*p == '@' && *k != '@') || + (((*p == '@' && *k == '@') || + (*p != '@' && *k != '@')) && + strcmp(p, k) < 0)); + + p = k; + } + } +} + static void test_restrict_namespace(void) { char *s = NULL; unsigned long ul; pid_t pid; + if (!have_namespaces()) { + log_notice("Testing without namespaces, skipping %s", __func__); + return; + } + + log_info("/* %s */", __func__); + assert_se(namespace_flags_to_string(0, &s) == 0 && streq(s, "")); s = mfree(s); assert_se(namespace_flags_to_string(CLONE_NEWNS, &s) == 0 && streq(s, "mnt")); @@ -160,10 +212,14 @@ static void test_restrict_namespace(void) { assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL); s = mfree(s); - if (!is_seccomp_available()) + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping remaining tests in %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping remaining tests in %s", __func__); return; + } pid = fork(); assert_se(pid >= 0); @@ -223,13 +279,22 @@ static void test_restrict_namespace(void) { static void test_protect_sysctl(void) { pid_t pid; - if (!is_seccomp_available()) + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); return; + } - if (detect_container() > 0) /* in containers _sysctl() is likely missing anyway */ + /* in containers _sysctl() is likely missing anyway */ + if (detect_container() > 0) { + log_notice("Testing in container, skipping %s", __func__); return; + } pid = fork(); assert_se(pid >= 0); @@ -256,10 +321,16 @@ static void test_protect_sysctl(void) { static void test_restrict_address_families(void) { pid_t pid; - if (!is_seccomp_available()) + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); return; + } pid = fork(); assert_se(pid >= 0); @@ -339,13 +410,22 @@ static void test_restrict_address_families(void) { static void test_restrict_realtime(void) { pid_t pid; - if (!is_seccomp_available()) + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); return; + } - if (detect_container() > 0) /* in containers RT privs are likely missing anyway */ + /* in containers RT privs are likely missing anyway */ + if (detect_container() > 0) { + log_notice("Testing in container, skipping %s", __func__); return; + } pid = fork(); assert_se(pid >= 0); @@ -377,10 +457,16 @@ static void test_restrict_realtime(void) { static void test_memory_deny_write_execute_mmap(void) { pid_t pid; - if (!is_seccomp_available()) + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); return; + } pid = fork(); assert_se(pid >= 0); @@ -421,10 +507,16 @@ static void test_memory_deny_write_execute_shmat(void) { int shmid; pid_t pid; - if (!is_seccomp_available()) + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); return; + } shmid = shmget(IPC_PRIVATE, page_size(), 0); assert_se(shmid >= 0); @@ -467,10 +559,16 @@ static void test_memory_deny_write_execute_shmat(void) { static void test_restrict_archs(void) { pid_t pid; - if (!is_seccomp_available()) + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); return; + } pid = fork(); assert_se(pid >= 0); @@ -501,10 +599,16 @@ static void test_restrict_archs(void) { static void test_load_syscall_filter_set_raw(void) { pid_t pid; - if (!is_seccomp_available()) + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); return; + } pid = fork(); assert_se(pid >= 0); @@ -515,7 +619,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(access("/", F_OK) >= 0); assert_se(poll(NULL, 0, 0) == 0); - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL, true) >= 0); assert_se(access("/", F_OK) >= 0); assert_se(poll(NULL, 0, 0) == 0); @@ -526,7 +630,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0); #endif - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0); assert_se(access("/", F_OK) < 0); assert_se(errno == EUCLEAN); @@ -542,7 +646,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0); #endif - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0); assert_se(access("/", F_OK) < 0); assert_se(errno == EILSEQ); @@ -558,7 +662,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0); #endif - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0); assert_se(access("/", F_OK) < 0); assert_se(errno == EILSEQ); @@ -575,7 +679,7 @@ static void test_load_syscall_filter_set_raw(void) { assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0); #endif - assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0); assert_se(access("/", F_OK) < 0); assert_se(errno == EILSEQ); @@ -593,10 +697,16 @@ static void test_lock_personality(void) { unsigned long current; pid_t pid; - if (!is_seccomp_available()) + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); return; - if (geteuid() != 0) + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); return; + } assert_se(opinionated_personality(¤t) >= 0); @@ -636,44 +746,14 @@ static void test_lock_personality(void) { assert_se(wait_for_terminate_and_check("lockpersonalityseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); } -static void test_filter_sets_ordered(void) { - size_t i; - - /* 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++) { - 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); - - NULSTR_FOREACH(k, syscall_filter_sets[i].value) { - - /* Ensure each syscall list is in itself ordered, but groups before names */ - assert_se(!p || - (*p == '@' && *k != '@') || - (((*p == '@' && *k == '@') || - (*p != '@' && *k != '@')) && - strcmp(p, k) < 0)); - - p = k; - } - } -} - int main(int argc, char *argv[]) { - - log_set_max_level(LOG_DEBUG); + test_setup_logging(LOG_DEBUG); test_seccomp_arch_to_string(); test_architecture_table(); test_syscall_filter_set_find(); test_filter_sets(); + test_filter_sets_ordered(); test_restrict_namespace(); test_protect_sysctl(); test_restrict_address_families(); @@ -683,7 +763,6 @@ int main(int argc, char *argv[]) { test_restrict_archs(); test_load_syscall_filter_set_raw(); test_lock_personality(); - test_filter_sets_ordered(); return 0; } |