]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-seccomp.c
tree-wide: remove Lennart's copyright lines
[thirdparty/systemd.git] / src / test / test-seccomp.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
f6281133 2
d7e454ba 3#include <poll.h>
469830d1 4#include <sched.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
ZJS
9#include <sys/shm.h>
10#include <sys/types.h>
11#include <unistd.h>
f6281133 12
add00535 13#include "alloc-util.h"
f6281133
LP
14#include "fd-util.h"
15#include "macro.h"
add00535
LP
16#include "missing.h"
17#include "nsflags.h"
f6281133 18#include "process-util.h"
add00535 19#include "raw-clone.h"
f6281133 20#include "seccomp-util.h"
469830d1 21#include "set.h"
aa34055f
ZJS
22#include "string-util.h"
23#include "util.h"
469830d1 24#include "virt.h"
f6281133 25
da1921a5
ZJS
26#if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__)
27/* On these archs, socket() is implemented via the socketcall() syscall multiplexer,
28 * and we can't restrict it hence via seccomp. */
29# define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1
30#else
31# define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0
32#endif
33
f6281133
LP
34static void test_seccomp_arch_to_string(void) {
35 uint32_t a, b;
36 const char *name;
37
38 a = seccomp_arch_native();
39 assert_se(a > 0);
40 name = seccomp_arch_to_string(a);
41 assert_se(name);
42 assert_se(seccomp_arch_from_string(name, &b) >= 0);
43 assert_se(a == b);
44}
45
aa34055f
ZJS
46static void test_architecture_table(void) {
47 const char *n, *n2;
48
49 NULSTR_FOREACH(n,
50 "native\0"
51 "x86\0"
52 "x86-64\0"
53 "x32\0"
54 "arm\0"
55 "arm64\0"
56 "mips\0"
57 "mips64\0"
58 "mips64-n32\0"
59 "mips-le\0"
60 "mips64-le\0"
61 "mips64-le-n32\0"
62 "ppc\0"
63 "ppc64\0"
64 "ppc64-le\0"
65 "s390\0"
66 "s390x\0") {
67 uint32_t c;
68
69 assert_se(seccomp_arch_from_string(n, &c) >= 0);
70 n2 = seccomp_arch_to_string(c);
71 log_info("seccomp-arch: %s → 0x%"PRIx32" → %s", n, c, n2);
72 assert_se(streq_ptr(n, n2));
73 }
74}
75
f6281133
LP
76static void test_syscall_filter_set_find(void) {
77 assert_se(!syscall_filter_set_find(NULL));
78 assert_se(!syscall_filter_set_find(""));
79 assert_se(!syscall_filter_set_find("quux"));
80 assert_se(!syscall_filter_set_find("@quux"));
81
82 assert_se(syscall_filter_set_find("@clock") == syscall_filter_sets + SYSCALL_FILTER_SET_CLOCK);
83 assert_se(syscall_filter_set_find("@default") == syscall_filter_sets + SYSCALL_FILTER_SET_DEFAULT);
84 assert_se(syscall_filter_set_find("@raw-io") == syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO);
85}
86
87static void test_filter_sets(void) {
88 unsigned i;
89 int r;
90
91 if (!is_seccomp_available())
92 return;
f6281133
LP
93 if (geteuid() != 0)
94 return;
95
96 for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
97 pid_t pid;
98
99 log_info("Testing %s", syscall_filter_sets[i].name);
100
101 pid = fork();
102 assert_se(pid >= 0);
103
104 if (pid == 0) { /* Child? */
105 int fd;
106
107 if (i == SYSCALL_FILTER_SET_DEFAULT) /* if we look at the default set, whitelist instead of blacklist */
469830d1 108 r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW);
f6281133 109 else
469830d1 110 r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN));
f6281133
LP
111 if (r < 0)
112 _exit(EXIT_FAILURE);
113
114 /* Test the sycall filter with one random system call */
115 fd = eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC);
116 if (IN_SET(i, SYSCALL_FILTER_SET_IO_EVENT, SYSCALL_FILTER_SET_DEFAULT))
469830d1 117 assert_se(fd < 0 && errno == EUCLEAN);
f6281133
LP
118 else {
119 assert_se(fd >= 0);
120 safe_close(fd);
121 }
122
123 _exit(EXIT_SUCCESS);
124 }
125
7d4904fe 126 assert_se(wait_for_terminate_and_check(syscall_filter_sets[i].name, pid, WAIT_LOG) == EXIT_SUCCESS);
f6281133
LP
127 }
128}
129
add00535 130static void test_restrict_namespace(void) {
86c2a9f1 131 char *s = NULL;
add00535 132 unsigned long ul;
469830d1 133 pid_t pid;
add00535 134
86c2a9f1
YW
135 assert_se(namespace_flags_to_string(0, &s) == 0 && streq(s, ""));
136 s = mfree(s);
137 assert_se(namespace_flags_to_string(CLONE_NEWNS, &s) == 0 && streq(s, "mnt"));
138 s = mfree(s);
139 assert_se(namespace_flags_to_string(CLONE_NEWNS|CLONE_NEWIPC, &s) == 0 && streq(s, "ipc mnt"));
140 s = mfree(s);
141 assert_se(namespace_flags_to_string(CLONE_NEWCGROUP, &s) == 0 && streq(s, "cgroup"));
142 s = mfree(s);
143
144 assert_se(namespace_flags_from_string("mnt", &ul) == 0 && ul == CLONE_NEWNS);
145 assert_se(namespace_flags_from_string(NULL, &ul) == 0 && ul == 0);
146 assert_se(namespace_flags_from_string("", &ul) == 0 && ul == 0);
147 assert_se(namespace_flags_from_string("uts", &ul) == 0 && ul == CLONE_NEWUTS);
148 assert_se(namespace_flags_from_string("mnt uts ipc", &ul) == 0 && ul == (CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC));
149
150 assert_se(namespace_flags_to_string(CLONE_NEWUTS, &s) == 0 && streq(s, "uts"));
151 assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == CLONE_NEWUTS);
152 s = mfree(s);
153 assert_se(namespace_flags_from_string("ipc", &ul) == 0 && ul == CLONE_NEWIPC);
154 assert_se(namespace_flags_to_string(ul, &s) == 0 && streq(s, "ipc"));
155 s = mfree(s);
156
157 assert_se(namespace_flags_to_string(NAMESPACE_FLAGS_ALL, &s) == 0);
add00535 158 assert_se(streq(s, "cgroup ipc net mnt pid user uts"));
86c2a9f1
YW
159 assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL);
160 s = mfree(s);
add00535
LP
161
162 if (!is_seccomp_available())
163 return;
add00535
LP
164 if (geteuid() != 0)
165 return;
166
167 pid = fork();
168 assert_se(pid >= 0);
169
170 if (pid == 0) {
171
172 assert_se(seccomp_restrict_namespaces(CLONE_NEWNS|CLONE_NEWNET) >= 0);
173
174 assert_se(unshare(CLONE_NEWNS) == 0);
175 assert_se(unshare(CLONE_NEWNET) == 0);
176 assert_se(unshare(CLONE_NEWUTS) == -1);
177 assert_se(errno == EPERM);
178 assert_se(unshare(CLONE_NEWIPC) == -1);
179 assert_se(errno == EPERM);
180 assert_se(unshare(CLONE_NEWNET|CLONE_NEWUTS) == -1);
181 assert_se(errno == EPERM);
182
183 /* We use fd 0 (stdin) here, which of course will fail with EINVAL on setns(). Except of course our
184 * seccomp filter worked, and hits first and makes it return EPERM */
185 assert_se(setns(0, CLONE_NEWNS) == -1);
186 assert_se(errno == EINVAL);
187 assert_se(setns(0, CLONE_NEWNET) == -1);
188 assert_se(errno == EINVAL);
189 assert_se(setns(0, CLONE_NEWUTS) == -1);
190 assert_se(errno == EPERM);
191 assert_se(setns(0, CLONE_NEWIPC) == -1);
192 assert_se(errno == EPERM);
193 assert_se(setns(0, CLONE_NEWNET|CLONE_NEWUTS) == -1);
194 assert_se(errno == EPERM);
195 assert_se(setns(0, 0) == -1);
196 assert_se(errno == EPERM);
197
198 pid = raw_clone(CLONE_NEWNS);
199 assert_se(pid >= 0);
200 if (pid == 0)
201 _exit(EXIT_SUCCESS);
202 pid = raw_clone(CLONE_NEWNET);
203 assert_se(pid >= 0);
204 if (pid == 0)
205 _exit(EXIT_SUCCESS);
206 pid = raw_clone(CLONE_NEWUTS);
207 assert_se(pid < 0);
208 assert_se(errno == EPERM);
209 pid = raw_clone(CLONE_NEWIPC);
210 assert_se(pid < 0);
211 assert_se(errno == EPERM);
212 pid = raw_clone(CLONE_NEWNET|CLONE_NEWUTS);
213 assert_se(pid < 0);
214 assert_se(errno == EPERM);
215
216 _exit(EXIT_SUCCESS);
217 }
218
7d4904fe 219 assert_se(wait_for_terminate_and_check("nsseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
add00535
LP
220}
221
469830d1
LP
222static void test_protect_sysctl(void) {
223 pid_t pid;
224
225 if (!is_seccomp_available())
226 return;
227 if (geteuid() != 0)
228 return;
229
230 if (detect_container() > 0) /* in containers _sysctl() is likely missing anyway */
231 return;
232
233 pid = fork();
234 assert_se(pid >= 0);
235
236 if (pid == 0) {
2e64e8f4 237#if __NR__sysctl > 0
469830d1
LP
238 assert_se(syscall(__NR__sysctl, NULL) < 0);
239 assert_se(errno == EFAULT);
2e64e8f4 240#endif
469830d1
LP
241
242 assert_se(seccomp_protect_sysctl() >= 0);
243
2e64e8f4 244#if __NR__sysctl > 0
469830d1
LP
245 assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0);
246 assert_se(errno == EPERM);
2e64e8f4 247#endif
469830d1
LP
248
249 _exit(EXIT_SUCCESS);
250 }
251
7d4904fe 252 assert_se(wait_for_terminate_and_check("sysctlseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
469830d1
LP
253}
254
255static void test_restrict_address_families(void) {
256 pid_t pid;
257
258 if (!is_seccomp_available())
259 return;
260 if (geteuid() != 0)
261 return;
262
263 pid = fork();
264 assert_se(pid >= 0);
265
266 if (pid == 0) {
267 int fd;
268 Set *s;
269
270 fd = socket(AF_INET, SOCK_DGRAM, 0);
271 assert_se(fd >= 0);
272 safe_close(fd);
273
274 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
275 assert_se(fd >= 0);
276 safe_close(fd);
277
278 fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
279 assert_se(fd >= 0);
280 safe_close(fd);
281
282 assert_se(s = set_new(NULL));
283 assert_se(set_put(s, INT_TO_PTR(AF_UNIX)) >= 0);
284
285 assert_se(seccomp_restrict_address_families(s, false) >= 0);
286
287 fd = socket(AF_INET, SOCK_DGRAM, 0);
288 assert_se(fd >= 0);
289 safe_close(fd);
290
ad8f1479 291 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
dce0e620 292#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
ad8f1479
LP
293 assert_se(fd >= 0);
294 safe_close(fd);
295#else
dce0e620 296 assert_se(fd < 0);
469830d1 297 assert_se(errno == EAFNOSUPPORT);
ad8f1479 298#endif
469830d1
LP
299
300 fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
301 assert_se(fd >= 0);
302 safe_close(fd);
303
304 set_clear(s);
305
306 assert_se(set_put(s, INT_TO_PTR(AF_INET)) >= 0);
307
308 assert_se(seccomp_restrict_address_families(s, true) >= 0);
309
310 fd = socket(AF_INET, SOCK_DGRAM, 0);
311 assert_se(fd >= 0);
312 safe_close(fd);
313
ad8f1479 314 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
dce0e620 315#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
ad8f1479
LP
316 assert_se(fd >= 0);
317 safe_close(fd);
dce0e620
ZJS
318#else
319 assert_se(fd < 0);
320 assert_se(errno == EAFNOSUPPORT);
321#endif
ad8f1479
LP
322
323 fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
dce0e620 324#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
ad8f1479
LP
325 assert_se(fd >= 0);
326 safe_close(fd);
327#else
dce0e620 328 assert_se(fd < 0);
469830d1 329 assert_se(errno == EAFNOSUPPORT);
ad8f1479 330#endif
469830d1
LP
331
332 _exit(EXIT_SUCCESS);
333 }
334
7d4904fe 335 assert_se(wait_for_terminate_and_check("socketseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
469830d1
LP
336}
337
338static void test_restrict_realtime(void) {
339 pid_t pid;
340
341 if (!is_seccomp_available())
342 return;
343 if (geteuid() != 0)
344 return;
345
346 if (detect_container() > 0) /* in containers RT privs are likely missing anyway */
347 return;
348
349 pid = fork();
350 assert_se(pid >= 0);
351
352 if (pid == 0) {
353 assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) >= 0);
354 assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) >= 0);
355 assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0);
356 assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0);
357 assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0);
358
359 assert_se(seccomp_restrict_realtime() >= 0);
360
361 assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0);
362 assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0);
363 assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0);
364
365 assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0);
366 assert_se(errno == EPERM);
367 assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) < 0);
368 assert_se(errno == EPERM);
369
370 _exit(EXIT_SUCCESS);
371 }
372
7d4904fe 373 assert_se(wait_for_terminate_and_check("realtimeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
469830d1
LP
374}
375
2a65bd94 376static void test_memory_deny_write_execute_mmap(void) {
469830d1
LP
377 pid_t pid;
378
379 if (!is_seccomp_available())
380 return;
381 if (geteuid() != 0)
382 return;
383
384 pid = fork();
385 assert_se(pid >= 0);
386
387 if (pid == 0) {
388 void *p;
389
390 p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
391 assert_se(p != MAP_FAILED);
392 assert_se(munmap(p, page_size()) >= 0);
393
8a50cf69
LP
394 p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
395 assert_se(p != MAP_FAILED);
396 assert_se(munmap(p, page_size()) >= 0);
469830d1 397
8a50cf69
LP
398 assert_se(seccomp_memory_deny_write_execute() >= 0);
399
8a50cf69 400 p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
4278d1f5 401#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc64__) || defined(__arm__) || defined(__aarch64__)
469830d1
LP
402 assert_se(p == MAP_FAILED);
403 assert_se(errno == EPERM);
2a65bd94
ZJS
404#else /* unknown architectures */
405 assert_se(p != MAP_FAILED);
406 assert_se(munmap(p, page_size()) >= 0);
8a50cf69 407#endif
469830d1
LP
408
409 p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
410 assert_se(p != MAP_FAILED);
411 assert_se(munmap(p, page_size()) >= 0);
412
413 _exit(EXIT_SUCCESS);
414 }
415
7d4904fe 416 assert_se(wait_for_terminate_and_check("memoryseccomp-mmap", pid, WAIT_LOG) == EXIT_SUCCESS);
2a65bd94
ZJS
417}
418
419static void test_memory_deny_write_execute_shmat(void) {
420 int shmid;
421 pid_t pid;
422
423 if (!is_seccomp_available())
424 return;
425 if (geteuid() != 0)
426 return;
427
428 shmid = shmget(IPC_PRIVATE, page_size(), 0);
429 assert_se(shmid >= 0);
430
431 pid = fork();
432 assert_se(pid >= 0);
433
434 if (pid == 0) {
435 void *p;
436
437 p = shmat(shmid, NULL, 0);
438 assert_se(p != MAP_FAILED);
439 assert_se(shmdt(p) == 0);
440
441 p = shmat(shmid, NULL, SHM_EXEC);
442 assert_se(p != MAP_FAILED);
443 assert_se(shmdt(p) == 0);
444
445 assert_se(seccomp_memory_deny_write_execute() >= 0);
446
447 p = shmat(shmid, NULL, SHM_EXEC);
4278d1f5 448#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
2a65bd94
ZJS
449 assert_se(p == MAP_FAILED);
450 assert_se(errno == EPERM);
2a8d6e63 451#else /* __i386__, __powerpc64__, and "unknown" architectures */
2a65bd94
ZJS
452 assert_se(p != MAP_FAILED);
453 assert_se(shmdt(p) == 0);
454#endif
455
456 p = shmat(shmid, NULL, 0);
457 assert_se(p != MAP_FAILED);
458 assert_se(shmdt(p) == 0);
459
460 _exit(EXIT_SUCCESS);
461 }
462
7d4904fe 463 assert_se(wait_for_terminate_and_check("memoryseccomp-shmat", pid, WAIT_LOG) == EXIT_SUCCESS);
469830d1
LP
464}
465
466static void test_restrict_archs(void) {
467 pid_t pid;
468
469 if (!is_seccomp_available())
470 return;
471 if (geteuid() != 0)
472 return;
473
474 pid = fork();
475 assert_se(pid >= 0);
476
477 if (pid == 0) {
478 _cleanup_set_free_ Set *s = NULL;
479
480 assert_se(access("/", F_OK) >= 0);
481
482 assert_se(s = set_new(NULL));
483
484#ifdef __x86_64__
485 assert_se(set_put(s, UINT32_TO_PTR(SCMP_ARCH_X86+1)) >= 0);
486#endif
487 assert_se(seccomp_restrict_archs(s) >= 0);
488
489 assert_se(access("/", F_OK) >= 0);
490 assert_se(seccomp_restrict_archs(NULL) >= 0);
491
492 assert_se(access("/", F_OK) >= 0);
493
494 _exit(EXIT_SUCCESS);
495 }
496
7d4904fe 497 assert_se(wait_for_terminate_and_check("archseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
469830d1
LP
498}
499
500static void test_load_syscall_filter_set_raw(void) {
501 pid_t pid;
502
503 if (!is_seccomp_available())
504 return;
505 if (geteuid() != 0)
506 return;
507
508 pid = fork();
509 assert_se(pid >= 0);
510
511 if (pid == 0) {
b4891260 512 _cleanup_hashmap_free_ Hashmap *s = NULL;
469830d1
LP
513
514 assert_se(access("/", F_OK) >= 0);
515 assert_se(poll(NULL, 0, 0) == 0);
516
517 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL) >= 0);
518 assert_se(access("/", F_OK) >= 0);
519 assert_se(poll(NULL, 0, 0) == 0);
520
b4891260 521 assert_se(s = hashmap_new(NULL));
f60a865a 522#if SCMP_SYS(access) >= 0
b4891260 523 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(-1)) >= 0);
f60a865a 524#else
b4891260 525 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0);
f60a865a 526#endif
469830d1
LP
527
528 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0);
529
530 assert_se(access("/", F_OK) < 0);
531 assert_se(errno == EUCLEAN);
532
533 assert_se(poll(NULL, 0, 0) == 0);
534
b4891260 535 s = hashmap_free(s);
469830d1 536
b4891260
YW
537 assert_se(s = hashmap_new(NULL));
538#if SCMP_SYS(access) >= 0
539 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(EILSEQ)) >= 0);
540#else
541 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0);
542#endif
543
544 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0);
545
546 assert_se(access("/", F_OK) < 0);
547 assert_se(errno == EILSEQ);
548
549 assert_se(poll(NULL, 0, 0) == 0);
550
551 s = hashmap_free(s);
552
553 assert_se(s = hashmap_new(NULL));
f60a865a 554#if SCMP_SYS(poll) >= 0
b4891260 555 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(-1)) >= 0);
f60a865a 556#else
b4891260 557 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0);
f60a865a 558#endif
469830d1
LP
559
560 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0);
561
562 assert_se(access("/", F_OK) < 0);
b4891260 563 assert_se(errno == EILSEQ);
469830d1
LP
564
565 assert_se(poll(NULL, 0, 0) < 0);
566 assert_se(errno == EUNATCH);
567
b4891260
YW
568 s = hashmap_free(s);
569
570 assert_se(s = hashmap_new(NULL));
571#if SCMP_SYS(poll) >= 0
572 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(EILSEQ)) >= 0);
573#else
574 assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0);
575#endif
576
577 assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0);
578
579 assert_se(access("/", F_OK) < 0);
580 assert_se(errno == EILSEQ);
581
582 assert_se(poll(NULL, 0, 0) < 0);
583 assert_se(errno == EILSEQ);
584
469830d1
LP
585 _exit(EXIT_SUCCESS);
586 }
587
7d4904fe 588 assert_se(wait_for_terminate_and_check("syscallrawseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
469830d1
LP
589}
590
78e864e5 591static void test_lock_personality(void) {
e8132d63 592 unsigned long current;
78e864e5
TM
593 pid_t pid;
594
595 if (!is_seccomp_available())
596 return;
597 if (geteuid() != 0)
598 return;
599
e8132d63
LP
600 assert_se(opinionated_personality(&current) >= 0);
601
602 log_info("current personality=%lu", current);
603
78e864e5
TM
604 pid = fork();
605 assert_se(pid >= 0);
606
607 if (pid == 0) {
e8132d63 608 assert_se(seccomp_lock_personality(current) >= 0);
78e864e5 609
21022b9d 610 assert_se((unsigned long) safe_personality(current) == current);
e8132d63 611
21022b9d
LP
612 /* Note, we also test that safe_personality() works correctly, by checkig whether errno is properly
613 * set, in addition to the return value */
614 errno = 0;
615 assert_se(safe_personality(PER_LINUX | ADDR_NO_RANDOMIZE) == -EPERM);
616 assert_se(errno == EPERM);
e8132d63 617
21022b9d
LP
618 assert_se(safe_personality(PER_LINUX | MMAP_PAGE_ZERO) == -EPERM);
619 assert_se(safe_personality(PER_LINUX | ADDR_COMPAT_LAYOUT) == -EPERM);
620 assert_se(safe_personality(PER_LINUX | READ_IMPLIES_EXEC) == -EPERM);
621 assert_se(safe_personality(PER_LINUX_32BIT) == -EPERM);
622 assert_se(safe_personality(PER_SVR4) == -EPERM);
623 assert_se(safe_personality(PER_BSD) == -EPERM);
624 assert_se(safe_personality(current == PER_LINUX ? PER_LINUX32 : PER_LINUX) == -EPERM);
625 assert_se(safe_personality(PER_LINUX32_3GB) == -EPERM);
626 assert_se(safe_personality(PER_UW7) == -EPERM);
627 assert_se(safe_personality(0x42) == -EPERM);
628
629 assert_se(safe_personality(PERSONALITY_INVALID) == -EPERM); /* maybe remove this later */
e8132d63
LP
630
631 assert_se((unsigned long) personality(current) == current);
78e864e5
TM
632 _exit(EXIT_SUCCESS);
633 }
634
7d4904fe 635 assert_se(wait_for_terminate_and_check("lockpersonalityseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
78e864e5
TM
636}
637
25e94f8c
LP
638static void test_filter_sets_ordered(void) {
639 size_t i;
640
641 /* Ensure "@default" always remains at the beginning of the list */
642 assert_se(SYSCALL_FILTER_SET_DEFAULT == 0);
643 assert_se(streq(syscall_filter_sets[0].name, "@default"));
644
645 for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
646 const char *k, *p = NULL;
647
648 /* Make sure each group has a description */
649 assert_se(!isempty(syscall_filter_sets[0].help));
650
651 /* Make sure the groups are ordered alphabetically, except for the first entry */
652 assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0);
653
654 NULSTR_FOREACH(k, syscall_filter_sets[i].value) {
655
656 /* Ensure each syscall list is in itself ordered, but groups before names */
657 assert_se(!p ||
658 (*p == '@' && *k != '@') ||
659 (((*p == '@' && *k == '@') ||
660 (*p != '@' && *k != '@')) &&
661 strcmp(p, k) < 0));
662
663 p = k;
664 }
665 }
666}
667
f6281133
LP
668int main(int argc, char *argv[]) {
669
add00535
LP
670 log_set_max_level(LOG_DEBUG);
671
f6281133 672 test_seccomp_arch_to_string();
aa34055f 673 test_architecture_table();
f6281133
LP
674 test_syscall_filter_set_find();
675 test_filter_sets();
add00535 676 test_restrict_namespace();
469830d1
LP
677 test_protect_sysctl();
678 test_restrict_address_families();
679 test_restrict_realtime();
2a65bd94
ZJS
680 test_memory_deny_write_execute_mmap();
681 test_memory_deny_write_execute_shmat();
469830d1
LP
682 test_restrict_archs();
683 test_load_syscall_filter_set_raw();
78e864e5 684 test_lock_personality();
25e94f8c 685 test_filter_sets_ordered();
f6281133
LP
686
687 return 0;
688}