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