LCOV - code coverage report
Current view: top level - test - test-seccomp.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 128 574 22.3 %
Date: 2019-08-23 13:36:53 Functions: 16 17 94.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 101 940 10.7 %

           Branch data     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                 :          4 : static void test_seccomp_arch_to_string(void) {
      40                 :            :         uint32_t a, b;
      41                 :            :         const char *name;
      42                 :            : 
      43         [ +  - ]:          4 :         log_info("/* %s */", __func__);
      44                 :            : 
      45                 :          4 :         a = seccomp_arch_native();
      46         [ -  + ]:          4 :         assert_se(a > 0);
      47                 :          4 :         name = seccomp_arch_to_string(a);
      48         [ -  + ]:          4 :         assert_se(name);
      49         [ -  + ]:          4 :         assert_se(seccomp_arch_from_string(name, &b) >= 0);
      50         [ -  + ]:          4 :         assert_se(a == b);
      51                 :          4 : }
      52                 :            : 
      53                 :          4 : static void test_architecture_table(void) {
      54                 :            :         const char *n, *n2;
      55                 :            : 
      56         [ +  - ]:          4 :         log_info("/* %s */", __func__);
      57                 :            : 
      58   [ +  -  +  + ]:         72 :         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         [ -  + ]:         68 :                 assert_se(seccomp_arch_from_string(n, &c) >= 0);
      79                 :         68 :                 n2 = seccomp_arch_to_string(c);
      80         [ +  - ]:         68 :                 log_info("seccomp-arch: %s → 0x%"PRIx32" → %s", n, c, n2);
      81         [ -  + ]:         68 :                 assert_se(streq_ptr(n, n2));
      82                 :            :         }
      83                 :          4 : }
      84                 :            : 
      85                 :          4 : static void test_syscall_filter_set_find(void) {
      86         [ +  - ]:          4 :         log_info("/* %s */", __func__);
      87                 :            : 
      88         [ -  + ]:          4 :         assert_se(!syscall_filter_set_find(NULL));
      89         [ -  + ]:          4 :         assert_se(!syscall_filter_set_find(""));
      90         [ -  + ]:          4 :         assert_se(!syscall_filter_set_find("quux"));
      91         [ -  + ]:          4 :         assert_se(!syscall_filter_set_find("@quux"));
      92                 :            : 
      93         [ -  + ]:          4 :         assert_se(syscall_filter_set_find("@clock") == syscall_filter_sets + SYSCALL_FILTER_SET_CLOCK);
      94         [ -  + ]:          4 :         assert_se(syscall_filter_set_find("@default") == syscall_filter_sets + SYSCALL_FILTER_SET_DEFAULT);
      95         [ -  + ]:          4 :         assert_se(syscall_filter_set_find("@raw-io") == syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO);
      96                 :          4 : }
      97                 :            : 
      98                 :          4 : static void test_filter_sets(void) {
      99                 :            :         unsigned i;
     100                 :            :         int r;
     101                 :            : 
     102         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     103                 :            : 
     104         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     105         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     106                 :          0 :                 return;
     107                 :            :         }
     108         [ +  - ]:          4 :         if (geteuid() != 0) {
     109         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     110                 :          4 :                 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                 :          4 : static void test_filter_sets_ordered(void) {
     149                 :            :         size_t i;
     150                 :            : 
     151         [ +  - ]:          4 :         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         [ -  + ]:          4 :         assert_se(streq(syscall_filter_sets[0].name, "@default"));
     156                 :            : 
     157         [ +  + ]:        112 :         for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
     158                 :        108 :                 const char *k, *p = NULL;
     159                 :            : 
     160                 :            :                 /* Make sure each group has a description */
     161         [ -  + ]:        108 :                 assert_se(!isempty(syscall_filter_sets[0].help));
     162                 :            : 
     163                 :            :                 /* Make sure the groups are ordered alphabetically, except for the first entry */
     164   [ +  +  -  + ]:        108 :                 assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0);
     165                 :            : 
     166   [ +  -  +  + ]:       1912 :                 NULSTR_FOREACH(k, syscall_filter_sets[i].value) {
     167                 :            : 
     168                 :            :                         /* Ensure each syscall list is in itself ordered, but groups before names */
     169   [ +  +  +  +  :       1804 :                         assert_se(!p ||
          +  +  +  +  +  
          +  +  +  -  +  
          +  +  +  -  -  
          +  -  +  +  -  
             -  +  -  + ]
     170                 :            :                                   (*p == '@' && *k != '@') ||
     171                 :            :                                   (((*p == '@' && *k == '@') ||
     172                 :            :                                     (*p != '@' && *k != '@')) &&
     173                 :            :                                    strcmp(p, k) < 0));
     174                 :            : 
     175                 :       1804 :                         p = k;
     176                 :            :                 }
     177                 :            :         }
     178                 :          4 : }
     179                 :            : 
     180                 :          4 : static void test_restrict_namespace(void) {
     181                 :          4 :         char *s = NULL;
     182                 :            :         unsigned long ul;
     183                 :            :         pid_t pid;
     184                 :            : 
     185         [ +  - ]:          4 :         if (!have_namespaces()) {
     186         [ +  - ]:          4 :                 log_notice("Testing without namespaces, skipping %s", __func__);
     187                 :          4 :                 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                 :          4 : static void test_protect_sysctl(void) {
     284                 :            :         pid_t pid;
     285                 :            : 
     286         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     287                 :            : 
     288         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     289         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     290                 :          0 :                 return;
     291                 :            :         }
     292         [ +  - ]:          4 :         if (geteuid() != 0) {
     293         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     294                 :          4 :                 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                 :          4 : static void test_restrict_address_families(void) {
     326                 :            :         pid_t pid;
     327                 :            : 
     328         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     329                 :            : 
     330         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     331         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     332                 :          0 :                 return;
     333                 :            :         }
     334         [ +  - ]:          4 :         if (geteuid() != 0) {
     335         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     336                 :          4 :                 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                 :          4 : static void test_restrict_realtime(void) {
     415                 :            :         pid_t pid;
     416                 :            : 
     417         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     418                 :            : 
     419         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     420         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     421                 :          0 :                 return;
     422                 :            :         }
     423         [ +  - ]:          4 :         if (geteuid() != 0) {
     424         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     425                 :          4 :                 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                 :          4 : static void test_memory_deny_write_execute_mmap(void) {
     462                 :            :         pid_t pid;
     463                 :            : 
     464         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     465                 :            : 
     466         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     467         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     468                 :          0 :                 return;
     469                 :            :         }
     470         [ +  - ]:          4 :         if (geteuid() != 0) {
     471         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     472                 :          4 :                 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                 :          4 : static void test_memory_deny_write_execute_shmat(void) {
     511                 :            :         int shmid;
     512                 :            :         pid_t pid;
     513                 :            :         uint32_t arch;
     514                 :            : 
     515         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     516                 :            : 
     517         [ +  + ]:         16 :         SECCOMP_FOREACH_LOCAL_ARCH(arch) {
     518         [ +  - ]:         12 :                 log_debug("arch %s: SCMP_SYS(mmap) = %d", seccomp_arch_to_string(arch), SCMP_SYS(mmap));
     519         [ +  - ]:         12 :                 log_debug("arch %s: SCMP_SYS(mmap2) = %d", seccomp_arch_to_string(arch), SCMP_SYS(mmap2));
     520         [ +  - ]:         12 :                 log_debug("arch %s: SCMP_SYS(shmget) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmget));
     521         [ +  - ]:         12 :                 log_debug("arch %s: SCMP_SYS(shmat) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmat));
     522         [ +  - ]:         12 :                 log_debug("arch %s: SCMP_SYS(shmdt) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmdt));
     523                 :            :         }
     524                 :            : 
     525         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     526         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     527                 :          0 :                 return;
     528                 :            :         }
     529         [ +  - ]:          4 :         if (geteuid() != 0) {
     530         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     531                 :          4 :                 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                 :          4 : static void test_restrict_archs(void) {
     576                 :            :         pid_t pid;
     577                 :            : 
     578         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     579                 :            : 
     580         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     581         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     582                 :          0 :                 return;
     583                 :            :         }
     584         [ +  - ]:          4 :         if (geteuid() != 0) {
     585         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     586                 :          4 :                 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                 :          4 : static void test_load_syscall_filter_set_raw(void) {
     616                 :            :         pid_t pid;
     617                 :            : 
     618         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     619                 :            : 
     620         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     621         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     622                 :          0 :                 return;
     623                 :            :         }
     624         [ +  - ]:          4 :         if (geteuid() != 0) {
     625         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     626                 :          4 :                 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                 :          4 : static void test_lock_personality(void) {
     713                 :            :         unsigned long current;
     714                 :            :         pid_t pid;
     715                 :            : 
     716         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     717                 :            : 
     718         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     719         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     720                 :          4 :                 return;
     721                 :            :         }
     722         [ +  - ]:          4 :         if (geteuid() != 0) {
     723         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     724                 :          4 :                 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                 :          4 : static void test_restrict_suid_sgid(void) {
     778                 :            :         pid_t pid;
     779                 :            : 
     780         [ +  - ]:          4 :         log_info("/* %s */", __func__);
     781                 :            : 
     782         [ -  + ]:          4 :         if (!is_seccomp_available()) {
     783         [ #  # ]:          0 :                 log_notice("Seccomp not available, skipping %s", __func__);
     784                 :          0 :                 return;
     785                 :            :         }
     786         [ +  - ]:          4 :         if (geteuid() != 0) {
     787         [ +  - ]:          4 :                 log_notice("Not root, skipping %s", __func__);
     788                 :          4 :                 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                 :          4 : int main(int argc, char *argv[]) {
     976                 :          4 :         test_setup_logging(LOG_DEBUG);
     977                 :            : 
     978                 :          4 :         test_seccomp_arch_to_string();
     979                 :          4 :         test_architecture_table();
     980                 :          4 :         test_syscall_filter_set_find();
     981                 :          4 :         test_filter_sets();
     982                 :          4 :         test_filter_sets_ordered();
     983                 :          4 :         test_restrict_namespace();
     984                 :          4 :         test_protect_sysctl();
     985                 :          4 :         test_restrict_address_families();
     986                 :          4 :         test_restrict_realtime();
     987                 :          4 :         test_memory_deny_write_execute_mmap();
     988                 :          4 :         test_memory_deny_write_execute_shmat();
     989                 :          4 :         test_restrict_archs();
     990                 :          4 :         test_load_syscall_filter_set_raw();
     991                 :          4 :         test_lock_personality();
     992                 :          4 :         test_restrict_suid_sgid();
     993                 :            : 
     994                 :          4 :         return 0;
     995                 :            : }

Generated by: LCOV version 1.14