LCOV - code coverage report
Current view: top level - test - test-seccomp.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 128 574 22.3 %
Date: 2019-08-22 15:41:25 Functions: 16 17 94.1 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <poll.h>
       4             : #include <sched.h>
       5             : #include <stdlib.h>
       6             : #include <sys/eventfd.h>
       7             : #include <sys/mman.h>
       8             : #include <sys/personality.h>
       9             : #include <sys/shm.h>
      10             : #include <sys/syscall.h>
      11             : #include <sys/types.h>
      12             : #include <unistd.h>
      13             : 
      14             : #include "alloc-util.h"
      15             : #include "fd-util.h"
      16             : #include "macro.h"
      17             : #include "memory-util.h"
      18             : #include "missing.h"
      19             : #include "nsflags.h"
      20             : #include "nulstr-util.h"
      21             : #include "process-util.h"
      22             : #include "raw-clone.h"
      23             : #include "rm-rf.h"
      24             : #include "seccomp-util.h"
      25             : #include "set.h"
      26             : #include "string-util.h"
      27             : #include "tests.h"
      28             : #include "tmpfile-util.h"
      29             : #include "virt.h"
      30             : 
      31             : #if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__)
      32             : /* On these archs, socket() is implemented via the socketcall() syscall multiplexer,
      33             :  * and we can't restrict it hence via seccomp. */
      34             : #  define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1
      35             : #else
      36             : #  define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0
      37             : #endif
      38             : 
      39           1 : static void test_seccomp_arch_to_string(void) {
      40             :         uint32_t a, b;
      41             :         const char *name;
      42             : 
      43           1 :         log_info("/* %s */", __func__);
      44             : 
      45           1 :         a = seccomp_arch_native();
      46           1 :         assert_se(a > 0);
      47           1 :         name = seccomp_arch_to_string(a);
      48           1 :         assert_se(name);
      49           1 :         assert_se(seccomp_arch_from_string(name, &b) >= 0);
      50           1 :         assert_se(a == b);
      51           1 : }
      52             : 
      53           1 : static void test_architecture_table(void) {
      54             :         const char *n, *n2;
      55             : 
      56           1 :         log_info("/* %s */", __func__);
      57             : 
      58          18 :         NULSTR_FOREACH(n,
      59             :                        "native\0"
      60             :                        "x86\0"
      61             :                        "x86-64\0"
      62             :                        "x32\0"
      63             :                        "arm\0"
      64             :                        "arm64\0"
      65             :                        "mips\0"
      66             :                        "mips64\0"
      67             :                        "mips64-n32\0"
      68             :                        "mips-le\0"
      69             :                        "mips64-le\0"
      70             :                        "mips64-le-n32\0"
      71             :                        "ppc\0"
      72             :                        "ppc64\0"
      73             :                        "ppc64-le\0"
      74             :                        "s390\0"
      75             :                        "s390x\0") {
      76             :                 uint32_t c;
      77             : 
      78          17 :                 assert_se(seccomp_arch_from_string(n, &c) >= 0);
      79          17 :                 n2 = seccomp_arch_to_string(c);
      80          17 :                 log_info("seccomp-arch: %s → 0x%"PRIx32" → %s", n, c, n2);
      81          17 :                 assert_se(streq_ptr(n, n2));
      82             :         }
      83           1 : }
      84             : 
      85           1 : static void test_syscall_filter_set_find(void) {
      86           1 :         log_info("/* %s */", __func__);
      87             : 
      88           1 :         assert_se(!syscall_filter_set_find(NULL));
      89           1 :         assert_se(!syscall_filter_set_find(""));
      90           1 :         assert_se(!syscall_filter_set_find("quux"));
      91           1 :         assert_se(!syscall_filter_set_find("@quux"));
      92             : 
      93           1 :         assert_se(syscall_filter_set_find("@clock") == syscall_filter_sets + SYSCALL_FILTER_SET_CLOCK);
      94           1 :         assert_se(syscall_filter_set_find("@default") == syscall_filter_sets + SYSCALL_FILTER_SET_DEFAULT);
      95           1 :         assert_se(syscall_filter_set_find("@raw-io") == syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO);
      96           1 : }
      97             : 
      98           1 : static void test_filter_sets(void) {
      99             :         unsigned i;
     100             :         int r;
     101             : 
     102           1 :         log_info("/* %s */", __func__);
     103             : 
     104           1 :         if (!is_seccomp_available()) {
     105           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     106           0 :                 return;
     107             :         }
     108           1 :         if (geteuid() != 0) {
     109           1 :                 log_notice("Not root, skipping %s", __func__);
     110           1 :                 return;
     111             :         }
     112             : 
     113           0 :         for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
     114             :                 pid_t pid;
     115             : 
     116           0 :                 log_info("Testing %s", syscall_filter_sets[i].name);
     117             : 
     118           0 :                 pid = fork();
     119           0 :                 assert_se(pid >= 0);
     120             : 
     121           0 :                 if (pid == 0) { /* Child? */
     122             :                         int fd;
     123             : 
     124             :                         /* If we look at the default set (or one that includes it), whitelist instead of blacklist */
     125           0 :                         if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_SYSTEM_SERVICE))
     126           0 :                                 r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW, true);
     127             :                         else
     128           0 :                                 r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN), true);
     129           0 :                         if (r < 0)
     130           0 :                                 _exit(EXIT_FAILURE);
     131             : 
     132             :                         /* Test the sycall filter with one random system call */
     133           0 :                         fd = eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC);
     134           0 :                         if (IN_SET(i, SYSCALL_FILTER_SET_IO_EVENT, SYSCALL_FILTER_SET_DEFAULT))
     135           0 :                                 assert_se(fd < 0 && errno == EUCLEAN);
     136             :                         else {
     137           0 :                                 assert_se(fd >= 0);
     138           0 :                                 safe_close(fd);
     139             :                         }
     140             : 
     141           0 :                         _exit(EXIT_SUCCESS);
     142             :                 }
     143             : 
     144           0 :                 assert_se(wait_for_terminate_and_check(syscall_filter_sets[i].name, pid, WAIT_LOG) == EXIT_SUCCESS);
     145             :         }
     146             : }
     147             : 
     148           1 : static void test_filter_sets_ordered(void) {
     149             :         size_t i;
     150             : 
     151           1 :         log_info("/* %s */", __func__);
     152             : 
     153             :         /* Ensure "@default" always remains at the beginning of the list */
     154             :         assert_se(SYSCALL_FILTER_SET_DEFAULT == 0);
     155           1 :         assert_se(streq(syscall_filter_sets[0].name, "@default"));
     156             : 
     157          28 :         for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
     158          27 :                 const char *k, *p = NULL;
     159             : 
     160             :                 /* Make sure each group has a description */
     161          27 :                 assert_se(!isempty(syscall_filter_sets[0].help));
     162             : 
     163             :                 /* Make sure the groups are ordered alphabetically, except for the first entry */
     164          27 :                 assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0);
     165             : 
     166         478 :                 NULSTR_FOREACH(k, syscall_filter_sets[i].value) {
     167             : 
     168             :                         /* Ensure each syscall list is in itself ordered, but groups before names */
     169         451 :                         assert_se(!p ||
     170             :                                   (*p == '@' && *k != '@') ||
     171             :                                   (((*p == '@' && *k == '@') ||
     172             :                                     (*p != '@' && *k != '@')) &&
     173             :                                    strcmp(p, k) < 0));
     174             : 
     175         451 :                         p = k;
     176             :                 }
     177             :         }
     178           1 : }
     179             : 
     180           1 : static void test_restrict_namespace(void) {
     181           1 :         char *s = NULL;
     182             :         unsigned long ul;
     183             :         pid_t pid;
     184             : 
     185           1 :         if (!have_namespaces()) {
     186           1 :                 log_notice("Testing without namespaces, skipping %s", __func__);
     187           1 :                 return;
     188             :         }
     189             : 
     190           0 :         log_info("/* %s */", __func__);
     191             : 
     192           0 :         assert_se(namespace_flags_to_string(0, &s) == 0 && streq(s, ""));
     193           0 :         s = mfree(s);
     194           0 :         assert_se(namespace_flags_to_string(CLONE_NEWNS, &s) == 0 && streq(s, "mnt"));
     195           0 :         s = mfree(s);
     196           0 :         assert_se(namespace_flags_to_string(CLONE_NEWNS|CLONE_NEWIPC, &s) == 0 && streq(s, "ipc mnt"));
     197           0 :         s = mfree(s);
     198           0 :         assert_se(namespace_flags_to_string(CLONE_NEWCGROUP, &s) == 0 && streq(s, "cgroup"));
     199           0 :         s = mfree(s);
     200             : 
     201           0 :         assert_se(namespace_flags_from_string("mnt", &ul) == 0 && ul == CLONE_NEWNS);
     202           0 :         assert_se(namespace_flags_from_string(NULL, &ul) == 0 && ul == 0);
     203           0 :         assert_se(namespace_flags_from_string("", &ul) == 0 && ul == 0);
     204           0 :         assert_se(namespace_flags_from_string("uts", &ul) == 0 && ul == CLONE_NEWUTS);
     205           0 :         assert_se(namespace_flags_from_string("mnt uts ipc", &ul) == 0 && ul == (CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC));
     206             : 
     207           0 :         assert_se(namespace_flags_to_string(CLONE_NEWUTS, &s) == 0 && streq(s, "uts"));
     208           0 :         assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == CLONE_NEWUTS);
     209           0 :         s = mfree(s);
     210           0 :         assert_se(namespace_flags_from_string("ipc", &ul) == 0 && ul == CLONE_NEWIPC);
     211           0 :         assert_se(namespace_flags_to_string(ul, &s) == 0 && streq(s, "ipc"));
     212           0 :         s = mfree(s);
     213             : 
     214           0 :         assert_se(namespace_flags_to_string(NAMESPACE_FLAGS_ALL, &s) == 0);
     215           0 :         assert_se(streq(s, "cgroup ipc net mnt pid user uts"));
     216           0 :         assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL);
     217           0 :         s = mfree(s);
     218             : 
     219           0 :         if (!is_seccomp_available()) {
     220           0 :                 log_notice("Seccomp not available, skipping remaining tests in %s", __func__);
     221           0 :                 return;
     222             :         }
     223           0 :         if (geteuid() != 0) {
     224           0 :                 log_notice("Not root, skipping remaining tests in %s", __func__);
     225           0 :                 return;
     226             :         }
     227             : 
     228           0 :         pid = fork();
     229           0 :         assert_se(pid >= 0);
     230             : 
     231           0 :         if (pid == 0) {
     232             : 
     233           0 :                 assert_se(seccomp_restrict_namespaces(CLONE_NEWNS|CLONE_NEWNET) >= 0);
     234             : 
     235           0 :                 assert_se(unshare(CLONE_NEWNS) == 0);
     236           0 :                 assert_se(unshare(CLONE_NEWNET) == 0);
     237           0 :                 assert_se(unshare(CLONE_NEWUTS) == -1);
     238           0 :                 assert_se(errno == EPERM);
     239           0 :                 assert_se(unshare(CLONE_NEWIPC) == -1);
     240           0 :                 assert_se(errno == EPERM);
     241           0 :                 assert_se(unshare(CLONE_NEWNET|CLONE_NEWUTS) == -1);
     242           0 :                 assert_se(errno == EPERM);
     243             : 
     244             :                 /* We use fd 0 (stdin) here, which of course will fail with EINVAL on setns(). Except of course our
     245             :                  * seccomp filter worked, and hits first and makes it return EPERM */
     246           0 :                 assert_se(setns(0, CLONE_NEWNS) == -1);
     247           0 :                 assert_se(errno == EINVAL);
     248           0 :                 assert_se(setns(0, CLONE_NEWNET) == -1);
     249           0 :                 assert_se(errno == EINVAL);
     250           0 :                 assert_se(setns(0, CLONE_NEWUTS) == -1);
     251           0 :                 assert_se(errno == EPERM);
     252           0 :                 assert_se(setns(0, CLONE_NEWIPC) == -1);
     253           0 :                 assert_se(errno == EPERM);
     254           0 :                 assert_se(setns(0, CLONE_NEWNET|CLONE_NEWUTS) == -1);
     255           0 :                 assert_se(errno == EPERM);
     256           0 :                 assert_se(setns(0, 0) == -1);
     257           0 :                 assert_se(errno == EPERM);
     258             : 
     259           0 :                 pid = raw_clone(CLONE_NEWNS);
     260           0 :                 assert_se(pid >= 0);
     261           0 :                 if (pid == 0)
     262           0 :                         _exit(EXIT_SUCCESS);
     263           0 :                 pid = raw_clone(CLONE_NEWNET);
     264           0 :                 assert_se(pid >= 0);
     265           0 :                 if (pid == 0)
     266           0 :                         _exit(EXIT_SUCCESS);
     267           0 :                 pid = raw_clone(CLONE_NEWUTS);
     268           0 :                 assert_se(pid < 0);
     269           0 :                 assert_se(errno == EPERM);
     270           0 :                 pid = raw_clone(CLONE_NEWIPC);
     271           0 :                 assert_se(pid < 0);
     272           0 :                 assert_se(errno == EPERM);
     273           0 :                 pid = raw_clone(CLONE_NEWNET|CLONE_NEWUTS);
     274           0 :                 assert_se(pid < 0);
     275           0 :                 assert_se(errno == EPERM);
     276             : 
     277           0 :                 _exit(EXIT_SUCCESS);
     278             :         }
     279             : 
     280           0 :         assert_se(wait_for_terminate_and_check("nsseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
     281             : }
     282             : 
     283           1 : static void test_protect_sysctl(void) {
     284             :         pid_t pid;
     285             : 
     286           1 :         log_info("/* %s */", __func__);
     287             : 
     288           1 :         if (!is_seccomp_available()) {
     289           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     290           0 :                 return;
     291             :         }
     292           1 :         if (geteuid() != 0) {
     293           1 :                 log_notice("Not root, skipping %s", __func__);
     294           1 :                 return;
     295             :         }
     296             : 
     297             :         /* in containers _sysctl() is likely missing anyway */
     298           0 :         if (detect_container() > 0) {
     299           0 :                 log_notice("Testing in container, skipping %s", __func__);
     300           0 :                 return;
     301             :         }
     302             : 
     303           0 :         pid = fork();
     304           0 :         assert_se(pid >= 0);
     305             : 
     306           0 :         if (pid == 0) {
     307             : #if __NR__sysctl > 0
     308           0 :                 assert_se(syscall(__NR__sysctl, NULL) < 0);
     309           0 :                 assert_se(errno == EFAULT);
     310             : #endif
     311             : 
     312           0 :                 assert_se(seccomp_protect_sysctl() >= 0);
     313             : 
     314             : #if __NR__sysctl > 0
     315           0 :                 assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0);
     316           0 :                 assert_se(errno == EPERM);
     317             : #endif
     318             : 
     319           0 :                 _exit(EXIT_SUCCESS);
     320             :         }
     321             : 
     322           0 :         assert_se(wait_for_terminate_and_check("sysctlseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
     323             : }
     324             : 
     325           1 : static void test_restrict_address_families(void) {
     326             :         pid_t pid;
     327             : 
     328           1 :         log_info("/* %s */", __func__);
     329             : 
     330           1 :         if (!is_seccomp_available()) {
     331           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     332           0 :                 return;
     333             :         }
     334           1 :         if (geteuid() != 0) {
     335           1 :                 log_notice("Not root, skipping %s", __func__);
     336           1 :                 return;
     337             :         }
     338             : 
     339           0 :         pid = fork();
     340           0 :         assert_se(pid >= 0);
     341             : 
     342           0 :         if (pid == 0) {
     343             :                 int fd;
     344             :                 Set *s;
     345             : 
     346           0 :                 fd = socket(AF_INET, SOCK_DGRAM, 0);
     347           0 :                 assert_se(fd >= 0);
     348           0 :                 safe_close(fd);
     349             : 
     350           0 :                 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
     351           0 :                 assert_se(fd >= 0);
     352           0 :                 safe_close(fd);
     353             : 
     354           0 :                 fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
     355           0 :                 assert_se(fd >= 0);
     356           0 :                 safe_close(fd);
     357             : 
     358           0 :                 assert_se(s = set_new(NULL));
     359           0 :                 assert_se(set_put(s, INT_TO_PTR(AF_UNIX)) >= 0);
     360             : 
     361           0 :                 assert_se(seccomp_restrict_address_families(s, false) >= 0);
     362             : 
     363           0 :                 fd = socket(AF_INET, SOCK_DGRAM, 0);
     364           0 :                 assert_se(fd >= 0);
     365           0 :                 safe_close(fd);
     366             : 
     367           0 :                 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
     368             : #if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
     369             :                 assert_se(fd >= 0);
     370             :                 safe_close(fd);
     371             : #else
     372           0 :                 assert_se(fd < 0);
     373           0 :                 assert_se(errno == EAFNOSUPPORT);
     374             : #endif
     375             : 
     376           0 :                 fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
     377           0 :                 assert_se(fd >= 0);
     378           0 :                 safe_close(fd);
     379             : 
     380           0 :                 set_clear(s);
     381             : 
     382           0 :                 assert_se(set_put(s, INT_TO_PTR(AF_INET)) >= 0);
     383             : 
     384           0 :                 assert_se(seccomp_restrict_address_families(s, true) >= 0);
     385             : 
     386           0 :                 fd = socket(AF_INET, SOCK_DGRAM, 0);
     387           0 :                 assert_se(fd >= 0);
     388           0 :                 safe_close(fd);
     389             : 
     390           0 :                 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
     391             : #if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
     392             :                 assert_se(fd >= 0);
     393             :                 safe_close(fd);
     394             : #else
     395           0 :                 assert_se(fd < 0);
     396           0 :                 assert_se(errno == EAFNOSUPPORT);
     397             : #endif
     398             : 
     399           0 :                 fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
     400             : #if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
     401             :                 assert_se(fd >= 0);
     402             :                 safe_close(fd);
     403             : #else
     404           0 :                 assert_se(fd < 0);
     405           0 :                 assert_se(errno == EAFNOSUPPORT);
     406             : #endif
     407             : 
     408           0 :                 _exit(EXIT_SUCCESS);
     409             :         }
     410             : 
     411           0 :         assert_se(wait_for_terminate_and_check("socketseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
     412             : }
     413             : 
     414           1 : static void test_restrict_realtime(void) {
     415             :         pid_t pid;
     416             : 
     417           1 :         log_info("/* %s */", __func__);
     418             : 
     419           1 :         if (!is_seccomp_available()) {
     420           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     421           0 :                 return;
     422             :         }
     423           1 :         if (geteuid() != 0) {
     424           1 :                 log_notice("Not root, skipping %s", __func__);
     425           1 :                 return;
     426             :         }
     427             : 
     428             :         /* in containers RT privs are likely missing anyway */
     429           0 :         if (detect_container() > 0) {
     430           0 :                 log_notice("Testing in container, skipping %s", __func__);
     431           0 :                 return;
     432             :         }
     433             : 
     434           0 :         pid = fork();
     435           0 :         assert_se(pid >= 0);
     436             : 
     437           0 :         if (pid == 0) {
     438           0 :                 assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) >= 0);
     439           0 :                 assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) >= 0);
     440           0 :                 assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0);
     441           0 :                 assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0);
     442           0 :                 assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0);
     443             : 
     444           0 :                 assert_se(seccomp_restrict_realtime() >= 0);
     445             : 
     446           0 :                 assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0);
     447           0 :                 assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0);
     448           0 :                 assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0);
     449             : 
     450           0 :                 assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0);
     451           0 :                 assert_se(errno == EPERM);
     452           0 :                 assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) < 0);
     453           0 :                 assert_se(errno == EPERM);
     454             : 
     455           0 :                 _exit(EXIT_SUCCESS);
     456             :         }
     457             : 
     458           0 :         assert_se(wait_for_terminate_and_check("realtimeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
     459             : }
     460             : 
     461           1 : static void test_memory_deny_write_execute_mmap(void) {
     462             :         pid_t pid;
     463             : 
     464           1 :         log_info("/* %s */", __func__);
     465             : 
     466           1 :         if (!is_seccomp_available()) {
     467           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     468           0 :                 return;
     469             :         }
     470           1 :         if (geteuid() != 0) {
     471           1 :                 log_notice("Not root, skipping %s", __func__);
     472           1 :                 return;
     473             :         }
     474             : 
     475           0 :         pid = fork();
     476           0 :         assert_se(pid >= 0);
     477             : 
     478           0 :         if (pid == 0) {
     479             :                 void *p;
     480             : 
     481           0 :                 p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
     482           0 :                 assert_se(p != MAP_FAILED);
     483           0 :                 assert_se(munmap(p, page_size()) >= 0);
     484             : 
     485           0 :                 p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
     486           0 :                 assert_se(p != MAP_FAILED);
     487           0 :                 assert_se(munmap(p, page_size()) >= 0);
     488             : 
     489           0 :                 assert_se(seccomp_memory_deny_write_execute() >= 0);
     490             : 
     491           0 :                 p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
     492             : #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc64__) || defined(__arm__) || defined(__aarch64__)
     493           0 :                 assert_se(p == MAP_FAILED);
     494           0 :                 assert_se(errno == EPERM);
     495             : #else /* unknown architectures */
     496             :                 assert_se(p != MAP_FAILED);
     497             :                 assert_se(munmap(p, page_size()) >= 0);
     498             : #endif
     499             : 
     500           0 :                 p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
     501           0 :                 assert_se(p != MAP_FAILED);
     502           0 :                 assert_se(munmap(p, page_size()) >= 0);
     503             : 
     504           0 :                 _exit(EXIT_SUCCESS);
     505             :         }
     506             : 
     507           0 :         assert_se(wait_for_terminate_and_check("memoryseccomp-mmap", pid, WAIT_LOG) == EXIT_SUCCESS);
     508             : }
     509             : 
     510           1 : static void test_memory_deny_write_execute_shmat(void) {
     511             :         int shmid;
     512             :         pid_t pid;
     513             :         uint32_t arch;
     514             : 
     515           1 :         log_info("/* %s */", __func__);
     516             : 
     517           4 :         SECCOMP_FOREACH_LOCAL_ARCH(arch) {
     518           3 :                 log_debug("arch %s: SCMP_SYS(mmap) = %d", seccomp_arch_to_string(arch), SCMP_SYS(mmap));
     519           3 :                 log_debug("arch %s: SCMP_SYS(mmap2) = %d", seccomp_arch_to_string(arch), SCMP_SYS(mmap2));
     520           3 :                 log_debug("arch %s: SCMP_SYS(shmget) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmget));
     521           3 :                 log_debug("arch %s: SCMP_SYS(shmat) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmat));
     522           3 :                 log_debug("arch %s: SCMP_SYS(shmdt) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmdt));
     523             :         }
     524             : 
     525           1 :         if (!is_seccomp_available()) {
     526           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     527           0 :                 return;
     528             :         }
     529           1 :         if (geteuid() != 0) {
     530           1 :                 log_notice("Not root, skipping %s", __func__);
     531           1 :                 return;
     532             :         }
     533             : 
     534           0 :         shmid = shmget(IPC_PRIVATE, page_size(), 0);
     535           0 :         assert_se(shmid >= 0);
     536             : 
     537           0 :         pid = fork();
     538           0 :         assert_se(pid >= 0);
     539             : 
     540           0 :         if (pid == 0) {
     541             :                 void *p;
     542             : 
     543           0 :                 p = shmat(shmid, NULL, 0);
     544           0 :                 assert_se(p != MAP_FAILED);
     545           0 :                 assert_se(shmdt(p) == 0);
     546             : 
     547           0 :                 p = shmat(shmid, NULL, SHM_EXEC);
     548           0 :                 assert_se(p != MAP_FAILED);
     549           0 :                 assert_se(shmdt(p) == 0);
     550             : 
     551           0 :                 assert_se(seccomp_memory_deny_write_execute() >= 0);
     552             : 
     553           0 :                 p = shmat(shmid, NULL, SHM_EXEC);
     554           0 :                 log_debug_errno(p == MAP_FAILED ? errno : 0, "shmat(SHM_EXEC): %m");
     555             : #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
     556           0 :                 assert_se(p == MAP_FAILED);
     557           0 :                 assert_se(errno == EPERM);
     558             : #endif
     559             :                 /* Depending on kernel, libseccomp, and glibc versions, other architectures
     560             :                  * might fail or not. Let's not assert success. */
     561           0 :                 if (p != MAP_FAILED)
     562           0 :                         assert_se(shmdt(p) == 0);
     563             : 
     564           0 :                 p = shmat(shmid, NULL, 0);
     565           0 :                 log_debug_errno(p == MAP_FAILED ? errno : 0, "shmat(0): %m");
     566           0 :                 assert_se(p != MAP_FAILED);
     567           0 :                 assert_se(shmdt(p) == 0);
     568             : 
     569           0 :                 _exit(EXIT_SUCCESS);
     570             :         }
     571             : 
     572           0 :         assert_se(wait_for_terminate_and_check("memoryseccomp-shmat", pid, WAIT_LOG) == EXIT_SUCCESS);
     573             : }
     574             : 
     575           1 : static void test_restrict_archs(void) {
     576             :         pid_t pid;
     577             : 
     578           1 :         log_info("/* %s */", __func__);
     579             : 
     580           1 :         if (!is_seccomp_available()) {
     581           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     582           0 :                 return;
     583             :         }
     584           1 :         if (geteuid() != 0) {
     585           1 :                 log_notice("Not root, skipping %s", __func__);
     586           1 :                 return;
     587             :         }
     588             : 
     589           0 :         pid = fork();
     590           0 :         assert_se(pid >= 0);
     591             : 
     592           0 :         if (pid == 0) {
     593           0 :                 _cleanup_set_free_ Set *s = NULL;
     594             : 
     595           0 :                 assert_se(access("/", F_OK) >= 0);
     596             : 
     597           0 :                 assert_se(s = set_new(NULL));
     598             : 
     599             : #ifdef __x86_64__
     600           0 :                 assert_se(set_put(s, UINT32_TO_PTR(SCMP_ARCH_X86+1)) >= 0);
     601             : #endif
     602           0 :                 assert_se(seccomp_restrict_archs(s) >= 0);
     603             : 
     604           0 :                 assert_se(access("/", F_OK) >= 0);
     605           0 :                 assert_se(seccomp_restrict_archs(NULL) >= 0);
     606             : 
     607           0 :                 assert_se(access("/", F_OK) >= 0);
     608             : 
     609           0 :                 _exit(EXIT_SUCCESS);
     610             :         }
     611             : 
     612           0 :         assert_se(wait_for_terminate_and_check("archseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
     613             : }
     614             : 
     615           1 : static void test_load_syscall_filter_set_raw(void) {
     616             :         pid_t pid;
     617             : 
     618           1 :         log_info("/* %s */", __func__);
     619             : 
     620           1 :         if (!is_seccomp_available()) {
     621           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     622           0 :                 return;
     623             :         }
     624           1 :         if (geteuid() != 0) {
     625           1 :                 log_notice("Not root, skipping %s", __func__);
     626           1 :                 return;
     627             :         }
     628             : 
     629           0 :         pid = fork();
     630           0 :         assert_se(pid >= 0);
     631             : 
     632           0 :         if (pid == 0) {
     633           0 :                 _cleanup_hashmap_free_ Hashmap *s = NULL;
     634             : 
     635           0 :                 assert_se(access("/", F_OK) >= 0);
     636           0 :                 assert_se(poll(NULL, 0, 0) == 0);
     637             : 
     638           0 :                 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, scmp_act_kill_process(), true) >= 0);
     639           0 :                 assert_se(access("/", F_OK) >= 0);
     640           0 :                 assert_se(poll(NULL, 0, 0) == 0);
     641             : 
     642           0 :                 assert_se(s = hashmap_new(NULL));
     643             : #if SCMP_SYS(access) >= 0
     644           0 :                 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(-1)) >= 0);
     645             : #else
     646             :                 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0);
     647             : #endif
     648             : 
     649           0 :                 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0);
     650             : 
     651           0 :                 assert_se(access("/", F_OK) < 0);
     652           0 :                 assert_se(errno == EUCLEAN);
     653             : 
     654           0 :                 assert_se(poll(NULL, 0, 0) == 0);
     655             : 
     656           0 :                 s = hashmap_free(s);
     657             : 
     658           0 :                 assert_se(s = hashmap_new(NULL));
     659             : #if SCMP_SYS(access) >= 0
     660           0 :                 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(EILSEQ)) >= 0);
     661             : #else
     662             :                 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0);
     663             : #endif
     664             : 
     665           0 :                 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0);
     666             : 
     667           0 :                 assert_se(access("/", F_OK) < 0);
     668           0 :                 assert_se(errno == EILSEQ);
     669             : 
     670           0 :                 assert_se(poll(NULL, 0, 0) == 0);
     671             : 
     672           0 :                 s = hashmap_free(s);
     673             : 
     674           0 :                 assert_se(s = hashmap_new(NULL));
     675             : #if SCMP_SYS(poll) >= 0
     676           0 :                 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(-1)) >= 0);
     677             : #else
     678             :                 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0);
     679             : #endif
     680             : 
     681           0 :                 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0);
     682             : 
     683           0 :                 assert_se(access("/", F_OK) < 0);
     684           0 :                 assert_se(errno == EILSEQ);
     685             : 
     686           0 :                 assert_se(poll(NULL, 0, 0) < 0);
     687           0 :                 assert_se(errno == EUNATCH);
     688             : 
     689           0 :                 s = hashmap_free(s);
     690             : 
     691           0 :                 assert_se(s = hashmap_new(NULL));
     692             : #if SCMP_SYS(poll) >= 0
     693           0 :                 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(EILSEQ)) >= 0);
     694             : #else
     695             :                 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0);
     696             : #endif
     697             : 
     698           0 :                 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0);
     699             : 
     700           0 :                 assert_se(access("/", F_OK) < 0);
     701           0 :                 assert_se(errno == EILSEQ);
     702             : 
     703           0 :                 assert_se(poll(NULL, 0, 0) < 0);
     704           0 :                 assert_se(errno == EILSEQ);
     705             : 
     706           0 :                 _exit(EXIT_SUCCESS);
     707             :         }
     708             : 
     709           0 :         assert_se(wait_for_terminate_and_check("syscallrawseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
     710             : }
     711             : 
     712           1 : static void test_lock_personality(void) {
     713             :         unsigned long current;
     714             :         pid_t pid;
     715             : 
     716           1 :         log_info("/* %s */", __func__);
     717             : 
     718           1 :         if (!is_seccomp_available()) {
     719           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     720           1 :                 return;
     721             :         }
     722           1 :         if (geteuid() != 0) {
     723           1 :                 log_notice("Not root, skipping %s", __func__);
     724           1 :                 return;
     725             :         }
     726             : 
     727           0 :         assert_se(opinionated_personality(&current) >= 0);
     728             : 
     729           0 :         log_info("current personality=%lu", current);
     730             : 
     731           0 :         pid = fork();
     732           0 :         assert_se(pid >= 0);
     733             : 
     734           0 :         if (pid == 0) {
     735           0 :                 assert_se(seccomp_lock_personality(current) >= 0);
     736             : 
     737           0 :                 assert_se((unsigned long) safe_personality(current) == current);
     738             : 
     739             :                 /* Note, we also test that safe_personality() works correctly, by checkig whether errno is properly
     740             :                  * set, in addition to the return value */
     741           0 :                 errno = 0;
     742           0 :                 assert_se(safe_personality(PER_LINUX | ADDR_NO_RANDOMIZE) == -EPERM);
     743           0 :                 assert_se(errno == EPERM);
     744             : 
     745           0 :                 assert_se(safe_personality(PER_LINUX | MMAP_PAGE_ZERO) == -EPERM);
     746           0 :                 assert_se(safe_personality(PER_LINUX | ADDR_COMPAT_LAYOUT) == -EPERM);
     747           0 :                 assert_se(safe_personality(PER_LINUX | READ_IMPLIES_EXEC) == -EPERM);
     748           0 :                 assert_se(safe_personality(PER_LINUX_32BIT) == -EPERM);
     749           0 :                 assert_se(safe_personality(PER_SVR4) == -EPERM);
     750           0 :                 assert_se(safe_personality(PER_BSD) == -EPERM);
     751           0 :                 assert_se(safe_personality(current == PER_LINUX ? PER_LINUX32 : PER_LINUX) == -EPERM);
     752           0 :                 assert_se(safe_personality(PER_LINUX32_3GB) == -EPERM);
     753           0 :                 assert_se(safe_personality(PER_UW7) == -EPERM);
     754           0 :                 assert_se(safe_personality(0x42) == -EPERM);
     755             : 
     756           0 :                 assert_se(safe_personality(PERSONALITY_INVALID) == -EPERM); /* maybe remove this later */
     757             : 
     758           0 :                 assert_se((unsigned long) personality(current) == current);
     759           0 :                 _exit(EXIT_SUCCESS);
     760             :         }
     761             : 
     762           0 :         assert_se(wait_for_terminate_and_check("lockpersonalityseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
     763             : }
     764             : 
     765           0 : static int real_open(const char *path, int flags, mode_t mode) {
     766             :         /* glibc internally calls openat() when open() is requested. Let's hence define our own wrapper for
     767             :          * testing purposes that calls the real syscall, on architectures where SYS_open is defined. On
     768             :          * other architectures, let's just fall back to the glibc call. */
     769             : 
     770             : #ifdef SYS_open
     771           0 :         return (int) syscall(SYS_open, path, flags, mode);
     772             : #else
     773             :         return open(path, flags, mode);
     774             : #endif
     775             : }
     776             : 
     777           1 : static void test_restrict_suid_sgid(void) {
     778             :         pid_t pid;
     779             : 
     780           1 :         log_info("/* %s */", __func__);
     781             : 
     782           1 :         if (!is_seccomp_available()) {
     783           0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     784           0 :                 return;
     785             :         }
     786           1 :         if (geteuid() != 0) {
     787           1 :                 log_notice("Not root, skipping %s", __func__);
     788           1 :                 return;
     789             :         }
     790             : 
     791           0 :         pid = fork();
     792           0 :         assert_se(pid >= 0);
     793             : 
     794           0 :         if (pid == 0) {
     795           0 :                 char path[] = "/tmp/suidsgidXXXXXX", dir[] = "/tmp/suidsgiddirXXXXXX";
     796           0 :                 int fd = -1, k = -1;
     797             :                 const char *z;
     798             : 
     799           0 :                 fd = mkostemp_safe(path);
     800           0 :                 assert_se(fd >= 0);
     801             : 
     802           0 :                 assert_se(mkdtemp(dir));
     803           0 :                 z = strjoina(dir, "/test");
     804             : 
     805           0 :                 assert_se(chmod(path, 0755 | S_ISUID) >= 0);
     806           0 :                 assert_se(chmod(path, 0755 | S_ISGID) >= 0);
     807           0 :                 assert_se(chmod(path, 0755 | S_ISGID | S_ISUID) >= 0);
     808           0 :                 assert_se(chmod(path, 0755) >= 0);
     809             : 
     810           0 :                 assert_se(fchmod(fd, 0755 | S_ISUID) >= 0);
     811           0 :                 assert_se(fchmod(fd, 0755 | S_ISGID) >= 0);
     812           0 :                 assert_se(fchmod(fd, 0755 | S_ISGID | S_ISUID) >= 0);
     813           0 :                 assert_se(fchmod(fd, 0755) >= 0);
     814             : 
     815           0 :                 assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) >= 0);
     816           0 :                 assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) >= 0);
     817           0 :                 assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0);
     818           0 :                 assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
     819             : 
     820           0 :                 k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID);
     821           0 :                 k = safe_close(k);
     822           0 :                 assert_se(unlink(z) >= 0);
     823             : 
     824           0 :                 k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID);
     825           0 :                 k = safe_close(k);
     826           0 :                 assert_se(unlink(z) >= 0);
     827             : 
     828           0 :                 k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID);
     829           0 :                 k = safe_close(k);
     830           0 :                 assert_se(unlink(z) >= 0);
     831             : 
     832           0 :                 k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
     833           0 :                 k = safe_close(k);
     834           0 :                 assert_se(unlink(z) >= 0);
     835             : 
     836           0 :                 k = creat(z, 0644 | S_ISUID);
     837           0 :                 k = safe_close(k);
     838           0 :                 assert_se(unlink(z) >= 0);
     839             : 
     840           0 :                 k = creat(z, 0644 | S_ISGID);
     841           0 :                 k = safe_close(k);
     842           0 :                 assert_se(unlink(z) >= 0);
     843             : 
     844           0 :                 k = creat(z, 0644 | S_ISUID | S_ISGID);
     845           0 :                 k = safe_close(k);
     846           0 :                 assert_se(unlink(z) >= 0);
     847             : 
     848           0 :                 k = creat(z, 0644);
     849           0 :                 k = safe_close(k);
     850           0 :                 assert_se(unlink(z) >= 0);
     851             : 
     852           0 :                 k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID);
     853           0 :                 k = safe_close(k);
     854           0 :                 assert_se(unlink(z) >= 0);
     855             : 
     856           0 :                 k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID);
     857           0 :                 k = safe_close(k);
     858           0 :                 assert_se(unlink(z) >= 0);
     859             : 
     860           0 :                 k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID);
     861           0 :                 k = safe_close(k);
     862           0 :                 assert_se(unlink(z) >= 0);
     863             : 
     864           0 :                 k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
     865           0 :                 k = safe_close(k);
     866           0 :                 assert_se(unlink(z) >= 0);
     867             : 
     868           0 :                 assert_se(mkdir(z, 0755 | S_ISUID) >= 0);
     869           0 :                 assert_se(rmdir(z) >= 0);
     870           0 :                 assert_se(mkdir(z, 0755 | S_ISGID) >= 0);
     871           0 :                 assert_se(rmdir(z) >= 0);
     872           0 :                 assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) >= 0);
     873           0 :                 assert_se(rmdir(z) >= 0);
     874           0 :                 assert_se(mkdir(z, 0755) >= 0);
     875           0 :                 assert_se(rmdir(z) >= 0);
     876             : 
     877           0 :                 assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) >= 0);
     878           0 :                 assert_se(rmdir(z) >= 0);
     879           0 :                 assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) >= 0);
     880           0 :                 assert_se(rmdir(z) >= 0);
     881           0 :                 assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) >= 0);
     882           0 :                 assert_se(rmdir(z) >= 0);
     883           0 :                 assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0);
     884           0 :                 assert_se(rmdir(z) >= 0);
     885             : 
     886           0 :                 assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) >= 0);
     887           0 :                 assert_se(unlink(z) >= 0);
     888           0 :                 assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) >= 0);
     889           0 :                 assert_se(unlink(z) >= 0);
     890           0 :                 assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0);
     891           0 :                 assert_se(unlink(z) >= 0);
     892           0 :                 assert_se(mknod(z, S_IFREG | 0755, 0) >= 0);
     893           0 :                 assert_se(unlink(z) >= 0);
     894             : 
     895           0 :                 assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) >= 0);
     896           0 :                 assert_se(unlink(z) >= 0);
     897           0 :                 assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) >= 0);
     898           0 :                 assert_se(unlink(z) >= 0);
     899           0 :                 assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0);
     900           0 :                 assert_se(unlink(z) >= 0);
     901           0 :                 assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0);
     902           0 :                 assert_se(unlink(z) >= 0);
     903             : 
     904           0 :                 assert_se(seccomp_restrict_suid_sgid() >= 0);
     905             : 
     906           0 :                 assert_se(chmod(path, 0775 | S_ISUID) < 0 && errno == EPERM);
     907           0 :                 assert_se(chmod(path, 0775 | S_ISGID) < 0  && errno == EPERM);
     908           0 :                 assert_se(chmod(path, 0775 | S_ISGID | S_ISUID) < 0  && errno == EPERM);
     909           0 :                 assert_se(chmod(path, 0775) >= 0);
     910             : 
     911           0 :                 assert_se(fchmod(fd, 0775 | S_ISUID) < 0 && errno == EPERM);
     912           0 :                 assert_se(fchmod(fd, 0775 | S_ISGID) < 0  && errno == EPERM);
     913           0 :                 assert_se(fchmod(fd, 0775 | S_ISGID | S_ISUID) < 0  && errno == EPERM);
     914           0 :                 assert_se(fchmod(fd, 0775) >= 0);
     915             : 
     916           0 :                 assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) < 0 && errno == EPERM);
     917           0 :                 assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) < 0 && errno == EPERM);
     918           0 :                 assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM);
     919           0 :                 assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
     920             : 
     921           0 :                 assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM);
     922           0 :                 assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM);
     923           0 :                 assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
     924           0 :                 k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
     925           0 :                 k = safe_close(k);
     926           0 :                 assert_se(unlink(z) >= 0);
     927             : 
     928           0 :                 assert_se(creat(z, 0644 | S_ISUID) < 0 && errno == EPERM);
     929           0 :                 assert_se(creat(z, 0644 | S_ISGID) < 0 && errno == EPERM);
     930           0 :                 assert_se(creat(z, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
     931           0 :                 k = creat(z, 0644);
     932           0 :                 k = safe_close(k);
     933           0 :                 assert_se(unlink(z) >= 0);
     934             : 
     935           0 :                 assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM);
     936           0 :                 assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM);
     937           0 :                 assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
     938           0 :                 k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
     939           0 :                 k = safe_close(k);
     940           0 :                 assert_se(unlink(z) >= 0);
     941             : 
     942           0 :                 assert_se(mkdir(z, 0755 | S_ISUID) < 0 && errno == EPERM);
     943           0 :                 assert_se(mkdir(z, 0755 | S_ISGID) < 0 && errno == EPERM);
     944           0 :                 assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
     945           0 :                 assert_se(mkdir(z, 0755) >= 0);
     946           0 :                 assert_se(rmdir(z) >= 0);
     947             : 
     948           0 :                 assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) < 0 && errno == EPERM);
     949           0 :                 assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) < 0 && errno == EPERM);
     950           0 :                 assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
     951           0 :                 assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0);
     952           0 :                 assert_se(rmdir(z) >= 0);
     953             : 
     954           0 :                 assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM);
     955           0 :                 assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM);
     956           0 :                 assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM);
     957           0 :                 assert_se(mknod(z, S_IFREG | 0755, 0) >= 0);
     958           0 :                 assert_se(unlink(z) >= 0);
     959             : 
     960           0 :                 assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM);
     961           0 :                 assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM);
     962           0 :                 assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM);
     963           0 :                 assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0);
     964           0 :                 assert_se(unlink(z) >= 0);
     965             : 
     966           0 :                 assert_se(unlink(path) >= 0);
     967           0 :                 assert_se(rm_rf(dir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
     968             : 
     969           0 :                 _exit(EXIT_SUCCESS);
     970             :         }
     971             : 
     972           0 :         assert_se(wait_for_terminate_and_check("suidsgidseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
     973             : }
     974             : 
     975           1 : int main(int argc, char *argv[]) {
     976           1 :         test_setup_logging(LOG_DEBUG);
     977             : 
     978           1 :         test_seccomp_arch_to_string();
     979           1 :         test_architecture_table();
     980           1 :         test_syscall_filter_set_find();
     981           1 :         test_filter_sets();
     982           1 :         test_filter_sets_ordered();
     983           1 :         test_restrict_namespace();
     984           1 :         test_protect_sysctl();
     985           1 :         test_restrict_address_families();
     986           1 :         test_restrict_realtime();
     987           1 :         test_memory_deny_write_execute_mmap();
     988           1 :         test_memory_deny_write_execute_shmat();
     989           1 :         test_restrict_archs();
     990           1 :         test_load_syscall_filter_set_raw();
     991           1 :         test_lock_personality();
     992           1 :         test_restrict_suid_sgid();
     993             : 
     994           1 :         return 0;
     995             : }

Generated by: LCOV version 1.14