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