1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include <sys/eventfd.h>
8 #include <sys/personality.h>
10 #include <sys/syscall.h>
11 #include <sys/types.h>
13 #if HAVE_VALGRIND_VALGRIND_H
14 #include <valgrind/valgrind.h>
17 #include "alloc-util.h"
18 #include "capability-util.h"
22 #include "memory-util.h"
23 #include "missing_sched.h"
25 #include "nulstr-util.h"
26 #include "process-util.h"
27 #include "raw-clone.h"
29 #include "seccomp-util.h"
31 #include "string-util.h"
33 #include "tmpfile-util.h"
36 /* __NR_socket may be invalid due to libseccomp */
37 #if !defined(__NR_socket) || __NR_socket < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) || defined(__powerpc64__) || defined(__powerpc__)
38 /* On these archs, socket() is implemented via the socketcall() syscall multiplexer,
39 * and we can't restrict it hence via seccomp. */
40 # define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1
42 # define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0
45 static bool have_seccomp_privs(void) {
46 return geteuid() == 0 && have_effective_cap(CAP_SYS_ADMIN
) > 0; /* If we are root but CAP_SYS_ADMIN we can't do caps (unless we also do NNP) */
49 static void test_parse_syscall_and_errno(void) {
50 _cleanup_free_
char *n
= NULL
;
53 assert_se(parse_syscall_and_errno("uname:EILSEQ", &n
, &e
) >= 0);
54 assert_se(streq(n
, "uname"));
55 assert_se(e
== errno_from_name("EILSEQ") && e
>= 0);
58 assert_se(parse_syscall_and_errno("uname:EINVAL", &n
, &e
) >= 0);
59 assert_se(streq(n
, "uname"));
60 assert_se(e
== errno_from_name("EINVAL") && e
>= 0);
63 assert_se(parse_syscall_and_errno("@sync:4095", &n
, &e
) >= 0);
64 assert_se(streq(n
, "@sync"));
68 /* If errno is omitted, then e is set to -1 */
69 assert_se(parse_syscall_and_errno("mount", &n
, &e
) >= 0);
70 assert_se(streq(n
, "mount"));
74 /* parse_syscall_and_errno() does not check the syscall name is valid or not. */
75 assert_se(parse_syscall_and_errno("hoge:255", &n
, &e
) >= 0);
76 assert_se(streq(n
, "hoge"));
80 /* 0 is also a valid errno. */
81 assert_se(parse_syscall_and_errno("hoge:0", &n
, &e
) >= 0);
82 assert_se(streq(n
, "hoge"));
86 assert_se(parse_syscall_and_errno("hoge:kill", &n
, &e
) >= 0);
87 assert_se(streq(n
, "hoge"));
88 assert_se(e
== SECCOMP_ERROR_NUMBER_KILL
);
91 /* The function checks the syscall name is empty or not. */
92 assert_se(parse_syscall_and_errno("", &n
, &e
) == -EINVAL
);
93 assert_se(parse_syscall_and_errno(":255", &n
, &e
) == -EINVAL
);
95 /* errno must be a valid errno name or number between 0 and ERRNO_MAX == 4095, or "kill" */
96 assert_se(parse_syscall_and_errno("hoge:4096", &n
, &e
) == -ERANGE
);
97 assert_se(parse_syscall_and_errno("hoge:-3", &n
, &e
) == -ERANGE
);
98 assert_se(parse_syscall_and_errno("hoge:12.3", &n
, &e
) == -EINVAL
);
99 assert_se(parse_syscall_and_errno("hoge:123junk", &n
, &e
) == -EINVAL
);
100 assert_se(parse_syscall_and_errno("hoge:junk123", &n
, &e
) == -EINVAL
);
101 assert_se(parse_syscall_and_errno("hoge:255:EILSEQ", &n
, &e
) == -EINVAL
);
102 assert_se(parse_syscall_and_errno("hoge:-EINVAL", &n
, &e
) == -EINVAL
);
103 assert_se(parse_syscall_and_errno("hoge:EINVALaaa", &n
, &e
) == -EINVAL
);
104 assert_se(parse_syscall_and_errno("hoge:", &n
, &e
) == -EINVAL
);
107 static void test_seccomp_arch_to_string(void) {
111 log_info("/* %s */", __func__
);
113 a
= seccomp_arch_native();
115 name
= seccomp_arch_to_string(a
);
117 assert_se(seccomp_arch_from_string(name
, &b
) >= 0);
121 static void test_architecture_table(void) {
124 log_info("/* %s */", __func__
);
142 #ifdef SCMP_ARCH_RISCV64
149 assert_se(seccomp_arch_from_string(n
, &c
) >= 0);
150 n2
= seccomp_arch_to_string(c
);
151 log_info("seccomp-arch: %s → 0x%"PRIx32
" → %s", n
, c
, n2
);
152 assert_se(streq_ptr(n
, n2
));
156 static void test_syscall_filter_set_find(void) {
157 log_info("/* %s */", __func__
);
159 assert_se(!syscall_filter_set_find(NULL
));
160 assert_se(!syscall_filter_set_find(""));
161 assert_se(!syscall_filter_set_find("quux"));
162 assert_se(!syscall_filter_set_find("@quux"));
164 assert_se(syscall_filter_set_find("@clock") == syscall_filter_sets
+ SYSCALL_FILTER_SET_CLOCK
);
165 assert_se(syscall_filter_set_find("@default") == syscall_filter_sets
+ SYSCALL_FILTER_SET_DEFAULT
);
166 assert_se(syscall_filter_set_find("@raw-io") == syscall_filter_sets
+ SYSCALL_FILTER_SET_RAW_IO
);
169 static void test_filter_sets(void) {
170 log_info("/* %s */", __func__
);
172 if (!is_seccomp_available()) {
173 log_notice("Seccomp not available, skipping %s", __func__
);
176 if (!have_seccomp_privs()) {
177 log_notice("Not privileged, skipping %s", __func__
);
181 for (unsigned i
= 0; i
< _SYSCALL_FILTER_SET_MAX
; i
++) {
184 #if HAVE_VALGRIND_VALGRIND_H
185 if (RUNNING_ON_VALGRIND
&& IN_SET(i
, SYSCALL_FILTER_SET_DEFAULT
, SYSCALL_FILTER_SET_BASIC_IO
, SYSCALL_FILTER_SET_SIGNAL
)) {
186 /* valgrind at least requires rt_sigprocmask(), read(), write(). */
187 log_info("Running on valgrind, skipping %s", syscall_filter_sets
[i
].name
);
191 #if HAS_FEATURE_ADDRESS_SANITIZER
192 if (IN_SET(i
, SYSCALL_FILTER_SET_DEFAULT
, SYSCALL_FILTER_SET_BASIC_IO
, SYSCALL_FILTER_SET_SIGNAL
)) {
193 /* ASAN at least requires sigaltstack(), read(), write(). */
194 log_info("Running on address sanitizer, skipping %s", syscall_filter_sets
[i
].name
);
199 log_info("Testing %s", syscall_filter_sets
[i
].name
);
204 if (pid
== 0) { /* Child? */
207 /* If we look at the default set (or one that includes it), allow-list instead of deny-list */
208 if (IN_SET(i
, SYSCALL_FILTER_SET_DEFAULT
,
209 SYSCALL_FILTER_SET_SYSTEM_SERVICE
,
210 SYSCALL_FILTER_SET_KNOWN
))
211 r
= seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN
), syscall_filter_sets
+ i
, SCMP_ACT_ALLOW
, true);
213 r
= seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW
, syscall_filter_sets
+ i
, SCMP_ACT_ERRNO(EUCLEAN
), true);
217 /* Test the sycall filter with one random system call */
218 fd
= eventfd(0, EFD_NONBLOCK
|EFD_CLOEXEC
);
219 if (IN_SET(i
, SYSCALL_FILTER_SET_IO_EVENT
, SYSCALL_FILTER_SET_DEFAULT
))
220 assert_se(fd
< 0 && errno
== EUCLEAN
);
229 assert_se(wait_for_terminate_and_check(syscall_filter_sets
[i
].name
, pid
, WAIT_LOG
) == EXIT_SUCCESS
);
233 static void test_filter_sets_ordered(void) {
234 log_info("/* %s */", __func__
);
236 /* Ensure "@default" always remains at the beginning of the list */
237 assert_se(SYSCALL_FILTER_SET_DEFAULT
== 0);
238 assert_se(streq(syscall_filter_sets
[0].name
, "@default"));
240 /* Ensure "@known" always remains at the end of the list */
241 assert_se(SYSCALL_FILTER_SET_KNOWN
== _SYSCALL_FILTER_SET_MAX
- 1);
242 assert_se(streq(syscall_filter_sets
[SYSCALL_FILTER_SET_KNOWN
].name
, "@known"));
244 for (size_t i
= 0; i
< _SYSCALL_FILTER_SET_MAX
; i
++) {
245 const char *k
, *p
= NULL
;
247 /* Make sure each group has a description */
248 assert_se(!isempty(syscall_filter_sets
[0].help
));
250 /* Make sure the groups are ordered alphabetically, except for the first and last entries */
251 assert_se(i
< 2 || i
== _SYSCALL_FILTER_SET_MAX
- 1 ||
252 strcmp(syscall_filter_sets
[i
-1].name
, syscall_filter_sets
[i
].name
) < 0);
254 NULSTR_FOREACH(k
, syscall_filter_sets
[i
].value
) {
256 /* Ensure each syscall list is in itself ordered, but groups before names */
258 (*p
== '@' && *k
!= '@') ||
259 (((*p
== '@' && *k
== '@') ||
260 (*p
!= '@' && *k
!= '@')) &&
268 static void test_restrict_namespace(void) {
273 if (!have_namespaces()) {
274 log_notice("Testing without namespaces, skipping %s", __func__
);
278 log_info("/* %s */", __func__
);
280 assert_se(namespace_flags_to_string(0, &s
) == 0 && isempty(s
));
282 assert_se(namespace_flags_to_string(CLONE_NEWNS
, &s
) == 0 && streq(s
, "mnt"));
284 assert_se(namespace_flags_to_string(CLONE_NEWNS
|CLONE_NEWIPC
, &s
) == 0 && streq(s
, "ipc mnt"));
286 assert_se(namespace_flags_to_string(CLONE_NEWCGROUP
, &s
) == 0 && streq(s
, "cgroup"));
289 assert_se(namespace_flags_from_string("mnt", &ul
) == 0 && ul
== CLONE_NEWNS
);
290 assert_se(namespace_flags_from_string(NULL
, &ul
) == 0 && ul
== 0);
291 assert_se(namespace_flags_from_string("", &ul
) == 0 && ul
== 0);
292 assert_se(namespace_flags_from_string("uts", &ul
) == 0 && ul
== CLONE_NEWUTS
);
293 assert_se(namespace_flags_from_string("mnt uts ipc", &ul
) == 0 && ul
== (CLONE_NEWNS
|CLONE_NEWUTS
|CLONE_NEWIPC
));
295 assert_se(namespace_flags_to_string(CLONE_NEWUTS
, &s
) == 0 && streq(s
, "uts"));
296 assert_se(namespace_flags_from_string(s
, &ul
) == 0 && ul
== CLONE_NEWUTS
);
298 assert_se(namespace_flags_from_string("ipc", &ul
) == 0 && ul
== CLONE_NEWIPC
);
299 assert_se(namespace_flags_to_string(ul
, &s
) == 0 && streq(s
, "ipc"));
302 assert_se(namespace_flags_to_string(NAMESPACE_FLAGS_ALL
, &s
) == 0);
303 assert_se(streq(s
, "cgroup ipc net mnt pid user uts"));
304 assert_se(namespace_flags_from_string(s
, &ul
) == 0 && ul
== NAMESPACE_FLAGS_ALL
);
307 if (!is_seccomp_available()) {
308 log_notice("Seccomp not available, skipping remaining tests in %s", __func__
);
311 if (!have_seccomp_privs()) {
312 log_notice("Not privileged, skipping remaining tests in %s", __func__
);
321 assert_se(seccomp_restrict_namespaces(CLONE_NEWNS
|CLONE_NEWNET
) >= 0);
323 assert_se(unshare(CLONE_NEWNS
) == 0);
324 assert_se(unshare(CLONE_NEWNET
) == 0);
325 assert_se(unshare(CLONE_NEWUTS
) == -1);
326 assert_se(errno
== EPERM
);
327 assert_se(unshare(CLONE_NEWIPC
) == -1);
328 assert_se(errno
== EPERM
);
329 assert_se(unshare(CLONE_NEWNET
|CLONE_NEWUTS
) == -1);
330 assert_se(errno
== EPERM
);
332 /* We use fd 0 (stdin) here, which of course will fail with EINVAL on setns(). Except of course our
333 * seccomp filter worked, and hits first and makes it return EPERM */
334 assert_se(setns(0, CLONE_NEWNS
) == -1);
335 assert_se(errno
== EINVAL
);
336 assert_se(setns(0, CLONE_NEWNET
) == -1);
337 assert_se(errno
== EINVAL
);
338 assert_se(setns(0, CLONE_NEWUTS
) == -1);
339 assert_se(errno
== EPERM
);
340 assert_se(setns(0, CLONE_NEWIPC
) == -1);
341 assert_se(errno
== EPERM
);
342 assert_se(setns(0, CLONE_NEWNET
|CLONE_NEWUTS
) == -1);
343 assert_se(errno
== EPERM
);
344 assert_se(setns(0, 0) == -1);
345 assert_se(errno
== EPERM
);
347 pid
= raw_clone(CLONE_NEWNS
);
351 pid
= raw_clone(CLONE_NEWNET
);
355 pid
= raw_clone(CLONE_NEWUTS
);
357 assert_se(errno
== EPERM
);
358 pid
= raw_clone(CLONE_NEWIPC
);
360 assert_se(errno
== EPERM
);
361 pid
= raw_clone(CLONE_NEWNET
|CLONE_NEWUTS
);
363 assert_se(errno
== EPERM
);
368 assert_se(wait_for_terminate_and_check("nsseccomp", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
371 static void test_protect_sysctl(void) {
373 _cleanup_free_
char *seccomp
= NULL
;
375 log_info("/* %s */", __func__
);
377 if (!is_seccomp_available()) {
378 log_notice("Seccomp not available, skipping %s", __func__
);
381 if (!have_seccomp_privs()) {
382 log_notice("Not privileged, skipping %s", __func__
);
386 /* in containers _sysctl() is likely missing anyway */
387 if (detect_container() > 0) {
388 log_notice("Testing in container, skipping %s", __func__
);
392 assert_se(get_proc_field("/proc/self/status", "Seccomp", WHITESPACE
, &seccomp
) == 0);
393 if (!streq(seccomp
, "0"))
394 log_warning("Warning: seccomp filter detected, results may be unreliable for %s", __func__
);
400 #if defined __NR__sysctl && __NR__sysctl >= 0
401 assert_se(syscall(__NR__sysctl
, NULL
) < 0);
402 assert_se(IN_SET(errno
, EFAULT
, ENOSYS
));
405 assert_se(seccomp_protect_sysctl() >= 0);
407 #if HAVE_VALGRIND_VALGRIND_H
408 if (RUNNING_ON_VALGRIND
) {
409 log_info("Running on valgrind, skipping syscall/EPERM test");
414 #if defined __NR__sysctl && __NR__sysctl >= 0
415 assert_se(syscall(__NR__sysctl
, 0, 0, 0) < 0);
416 assert_se(errno
== EPERM
);
422 assert_se(wait_for_terminate_and_check("sysctlseccomp", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
425 static void test_protect_syslog(void) {
428 log_info("/* %s */", __func__
);
430 if (!is_seccomp_available()) {
431 log_notice("Seccomp not available, skipping %s", __func__
);
434 if (!have_seccomp_privs()) {
435 log_notice("Not privileged, skipping %s", __func__
);
439 /* in containers syslog() is likely missing anyway */
440 if (detect_container() > 0) {
441 log_notice("Testing in container, skipping %s", __func__
);
449 #if defined __NR_syslog && __NR_syslog >= 0
450 assert_se(syscall(__NR_syslog
, -1, NULL
, 0) < 0);
451 assert_se(errno
== EINVAL
);
454 assert_se(seccomp_protect_syslog() >= 0);
456 #if defined __NR_syslog && __NR_syslog >= 0
457 assert_se(syscall(__NR_syslog
, 0, 0, 0) < 0);
458 assert_se(errno
== EPERM
);
464 assert_se(wait_for_terminate_and_check("syslogseccomp", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
467 static void test_restrict_address_families(void) {
470 log_info("/* %s */", __func__
);
472 if (!is_seccomp_available()) {
473 log_notice("Seccomp not available, skipping %s", __func__
);
476 if (!have_seccomp_privs()) {
477 log_notice("Not privileged, skipping %s", __func__
);
488 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
492 fd
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
496 fd
= socket(AF_NETLINK
, SOCK_DGRAM
, 0);
500 assert_se(s
= set_new(NULL
));
501 assert_se(set_put(s
, INT_TO_PTR(AF_UNIX
)) >= 0);
503 assert_se(seccomp_restrict_address_families(s
, false) >= 0);
505 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
509 fd
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
510 #if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
515 assert_se(errno
== EAFNOSUPPORT
);
518 fd
= socket(AF_NETLINK
, SOCK_DGRAM
, 0);
524 assert_se(set_put(s
, INT_TO_PTR(AF_INET
)) >= 0);
526 assert_se(seccomp_restrict_address_families(s
, true) >= 0);
528 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
532 fd
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
533 #if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
538 assert_se(errno
== EAFNOSUPPORT
);
541 fd
= socket(AF_NETLINK
, SOCK_DGRAM
, 0);
542 #if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
547 assert_se(errno
== EAFNOSUPPORT
);
553 assert_se(wait_for_terminate_and_check("socketseccomp", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
556 static void test_restrict_realtime(void) {
559 log_info("/* %s */", __func__
);
561 if (!is_seccomp_available()) {
562 log_notice("Seccomp not available, skipping %s", __func__
);
565 if (!have_seccomp_privs()) {
566 log_notice("Not privileged, skipping %s", __func__
);
570 /* in containers RT privs are likely missing anyway */
571 if (detect_container() > 0) {
572 log_notice("Testing in container, skipping %s", __func__
);
580 assert_se(sched_setscheduler(0, SCHED_FIFO
, &(struct sched_param
) { .sched_priority
= 1 }) >= 0);
581 assert_se(sched_setscheduler(0, SCHED_RR
, &(struct sched_param
) { .sched_priority
= 1 }) >= 0);
582 assert_se(sched_setscheduler(0, SCHED_IDLE
, &(struct sched_param
) { .sched_priority
= 0 }) >= 0);
583 assert_se(sched_setscheduler(0, SCHED_BATCH
, &(struct sched_param
) { .sched_priority
= 0 }) >= 0);
584 assert_se(sched_setscheduler(0, SCHED_OTHER
, &(struct sched_param
) {}) >= 0);
586 assert_se(seccomp_restrict_realtime() >= 0);
588 assert_se(sched_setscheduler(0, SCHED_IDLE
, &(struct sched_param
) { .sched_priority
= 0 }) >= 0);
589 assert_se(sched_setscheduler(0, SCHED_BATCH
, &(struct sched_param
) { .sched_priority
= 0 }) >= 0);
590 assert_se(sched_setscheduler(0, SCHED_OTHER
, &(struct sched_param
) {}) >= 0);
592 assert_se(sched_setscheduler(0, SCHED_FIFO
, &(struct sched_param
) { .sched_priority
= 1 }) < 0);
593 assert_se(errno
== EPERM
);
594 assert_se(sched_setscheduler(0, SCHED_RR
, &(struct sched_param
) { .sched_priority
= 1 }) < 0);
595 assert_se(errno
== EPERM
);
600 assert_se(wait_for_terminate_and_check("realtimeseccomp", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
603 static void test_memory_deny_write_execute_mmap(void) {
606 log_info("/* %s */", __func__
);
608 if (!is_seccomp_available()) {
609 log_notice("Seccomp not available, skipping %s", __func__
);
612 if (!have_seccomp_privs()) {
613 log_notice("Not privileged, skipping %s", __func__
);
616 #if HAVE_VALGRIND_VALGRIND_H
617 if (RUNNING_ON_VALGRIND
) {
618 log_notice("Running on valgrind, skipping %s", __func__
);
622 #if HAS_FEATURE_ADDRESS_SANITIZER
623 log_notice("Running on address sanitizer, skipping %s", __func__
);
633 p
= mmap(NULL
, page_size(), PROT_WRITE
|PROT_EXEC
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1,0);
634 assert_se(p
!= MAP_FAILED
);
635 assert_se(munmap(p
, page_size()) >= 0);
637 p
= mmap(NULL
, page_size(), PROT_WRITE
|PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1,0);
638 assert_se(p
!= MAP_FAILED
);
639 assert_se(munmap(p
, page_size()) >= 0);
641 assert_se(seccomp_memory_deny_write_execute() >= 0);
643 p
= mmap(NULL
, page_size(), PROT_WRITE
|PROT_EXEC
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1,0);
644 #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc64__) || defined(__arm__) || defined(__aarch64__)
645 assert_se(p
== MAP_FAILED
);
646 assert_se(errno
== EPERM
);
648 /* Depending on kernel, libseccomp, and glibc versions, other architectures
649 * might fail or not. Let's not assert success. */
651 assert_se(munmap(p
, page_size()) == 0);
653 p
= mmap(NULL
, page_size(), PROT_WRITE
|PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1,0);
654 assert_se(p
!= MAP_FAILED
);
655 assert_se(munmap(p
, page_size()) >= 0);
660 assert_se(wait_for_terminate_and_check("memoryseccomp-mmap", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
663 static void test_memory_deny_write_execute_shmat(void) {
668 log_info("/* %s */", __func__
);
670 SECCOMP_FOREACH_LOCAL_ARCH(arch
) {
671 log_debug("arch %s: SCMP_SYS(mmap) = %d", seccomp_arch_to_string(arch
), SCMP_SYS(mmap
));
672 log_debug("arch %s: SCMP_SYS(mmap2) = %d", seccomp_arch_to_string(arch
), SCMP_SYS(mmap2
));
673 log_debug("arch %s: SCMP_SYS(shmget) = %d", seccomp_arch_to_string(arch
), SCMP_SYS(shmget
));
674 log_debug("arch %s: SCMP_SYS(shmat) = %d", seccomp_arch_to_string(arch
), SCMP_SYS(shmat
));
675 log_debug("arch %s: SCMP_SYS(shmdt) = %d", seccomp_arch_to_string(arch
), SCMP_SYS(shmdt
));
678 if (!is_seccomp_available()) {
679 log_notice("Seccomp not available, skipping %s", __func__
);
682 if (!have_seccomp_privs()) {
683 log_notice("Not privileged, skipping %s", __func__
);
686 #if HAVE_VALGRIND_VALGRIND_H
687 if (RUNNING_ON_VALGRIND
) {
688 log_notice("Running on valgrind, skipping %s", __func__
);
692 #if HAS_FEATURE_ADDRESS_SANITIZER
693 log_notice("Running on address sanitizer, skipping %s", __func__
);
697 shmid
= shmget(IPC_PRIVATE
, page_size(), 0);
698 assert_se(shmid
>= 0);
706 p
= shmat(shmid
, NULL
, 0);
707 assert_se(p
!= MAP_FAILED
);
708 assert_se(shmdt(p
) == 0);
710 p
= shmat(shmid
, NULL
, SHM_EXEC
);
711 assert_se(p
!= MAP_FAILED
);
712 assert_se(shmdt(p
) == 0);
714 assert_se(seccomp_memory_deny_write_execute() >= 0);
716 p
= shmat(shmid
, NULL
, SHM_EXEC
);
717 log_debug_errno(p
== MAP_FAILED
? errno
: 0, "shmat(SHM_EXEC): %m");
718 #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
719 assert_se(p
== MAP_FAILED
);
720 assert_se(errno
== EPERM
);
722 /* Depending on kernel, libseccomp, and glibc versions, other architectures
723 * might fail or not. Let's not assert success. */
725 assert_se(shmdt(p
) == 0);
727 p
= shmat(shmid
, NULL
, 0);
728 log_debug_errno(p
== MAP_FAILED
? errno
: 0, "shmat(0): %m");
729 assert_se(p
!= MAP_FAILED
);
730 assert_se(shmdt(p
) == 0);
735 assert_se(wait_for_terminate_and_check("memoryseccomp-shmat", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
738 static void test_restrict_archs(void) {
741 log_info("/* %s */", __func__
);
743 if (!is_seccomp_available()) {
744 log_notice("Seccomp not available, skipping %s", __func__
);
747 if (!have_seccomp_privs()) {
748 log_notice("Not privileged, skipping %s", __func__
);
756 _cleanup_set_free_ Set
*s
= NULL
;
758 assert_se(access("/", F_OK
) >= 0);
760 assert_se(s
= set_new(NULL
));
763 assert_se(set_put(s
, UINT32_TO_PTR(SCMP_ARCH_X86
+1)) >= 0);
765 assert_se(seccomp_restrict_archs(s
) >= 0);
767 assert_se(access("/", F_OK
) >= 0);
768 assert_se(seccomp_restrict_archs(NULL
) >= 0);
770 assert_se(access("/", F_OK
) >= 0);
775 assert_se(wait_for_terminate_and_check("archseccomp", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
778 static void test_load_syscall_filter_set_raw(void) {
781 log_info("/* %s */", __func__
);
783 if (!is_seccomp_available()) {
784 log_notice("Seccomp not available, skipping %s", __func__
);
787 if (!have_seccomp_privs()) {
788 log_notice("Not privileged, skipping %s", __func__
);
796 _cleanup_hashmap_free_ Hashmap
*s
= NULL
;
798 assert_se(access("/", F_OK
) >= 0);
799 assert_se(poll(NULL
, 0, 0) == 0);
801 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW
, NULL
, scmp_act_kill_process(), true) >= 0);
802 assert_se(access("/", F_OK
) >= 0);
803 assert_se(poll(NULL
, 0, 0) == 0);
805 assert_se(s
= hashmap_new(NULL
));
806 #if defined __NR_access && __NR_access >= 0
807 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_access
+ 1), INT_TO_PTR(-1)) >= 0);
808 log_debug("has access()");
810 #if defined __NR_faccessat && __NR_faccessat >= 0
811 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_faccessat
+ 1), INT_TO_PTR(-1)) >= 0);
812 log_debug("has faccessat()");
814 #if defined __NR_faccessat2 && __NR_faccessat2 >= 0
815 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_faccessat2
+ 1), INT_TO_PTR(-1)) >= 0);
816 log_debug("has faccessat2()");
819 assert_se(!hashmap_isempty(s
));
820 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW
, s
, SCMP_ACT_ERRNO(EUCLEAN
), true) >= 0);
822 assert_se(access("/", F_OK
) < 0);
823 assert_se(errno
== EUCLEAN
);
825 assert_se(poll(NULL
, 0, 0) == 0);
828 #if defined __NR_access && __NR_access >= 0
829 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_access
+ 1), INT_TO_PTR(EILSEQ
)) >= 0);
831 #if defined __NR_faccessat && __NR_faccessat >= 0
832 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_faccessat
+ 1), INT_TO_PTR(EILSEQ
)) >= 0);
834 #if defined __NR_faccessat2 && __NR_faccessat2 >= 0
835 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_faccessat2
+ 1), INT_TO_PTR(EILSEQ
)) >= 0);
838 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW
, s
, SCMP_ACT_ERRNO(EUCLEAN
), true) >= 0);
840 assert_se(access("/", F_OK
) < 0);
841 assert_se(errno
== EILSEQ
);
843 assert_se(poll(NULL
, 0, 0) == 0);
846 #if defined __NR_poll && __NR_poll >= 0
847 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_poll
+ 1), INT_TO_PTR(-1)) >= 0);
848 log_debug("has poll()");
850 #if defined __NR_ppoll && __NR_ppoll >= 0
851 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_ppoll
+ 1), INT_TO_PTR(-1)) >= 0);
852 log_debug("has ppoll()");
854 #if defined __NR_ppoll_time64 && __NR_ppoll_time64 >= 0
855 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_ppoll_time64
+ 1), INT_TO_PTR(-1)) >= 0);
856 log_debug("has ppoll_time64()");
859 assert_se(!hashmap_isempty(s
));
860 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW
, s
, SCMP_ACT_ERRNO(EUNATCH
), true) >= 0);
862 assert_se(access("/", F_OK
) < 0);
863 assert_se(errno
== EILSEQ
);
865 assert_se(poll(NULL
, 0, 0) < 0);
866 assert_se(errno
== EUNATCH
);
869 #if defined __NR_poll && __NR_poll >= 0
870 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_poll
+ 1), INT_TO_PTR(EILSEQ
)) >= 0);
872 #if defined __NR_ppoll && __NR_ppoll >= 0
873 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_ppoll
+ 1), INT_TO_PTR(EILSEQ
)) >= 0);
875 #if defined __NR_ppoll_time64 && __NR_ppoll_time64 >= 0
876 assert_se(hashmap_put(s
, UINT32_TO_PTR(__NR_ppoll_time64
+ 1), INT_TO_PTR(EILSEQ
)) >= 0);
879 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW
, s
, SCMP_ACT_ERRNO(EUNATCH
), true) >= 0);
881 assert_se(access("/", F_OK
) < 0);
882 assert_se(errno
== EILSEQ
);
884 assert_se(poll(NULL
, 0, 0) < 0);
885 assert_se(errno
== EILSEQ
);
890 assert_se(wait_for_terminate_and_check("syscallrawseccomp", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
893 static void test_lock_personality(void) {
894 unsigned long current
;
897 log_info("/* %s */", __func__
);
899 if (!is_seccomp_available()) {
900 log_notice("Seccomp not available, skipping %s", __func__
);
903 if (!have_seccomp_privs()) {
904 log_notice("Not privileged, skipping %s", __func__
);
908 assert_se(opinionated_personality(¤t
) >= 0);
910 log_info("current personality=%lu", current
);
916 assert_se(seccomp_lock_personality(current
) >= 0);
918 assert_se((unsigned long) safe_personality(current
) == current
);
920 /* Note, we also test that safe_personality() works correctly, by checkig whether errno is properly
921 * set, in addition to the return value */
923 assert_se(safe_personality(PER_LINUX
| ADDR_NO_RANDOMIZE
) == -EPERM
);
924 assert_se(errno
== EPERM
);
926 assert_se(safe_personality(PER_LINUX
| MMAP_PAGE_ZERO
) == -EPERM
);
927 assert_se(safe_personality(PER_LINUX
| ADDR_COMPAT_LAYOUT
) == -EPERM
);
928 assert_se(safe_personality(PER_LINUX
| READ_IMPLIES_EXEC
) == -EPERM
);
929 assert_se(safe_personality(PER_LINUX_32BIT
) == -EPERM
);
930 assert_se(safe_personality(PER_SVR4
) == -EPERM
);
931 assert_se(safe_personality(PER_BSD
) == -EPERM
);
932 assert_se(safe_personality(current
== PER_LINUX
? PER_LINUX32
: PER_LINUX
) == -EPERM
);
933 assert_se(safe_personality(PER_LINUX32_3GB
) == -EPERM
);
934 assert_se(safe_personality(PER_UW7
) == -EPERM
);
935 assert_se(safe_personality(0x42) == -EPERM
);
937 assert_se(safe_personality(PERSONALITY_INVALID
) == -EPERM
); /* maybe remove this later */
939 assert_se((unsigned long) personality(current
) == current
);
943 assert_se(wait_for_terminate_and_check("lockpersonalityseccomp", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
946 static int real_open(const char *path
, int flags
, mode_t mode
) {
947 /* glibc internally calls openat() when open() is requested. Let's hence define our own wrapper for
948 * testing purposes that calls the real syscall, on architectures where SYS_open is defined. On
949 * other architectures, let's just fall back to the glibc call. */
951 #if defined __NR_open && __NR_open >= 0
952 return (int) syscall(__NR_open
, path
, flags
, mode
);
954 return open(path
, flags
, mode
);
958 static void test_restrict_suid_sgid(void) {
961 log_info("/* %s */", __func__
);
963 if (!is_seccomp_available()) {
964 log_notice("Seccomp not available, skipping %s", __func__
);
967 if (!have_seccomp_privs()) {
968 log_notice("Not privileged, skipping %s", __func__
);
976 char path
[] = "/tmp/suidsgidXXXXXX", dir
[] = "/tmp/suidsgiddirXXXXXX";
980 fd
= mkostemp_safe(path
);
983 assert_se(mkdtemp(dir
));
984 z
= strjoina(dir
, "/test");
986 assert_se(chmod(path
, 0755 | S_ISUID
) >= 0);
987 assert_se(chmod(path
, 0755 | S_ISGID
) >= 0);
988 assert_se(chmod(path
, 0755 | S_ISGID
| S_ISUID
) >= 0);
989 assert_se(chmod(path
, 0755) >= 0);
991 assert_se(fchmod(fd
, 0755 | S_ISUID
) >= 0);
992 assert_se(fchmod(fd
, 0755 | S_ISGID
) >= 0);
993 assert_se(fchmod(fd
, 0755 | S_ISGID
| S_ISUID
) >= 0);
994 assert_se(fchmod(fd
, 0755) >= 0);
996 assert_se(fchmodat(AT_FDCWD
, path
, 0755 | S_ISUID
, 0) >= 0);
997 assert_se(fchmodat(AT_FDCWD
, path
, 0755 | S_ISGID
, 0) >= 0);
998 assert_se(fchmodat(AT_FDCWD
, path
, 0755 | S_ISGID
| S_ISUID
, 0) >= 0);
999 assert_se(fchmodat(AT_FDCWD
, path
, 0755, 0) >= 0);
1001 k
= real_open(z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISUID
);
1003 assert_se(unlink(z
) >= 0);
1005 k
= real_open(z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISGID
);
1007 assert_se(unlink(z
) >= 0);
1009 k
= real_open(z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISUID
| S_ISGID
);
1011 assert_se(unlink(z
) >= 0);
1013 k
= real_open(z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644);
1015 assert_se(unlink(z
) >= 0);
1017 k
= creat(z
, 0644 | S_ISUID
);
1019 assert_se(unlink(z
) >= 0);
1021 k
= creat(z
, 0644 | S_ISGID
);
1023 assert_se(unlink(z
) >= 0);
1025 k
= creat(z
, 0644 | S_ISUID
| S_ISGID
);
1027 assert_se(unlink(z
) >= 0);
1031 assert_se(unlink(z
) >= 0);
1033 k
= openat(AT_FDCWD
, z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISUID
);
1035 assert_se(unlink(z
) >= 0);
1037 k
= openat(AT_FDCWD
, z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISGID
);
1039 assert_se(unlink(z
) >= 0);
1041 k
= openat(AT_FDCWD
, z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISUID
| S_ISGID
);
1043 assert_se(unlink(z
) >= 0);
1045 k
= openat(AT_FDCWD
, z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644);
1047 assert_se(unlink(z
) >= 0);
1049 assert_se(mkdir(z
, 0755 | S_ISUID
) >= 0);
1050 assert_se(rmdir(z
) >= 0);
1051 assert_se(mkdir(z
, 0755 | S_ISGID
) >= 0);
1052 assert_se(rmdir(z
) >= 0);
1053 assert_se(mkdir(z
, 0755 | S_ISUID
| S_ISGID
) >= 0);
1054 assert_se(rmdir(z
) >= 0);
1055 assert_se(mkdir(z
, 0755) >= 0);
1056 assert_se(rmdir(z
) >= 0);
1058 assert_se(mkdirat(AT_FDCWD
, z
, 0755 | S_ISUID
) >= 0);
1059 assert_se(rmdir(z
) >= 0);
1060 assert_se(mkdirat(AT_FDCWD
, z
, 0755 | S_ISGID
) >= 0);
1061 assert_se(rmdir(z
) >= 0);
1062 assert_se(mkdirat(AT_FDCWD
, z
, 0755 | S_ISUID
| S_ISGID
) >= 0);
1063 assert_se(rmdir(z
) >= 0);
1064 assert_se(mkdirat(AT_FDCWD
, z
, 0755) >= 0);
1065 assert_se(rmdir(z
) >= 0);
1067 assert_se(mknod(z
, S_IFREG
| 0755 | S_ISUID
, 0) >= 0);
1068 assert_se(unlink(z
) >= 0);
1069 assert_se(mknod(z
, S_IFREG
| 0755 | S_ISGID
, 0) >= 0);
1070 assert_se(unlink(z
) >= 0);
1071 assert_se(mknod(z
, S_IFREG
| 0755 | S_ISUID
| S_ISGID
, 0) >= 0);
1072 assert_se(unlink(z
) >= 0);
1073 assert_se(mknod(z
, S_IFREG
| 0755, 0) >= 0);
1074 assert_se(unlink(z
) >= 0);
1076 assert_se(mknodat(AT_FDCWD
, z
, S_IFREG
| 0755 | S_ISUID
, 0) >= 0);
1077 assert_se(unlink(z
) >= 0);
1078 assert_se(mknodat(AT_FDCWD
, z
, S_IFREG
| 0755 | S_ISGID
, 0) >= 0);
1079 assert_se(unlink(z
) >= 0);
1080 assert_se(mknodat(AT_FDCWD
, z
, S_IFREG
| 0755 | S_ISUID
| S_ISGID
, 0) >= 0);
1081 assert_se(unlink(z
) >= 0);
1082 assert_se(mknodat(AT_FDCWD
, z
, S_IFREG
| 0755, 0) >= 0);
1083 assert_se(unlink(z
) >= 0);
1085 assert_se(seccomp_restrict_suid_sgid() >= 0);
1087 assert_se(chmod(path
, 0775 | S_ISUID
) < 0 && errno
== EPERM
);
1088 assert_se(chmod(path
, 0775 | S_ISGID
) < 0 && errno
== EPERM
);
1089 assert_se(chmod(path
, 0775 | S_ISGID
| S_ISUID
) < 0 && errno
== EPERM
);
1090 assert_se(chmod(path
, 0775) >= 0);
1092 assert_se(fchmod(fd
, 0775 | S_ISUID
) < 0 && errno
== EPERM
);
1093 assert_se(fchmod(fd
, 0775 | S_ISGID
) < 0 && errno
== EPERM
);
1094 assert_se(fchmod(fd
, 0775 | S_ISGID
| S_ISUID
) < 0 && errno
== EPERM
);
1095 assert_se(fchmod(fd
, 0775) >= 0);
1097 assert_se(fchmodat(AT_FDCWD
, path
, 0755 | S_ISUID
, 0) < 0 && errno
== EPERM
);
1098 assert_se(fchmodat(AT_FDCWD
, path
, 0755 | S_ISGID
, 0) < 0 && errno
== EPERM
);
1099 assert_se(fchmodat(AT_FDCWD
, path
, 0755 | S_ISGID
| S_ISUID
, 0) < 0 && errno
== EPERM
);
1100 assert_se(fchmodat(AT_FDCWD
, path
, 0755, 0) >= 0);
1102 assert_se(real_open(z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISUID
) < 0 && errno
== EPERM
);
1103 assert_se(real_open(z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISGID
) < 0 && errno
== EPERM
);
1104 assert_se(real_open(z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISUID
| S_ISGID
) < 0 && errno
== EPERM
);
1105 k
= real_open(z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644);
1107 assert_se(unlink(z
) >= 0);
1109 assert_se(creat(z
, 0644 | S_ISUID
) < 0 && errno
== EPERM
);
1110 assert_se(creat(z
, 0644 | S_ISGID
) < 0 && errno
== EPERM
);
1111 assert_se(creat(z
, 0644 | S_ISUID
| S_ISGID
) < 0 && errno
== EPERM
);
1114 assert_se(unlink(z
) >= 0);
1116 assert_se(openat(AT_FDCWD
, z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISUID
) < 0 && errno
== EPERM
);
1117 assert_se(openat(AT_FDCWD
, z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISGID
) < 0 && errno
== EPERM
);
1118 assert_se(openat(AT_FDCWD
, z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644 | S_ISUID
| S_ISGID
) < 0 && errno
== EPERM
);
1119 k
= openat(AT_FDCWD
, z
, O_CREAT
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0644);
1121 assert_se(unlink(z
) >= 0);
1123 assert_se(mkdir(z
, 0755 | S_ISUID
) < 0 && errno
== EPERM
);
1124 assert_se(mkdir(z
, 0755 | S_ISGID
) < 0 && errno
== EPERM
);
1125 assert_se(mkdir(z
, 0755 | S_ISUID
| S_ISGID
) < 0 && errno
== EPERM
);
1126 assert_se(mkdir(z
, 0755) >= 0);
1127 assert_se(rmdir(z
) >= 0);
1129 assert_se(mkdirat(AT_FDCWD
, z
, 0755 | S_ISUID
) < 0 && errno
== EPERM
);
1130 assert_se(mkdirat(AT_FDCWD
, z
, 0755 | S_ISGID
) < 0 && errno
== EPERM
);
1131 assert_se(mkdirat(AT_FDCWD
, z
, 0755 | S_ISUID
| S_ISGID
) < 0 && errno
== EPERM
);
1132 assert_se(mkdirat(AT_FDCWD
, z
, 0755) >= 0);
1133 assert_se(rmdir(z
) >= 0);
1135 assert_se(mknod(z
, S_IFREG
| 0755 | S_ISUID
, 0) < 0 && errno
== EPERM
);
1136 assert_se(mknod(z
, S_IFREG
| 0755 | S_ISGID
, 0) < 0 && errno
== EPERM
);
1137 assert_se(mknod(z
, S_IFREG
| 0755 | S_ISUID
| S_ISGID
, 0) < 0 && errno
== EPERM
);
1138 assert_se(mknod(z
, S_IFREG
| 0755, 0) >= 0);
1139 assert_se(unlink(z
) >= 0);
1141 assert_se(mknodat(AT_FDCWD
, z
, S_IFREG
| 0755 | S_ISUID
, 0) < 0 && errno
== EPERM
);
1142 assert_se(mknodat(AT_FDCWD
, z
, S_IFREG
| 0755 | S_ISGID
, 0) < 0 && errno
== EPERM
);
1143 assert_se(mknodat(AT_FDCWD
, z
, S_IFREG
| 0755 | S_ISUID
| S_ISGID
, 0) < 0 && errno
== EPERM
);
1144 assert_se(mknodat(AT_FDCWD
, z
, S_IFREG
| 0755, 0) >= 0);
1145 assert_se(unlink(z
) >= 0);
1147 assert_se(unlink(path
) >= 0);
1148 assert_se(rm_rf(dir
, REMOVE_ROOT
|REMOVE_PHYSICAL
) >= 0);
1150 _exit(EXIT_SUCCESS
);
1153 assert_se(wait_for_terminate_and_check("suidsgidseccomp", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
1156 int main(int argc
, char *argv
[]) {
1157 test_setup_logging(LOG_DEBUG
);
1159 test_parse_syscall_and_errno();
1160 test_seccomp_arch_to_string();
1161 test_architecture_table();
1162 test_syscall_filter_set_find();
1164 test_filter_sets_ordered();
1165 test_restrict_namespace();
1166 test_protect_sysctl();
1167 test_protect_syslog();
1168 test_restrict_address_families();
1169 test_restrict_realtime();
1170 test_memory_deny_write_execute_mmap();
1171 test_memory_deny_write_execute_shmat();
1172 test_restrict_archs();
1173 test_load_syscall_filter_set_raw();
1174 test_lock_personality();
1175 test_restrict_suid_sgid();