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