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