]>
Commit | Line | Data |
---|---|---|
f6281133 LP |
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 | ||
469830d1 | 20 | #include <sched.h> |
f6281133 LP |
21 | #include <stdlib.h> |
22 | #include <sys/eventfd.h> | |
469830d1 | 23 | #include <sys/mman.h> |
469830d1 | 24 | #include <sys/poll.h> |
2a65bd94 ZJS |
25 | #include <sys/shm.h> |
26 | #include <sys/types.h> | |
27 | #include <unistd.h> | |
f6281133 | 28 | |
add00535 | 29 | #include "alloc-util.h" |
f6281133 LP |
30 | #include "fd-util.h" |
31 | #include "macro.h" | |
add00535 LP |
32 | #include "missing.h" |
33 | #include "nsflags.h" | |
f6281133 | 34 | #include "process-util.h" |
add00535 | 35 | #include "raw-clone.h" |
f6281133 | 36 | #include "seccomp-util.h" |
469830d1 | 37 | #include "set.h" |
aa34055f ZJS |
38 | #include "string-util.h" |
39 | #include "util.h" | |
469830d1 | 40 | #include "virt.h" |
f6281133 | 41 | |
da1921a5 ZJS |
42 | #if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) |
43 | /* On these archs, socket() is implemented via the socketcall() syscall multiplexer, | |
44 | * and we can't restrict it hence via seccomp. */ | |
45 | # define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1 | |
46 | #else | |
47 | # define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0 | |
48 | #endif | |
49 | ||
50 | ||
f6281133 LP |
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 | ||
aa34055f ZJS |
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 | ||
f6281133 LP |
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; | |
f6281133 LP |
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 */ | |
469830d1 | 125 | r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW); |
f6281133 | 126 | else |
469830d1 | 127 | r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN)); |
f6281133 LP |
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)) | |
469830d1 | 134 | assert_se(fd < 0 && errno == EUCLEAN); |
f6281133 LP |
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 | ||
add00535 LP |
147 | static void test_restrict_namespace(void) { |
148 | _cleanup_free_ char *s = NULL; | |
add00535 | 149 | unsigned long ul; |
469830d1 | 150 | pid_t pid; |
add00535 LP |
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; | |
add00535 LP |
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 | ||
469830d1 LP |
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 | assert_se(syscall(__NR__sysctl, NULL) < 0); | |
248 | assert_se(errno == EFAULT); | |
249 | ||
250 | assert_se(seccomp_protect_sysctl() >= 0); | |
251 | ||
252 | assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0); | |
253 | assert_se(errno == EPERM); | |
254 | ||
255 | _exit(EXIT_SUCCESS); | |
256 | } | |
257 | ||
258 | assert_se(wait_for_terminate_and_warn("sysctlseccomp", pid, true) == EXIT_SUCCESS); | |
259 | } | |
260 | ||
261 | static void test_restrict_address_families(void) { | |
262 | pid_t pid; | |
263 | ||
264 | if (!is_seccomp_available()) | |
265 | return; | |
266 | if (geteuid() != 0) | |
267 | return; | |
268 | ||
269 | pid = fork(); | |
270 | assert_se(pid >= 0); | |
271 | ||
272 | if (pid == 0) { | |
273 | int fd; | |
274 | Set *s; | |
275 | ||
276 | fd = socket(AF_INET, SOCK_DGRAM, 0); | |
277 | assert_se(fd >= 0); | |
278 | safe_close(fd); | |
279 | ||
280 | fd = socket(AF_UNIX, SOCK_DGRAM, 0); | |
281 | assert_se(fd >= 0); | |
282 | safe_close(fd); | |
283 | ||
284 | fd = socket(AF_NETLINK, SOCK_DGRAM, 0); | |
285 | assert_se(fd >= 0); | |
286 | safe_close(fd); | |
287 | ||
288 | assert_se(s = set_new(NULL)); | |
289 | assert_se(set_put(s, INT_TO_PTR(AF_UNIX)) >= 0); | |
290 | ||
291 | assert_se(seccomp_restrict_address_families(s, false) >= 0); | |
292 | ||
293 | fd = socket(AF_INET, SOCK_DGRAM, 0); | |
294 | assert_se(fd >= 0); | |
295 | safe_close(fd); | |
296 | ||
ad8f1479 | 297 | fd = socket(AF_UNIX, SOCK_DGRAM, 0); |
dce0e620 | 298 | #if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN |
ad8f1479 LP |
299 | assert_se(fd >= 0); |
300 | safe_close(fd); | |
301 | #else | |
dce0e620 | 302 | assert_se(fd < 0); |
469830d1 | 303 | assert_se(errno == EAFNOSUPPORT); |
ad8f1479 | 304 | #endif |
469830d1 LP |
305 | |
306 | fd = socket(AF_NETLINK, SOCK_DGRAM, 0); | |
307 | assert_se(fd >= 0); | |
308 | safe_close(fd); | |
309 | ||
310 | set_clear(s); | |
311 | ||
312 | assert_se(set_put(s, INT_TO_PTR(AF_INET)) >= 0); | |
313 | ||
314 | assert_se(seccomp_restrict_address_families(s, true) >= 0); | |
315 | ||
316 | fd = socket(AF_INET, SOCK_DGRAM, 0); | |
317 | assert_se(fd >= 0); | |
318 | safe_close(fd); | |
319 | ||
ad8f1479 | 320 | fd = socket(AF_UNIX, SOCK_DGRAM, 0); |
dce0e620 | 321 | #if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN |
ad8f1479 LP |
322 | assert_se(fd >= 0); |
323 | safe_close(fd); | |
dce0e620 ZJS |
324 | #else |
325 | assert_se(fd < 0); | |
326 | assert_se(errno == EAFNOSUPPORT); | |
327 | #endif | |
ad8f1479 LP |
328 | |
329 | fd = socket(AF_NETLINK, SOCK_DGRAM, 0); | |
dce0e620 | 330 | #if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN |
ad8f1479 LP |
331 | assert_se(fd >= 0); |
332 | safe_close(fd); | |
333 | #else | |
dce0e620 | 334 | assert_se(fd < 0); |
469830d1 | 335 | assert_se(errno == EAFNOSUPPORT); |
ad8f1479 | 336 | #endif |
469830d1 LP |
337 | |
338 | _exit(EXIT_SUCCESS); | |
339 | } | |
340 | ||
341 | assert_se(wait_for_terminate_and_warn("socketseccomp", pid, true) == EXIT_SUCCESS); | |
342 | } | |
343 | ||
344 | static void test_restrict_realtime(void) { | |
345 | pid_t pid; | |
346 | ||
347 | if (!is_seccomp_available()) | |
348 | return; | |
349 | if (geteuid() != 0) | |
350 | return; | |
351 | ||
352 | if (detect_container() > 0) /* in containers RT privs are likely missing anyway */ | |
353 | return; | |
354 | ||
355 | pid = fork(); | |
356 | assert_se(pid >= 0); | |
357 | ||
358 | if (pid == 0) { | |
359 | assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) >= 0); | |
360 | assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) >= 0); | |
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(seccomp_restrict_realtime() >= 0); | |
366 | ||
367 | assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0); | |
368 | assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0); | |
369 | assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0); | |
370 | ||
371 | assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0); | |
372 | assert_se(errno == EPERM); | |
373 | assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) < 0); | |
374 | assert_se(errno == EPERM); | |
375 | ||
376 | _exit(EXIT_SUCCESS); | |
377 | } | |
378 | ||
379 | assert_se(wait_for_terminate_and_warn("realtimeseccomp", pid, true) == EXIT_SUCCESS); | |
380 | } | |
381 | ||
2a65bd94 | 382 | static void test_memory_deny_write_execute_mmap(void) { |
469830d1 LP |
383 | pid_t pid; |
384 | ||
385 | if (!is_seccomp_available()) | |
386 | return; | |
387 | if (geteuid() != 0) | |
388 | return; | |
389 | ||
390 | pid = fork(); | |
391 | assert_se(pid >= 0); | |
392 | ||
393 | if (pid == 0) { | |
394 | void *p; | |
395 | ||
396 | p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0); | |
397 | assert_se(p != MAP_FAILED); | |
398 | assert_se(munmap(p, page_size()) >= 0); | |
399 | ||
8a50cf69 LP |
400 | p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0); |
401 | assert_se(p != MAP_FAILED); | |
402 | assert_se(munmap(p, page_size()) >= 0); | |
469830d1 | 403 | |
8a50cf69 LP |
404 | assert_se(seccomp_memory_deny_write_execute() >= 0); |
405 | ||
8a50cf69 | 406 | p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0); |
4278d1f5 | 407 | #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc64__) || defined(__arm__) || defined(__aarch64__) |
469830d1 LP |
408 | assert_se(p == MAP_FAILED); |
409 | assert_se(errno == EPERM); | |
2a65bd94 ZJS |
410 | #else /* unknown architectures */ |
411 | assert_se(p != MAP_FAILED); | |
412 | assert_se(munmap(p, page_size()) >= 0); | |
8a50cf69 | 413 | #endif |
469830d1 LP |
414 | |
415 | p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0); | |
416 | assert_se(p != MAP_FAILED); | |
417 | assert_se(munmap(p, page_size()) >= 0); | |
418 | ||
419 | _exit(EXIT_SUCCESS); | |
420 | } | |
421 | ||
2a65bd94 ZJS |
422 | assert_se(wait_for_terminate_and_warn("memoryseccomp-mmap", pid, true) == EXIT_SUCCESS); |
423 | } | |
424 | ||
425 | static void test_memory_deny_write_execute_shmat(void) { | |
426 | int shmid; | |
427 | pid_t pid; | |
428 | ||
429 | if (!is_seccomp_available()) | |
430 | return; | |
431 | if (geteuid() != 0) | |
432 | return; | |
433 | ||
434 | shmid = shmget(IPC_PRIVATE, page_size(), 0); | |
435 | assert_se(shmid >= 0); | |
436 | ||
437 | pid = fork(); | |
438 | assert_se(pid >= 0); | |
439 | ||
440 | if (pid == 0) { | |
441 | void *p; | |
442 | ||
443 | p = shmat(shmid, NULL, 0); | |
444 | assert_se(p != MAP_FAILED); | |
445 | assert_se(shmdt(p) == 0); | |
446 | ||
447 | p = shmat(shmid, NULL, SHM_EXEC); | |
448 | assert_se(p != MAP_FAILED); | |
449 | assert_se(shmdt(p) == 0); | |
450 | ||
451 | assert_se(seccomp_memory_deny_write_execute() >= 0); | |
452 | ||
453 | p = shmat(shmid, NULL, SHM_EXEC); | |
4278d1f5 | 454 | #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) |
2a65bd94 ZJS |
455 | assert_se(p == MAP_FAILED); |
456 | assert_se(errno == EPERM); | |
2a8d6e63 | 457 | #else /* __i386__, __powerpc64__, and "unknown" architectures */ |
2a65bd94 ZJS |
458 | assert_se(p != MAP_FAILED); |
459 | assert_se(shmdt(p) == 0); | |
460 | #endif | |
461 | ||
462 | p = shmat(shmid, NULL, 0); | |
463 | assert_se(p != MAP_FAILED); | |
464 | assert_se(shmdt(p) == 0); | |
465 | ||
466 | _exit(EXIT_SUCCESS); | |
467 | } | |
468 | ||
469 | assert_se(wait_for_terminate_and_warn("memoryseccomp-shmat", pid, true) == EXIT_SUCCESS); | |
469830d1 LP |
470 | } |
471 | ||
472 | static void test_restrict_archs(void) { | |
473 | pid_t pid; | |
474 | ||
475 | if (!is_seccomp_available()) | |
476 | return; | |
477 | if (geteuid() != 0) | |
478 | return; | |
479 | ||
480 | pid = fork(); | |
481 | assert_se(pid >= 0); | |
482 | ||
483 | if (pid == 0) { | |
484 | _cleanup_set_free_ Set *s = NULL; | |
485 | ||
486 | assert_se(access("/", F_OK) >= 0); | |
487 | ||
488 | assert_se(s = set_new(NULL)); | |
489 | ||
490 | #ifdef __x86_64__ | |
491 | assert_se(set_put(s, UINT32_TO_PTR(SCMP_ARCH_X86+1)) >= 0); | |
492 | #endif | |
493 | assert_se(seccomp_restrict_archs(s) >= 0); | |
494 | ||
495 | assert_se(access("/", F_OK) >= 0); | |
496 | assert_se(seccomp_restrict_archs(NULL) >= 0); | |
497 | ||
498 | assert_se(access("/", F_OK) >= 0); | |
499 | ||
500 | _exit(EXIT_SUCCESS); | |
501 | } | |
502 | ||
503 | assert_se(wait_for_terminate_and_warn("archseccomp", pid, true) == EXIT_SUCCESS); | |
504 | } | |
505 | ||
506 | static void test_load_syscall_filter_set_raw(void) { | |
507 | pid_t pid; | |
508 | ||
509 | if (!is_seccomp_available()) | |
510 | return; | |
511 | if (geteuid() != 0) | |
512 | return; | |
513 | ||
514 | pid = fork(); | |
515 | assert_se(pid >= 0); | |
516 | ||
517 | if (pid == 0) { | |
518 | _cleanup_set_free_ Set *s = NULL; | |
519 | ||
520 | assert_se(access("/", F_OK) >= 0); | |
521 | assert_se(poll(NULL, 0, 0) == 0); | |
522 | ||
523 | assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL) >= 0); | |
524 | assert_se(access("/", F_OK) >= 0); | |
525 | assert_se(poll(NULL, 0, 0) == 0); | |
526 | ||
527 | assert_se(s = set_new(NULL)); | |
528 | assert_se(set_put(s, UINT32_TO_PTR(__NR_access + 1)) >= 0); | |
529 | ||
530 | assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0); | |
531 | ||
532 | assert_se(access("/", F_OK) < 0); | |
533 | assert_se(errno == EUCLEAN); | |
534 | ||
535 | assert_se(poll(NULL, 0, 0) == 0); | |
536 | ||
537 | s = set_free(s); | |
538 | ||
539 | assert_se(s = set_new(NULL)); | |
540 | assert_se(set_put(s, UINT32_TO_PTR(__NR_poll + 1)) >= 0); | |
541 | ||
542 | assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0); | |
543 | ||
544 | assert_se(access("/", F_OK) < 0); | |
545 | assert_se(errno == EUCLEAN); | |
546 | ||
547 | assert_se(poll(NULL, 0, 0) < 0); | |
548 | assert_se(errno == EUNATCH); | |
549 | ||
550 | _exit(EXIT_SUCCESS); | |
551 | } | |
552 | ||
553 | assert_se(wait_for_terminate_and_warn("syscallrawseccomp", pid, true) == EXIT_SUCCESS); | |
554 | } | |
555 | ||
f6281133 LP |
556 | int main(int argc, char *argv[]) { |
557 | ||
add00535 LP |
558 | log_set_max_level(LOG_DEBUG); |
559 | ||
f6281133 | 560 | test_seccomp_arch_to_string(); |
aa34055f | 561 | test_architecture_table(); |
f6281133 LP |
562 | test_syscall_filter_set_find(); |
563 | test_filter_sets(); | |
add00535 | 564 | test_restrict_namespace(); |
469830d1 LP |
565 | test_protect_sysctl(); |
566 | test_restrict_address_families(); | |
567 | test_restrict_realtime(); | |
2a65bd94 ZJS |
568 | test_memory_deny_write_execute_mmap(); |
569 | test_memory_deny_write_execute_shmat(); | |
469830d1 LP |
570 | test_restrict_archs(); |
571 | test_load_syscall_filter_set_raw(); | |
f6281133 LP |
572 | |
573 | return 0; | |
574 | } |