blob: d4c8858fde8e77300d9c113bb0e0d50f8c7f744c [file] [log] [blame]
Thomas Gleixnere500db32019-06-04 10:11:14 +02001// SPDX-License-Identifier: GPL-2.0-only
Kees Cookc99ee512015-06-16 10:54:14 -07002/*
3 * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Kees Cookc99ee512015-06-16 10:54:14 -07004 *
5 * Test code for seccomp bpf.
6 */
7
Tycho Andersen6a21cc52018-12-09 11:24:13 -07008#define _GNU_SOURCE
Matt Redfearn0ce105b2016-03-29 09:35:29 +01009#include <sys/types.h>
Kees Cook10859f32017-09-07 16:32:46 -070010
11/*
12 * glibc 2.26 and later have SIGSYS in siginfo_t. Before that,
13 * we need to use the kernel's siginfo.h file and trick glibc
14 * into accepting it.
15 */
16#if !__GLIBC_PREREQ(2, 26)
17# include <asm/siginfo.h>
18# define __have_siginfo_t 1
19# define __have_sigval_t 1
20# define __have_sigevent_t 1
21#endif
Kees Cookc99ee512015-06-16 10:54:14 -070022
23#include <errno.h>
24#include <linux/filter.h>
25#include <sys/prctl.h>
26#include <sys/ptrace.h>
27#include <sys/user.h>
28#include <linux/prctl.h>
29#include <linux/ptrace.h>
30#include <linux/seccomp.h>
Kees Cookc99ee512015-06-16 10:54:14 -070031#include <pthread.h>
32#include <semaphore.h>
33#include <signal.h>
34#include <stddef.h>
35#include <stdbool.h>
36#include <string.h>
Kees Cook256d0af2015-10-06 12:30:25 -070037#include <time.h>
Christian Brauner223e6602019-09-20 10:30:06 +020038#include <limits.h>
Kees Cookc99ee512015-06-16 10:54:14 -070039#include <linux/elf.h>
40#include <sys/uio.h>
Kees Cook256d0af2015-10-06 12:30:25 -070041#include <sys/utsname.h>
Robert Sesekfd88d162015-11-02 15:28:49 -050042#include <sys/fcntl.h>
43#include <sys/mman.h>
44#include <sys/times.h>
Tycho Andersen6a21cc52018-12-09 11:24:13 -070045#include <sys/socket.h>
46#include <sys/ioctl.h>
Christian Brauner0eebfed2019-09-20 10:30:07 +020047#include <linux/kcmp.h>
Kees Cookc99ee512015-06-16 10:54:14 -070048
Kees Cookc99ee512015-06-16 10:54:14 -070049#include <unistd.h>
50#include <sys/syscall.h>
Tycho Andersen6a21cc52018-12-09 11:24:13 -070051#include <poll.h>
Kees Cookc99ee512015-06-16 10:54:14 -070052
Mickaël Salaün0b408082017-05-26 20:43:56 +020053#include "../kselftest_harness.h"
Kees Cookc99ee512015-06-16 10:54:14 -070054
Kees Cook8b1bc882020-07-10 09:24:36 -070055/* Attempt to de-conflict with the selftests tree. */
56#ifndef SKIP
57#define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__)
58#endif
59
Kees Cookc99ee512015-06-16 10:54:14 -070060#ifndef PR_SET_PTRACER
61# define PR_SET_PTRACER 0x59616d61
62#endif
63
64#ifndef PR_SET_NO_NEW_PRIVS
65#define PR_SET_NO_NEW_PRIVS 38
66#define PR_GET_NO_NEW_PRIVS 39
67#endif
68
69#ifndef PR_SECCOMP_EXT
70#define PR_SECCOMP_EXT 43
71#endif
72
73#ifndef SECCOMP_EXT_ACT
74#define SECCOMP_EXT_ACT 1
75#endif
76
77#ifndef SECCOMP_EXT_ACT_TSYNC
78#define SECCOMP_EXT_ACT_TSYNC 1
79#endif
80
81#ifndef SECCOMP_MODE_STRICT
82#define SECCOMP_MODE_STRICT 1
83#endif
84
85#ifndef SECCOMP_MODE_FILTER
86#define SECCOMP_MODE_FILTER 2
87#endif
88
Kees Cookf3e18212017-08-11 13:20:33 -070089#ifndef SECCOMP_RET_ALLOW
Kees Cookc99ee512015-06-16 10:54:14 -070090struct seccomp_data {
91 int nr;
92 __u32 arch;
93 __u64 instruction_pointer;
94 __u64 args[6];
95};
96#endif
97
Kees Cookf3e18212017-08-11 13:20:33 -070098#ifndef SECCOMP_RET_KILL_PROCESS
99#define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */
Kees Cookfd768752017-08-11 12:53:18 -0700100#define SECCOMP_RET_KILL_THREAD 0x00000000U /* kill the thread */
101#endif
Kees Cookc99ee512015-06-16 10:54:14 -0700102#ifndef SECCOMP_RET_KILL
Kees Cookfd768752017-08-11 12:53:18 -0700103#define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD
104#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
105#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
106#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
107#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
Tyler Hicks59f5cf42017-08-11 04:33:57 +0000108#endif
109#ifndef SECCOMP_RET_LOG
Kees Cookfd768752017-08-11 12:53:18 -0700110#define SECCOMP_RET_LOG 0x7ffc0000U /* allow after logging */
Tyler Hicks59f5cf42017-08-11 04:33:57 +0000111#endif
Kees Cookc99ee512015-06-16 10:54:14 -0700112
Kees Cookf3e18212017-08-11 13:20:33 -0700113#ifndef __NR_seccomp
114# if defined(__i386__)
115# define __NR_seccomp 354
116# elif defined(__x86_64__)
117# define __NR_seccomp 317
118# elif defined(__arm__)
119# define __NR_seccomp 383
120# elif defined(__aarch64__)
121# define __NR_seccomp 277
David Abdurachmanov53406272019-10-04 17:12:22 -0700122# elif defined(__riscv)
123# define __NR_seccomp 277
Kees Cookf3e18212017-08-11 13:20:33 -0700124# elif defined(__hppa__)
125# define __NR_seccomp 338
126# elif defined(__powerpc__)
127# define __NR_seccomp 358
128# elif defined(__s390__)
129# define __NR_seccomp 348
130# else
131# warning "seccomp syscall number unknown for this architecture"
132# define __NR_seccomp 0xffff
133# endif
134#endif
Kees Cookc99ee512015-06-16 10:54:14 -0700135
Kees Cookf3e18212017-08-11 13:20:33 -0700136#ifndef SECCOMP_SET_MODE_STRICT
137#define SECCOMP_SET_MODE_STRICT 0
138#endif
139
140#ifndef SECCOMP_SET_MODE_FILTER
141#define SECCOMP_SET_MODE_FILTER 1
142#endif
143
144#ifndef SECCOMP_GET_ACTION_AVAIL
145#define SECCOMP_GET_ACTION_AVAIL 2
146#endif
147
Tycho Andersen6a21cc52018-12-09 11:24:13 -0700148#ifndef SECCOMP_GET_NOTIF_SIZES
149#define SECCOMP_GET_NOTIF_SIZES 3
150#endif
151
Kees Cookf3e18212017-08-11 13:20:33 -0700152#ifndef SECCOMP_FILTER_FLAG_TSYNC
Kees Cook00a02d02018-05-03 14:56:12 -0700153#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
Kees Cookf3e18212017-08-11 13:20:33 -0700154#endif
155
156#ifndef SECCOMP_FILTER_FLAG_LOG
Kees Cook00a02d02018-05-03 14:56:12 -0700157#define SECCOMP_FILTER_FLAG_LOG (1UL << 1)
158#endif
159
160#ifndef SECCOMP_FILTER_FLAG_SPEC_ALLOW
161#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
Kees Cookf3e18212017-08-11 13:20:33 -0700162#endif
163
Tycho Andersend057dc42018-02-20 19:47:47 -0700164#ifndef PTRACE_SECCOMP_GET_METADATA
165#define PTRACE_SECCOMP_GET_METADATA 0x420d
166
167struct seccomp_metadata {
168 __u64 filter_off; /* Input: which filter */
169 __u64 flags; /* Output: filter's flags */
170};
171#endif
172
Tycho Andersen6a21cc52018-12-09 11:24:13 -0700173#ifndef SECCOMP_FILTER_FLAG_NEW_LISTENER
174#define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3)
175
176#define SECCOMP_RET_USER_NOTIF 0x7fc00000U
177
178#define SECCOMP_IOC_MAGIC '!'
179#define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr)
180#define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type)
181#define SECCOMP_IOW(nr, type) _IOW(SECCOMP_IOC_MAGIC, nr, type)
182#define SECCOMP_IOWR(nr, type) _IOWR(SECCOMP_IOC_MAGIC, nr, type)
183
184/* Flags for seccomp notification fd ioctl. */
185#define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif)
186#define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, \
187 struct seccomp_notif_resp)
188#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOR(2, __u64)
189
190struct seccomp_notif {
191 __u64 id;
192 __u32 pid;
193 __u32 flags;
194 struct seccomp_data data;
195};
196
197struct seccomp_notif_resp {
198 __u64 id;
199 __s64 val;
200 __s32 error;
201 __u32 flags;
202};
203
204struct seccomp_notif_sizes {
205 __u16 seccomp_notif;
206 __u16 seccomp_notif_resp;
207 __u16 seccomp_data;
208};
209#endif
210
Tycho Andersen88282292019-08-26 08:43:02 -0600211#ifndef PTRACE_EVENTMSG_SYSCALL_ENTRY
212#define PTRACE_EVENTMSG_SYSCALL_ENTRY 1
213#define PTRACE_EVENTMSG_SYSCALL_EXIT 2
214#endif
215
Christian Brauner2aa8d8d2019-10-21 11:10:55 +0200216#ifndef SECCOMP_USER_NOTIF_FLAG_CONTINUE
217#define SECCOMP_USER_NOTIF_FLAG_CONTINUE 0x00000001
218#endif
219
Tycho Andersen51891492020-03-04 11:05:17 -0700220#ifndef SECCOMP_FILTER_FLAG_TSYNC_ESRCH
221#define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4)
222#endif
223
Kees Cookf3e18212017-08-11 13:20:33 -0700224#ifndef seccomp
225int seccomp(unsigned int op, unsigned int flags, void *args)
226{
227 errno = 0;
228 return syscall(__NR_seccomp, op, flags, args);
229}
Kees Cookc99ee512015-06-16 10:54:14 -0700230#endif
231
Michael Ellermanc385d0d2015-07-23 20:21:10 +1000232#if __BYTE_ORDER == __LITTLE_ENDIAN
Kees Cookc99ee512015-06-16 10:54:14 -0700233#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
Michael Ellermanc385d0d2015-07-23 20:21:10 +1000234#elif __BYTE_ORDER == __BIG_ENDIAN
235#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]) + sizeof(__u32))
236#else
237#error "wut? Unknown __BYTE_ORDER?!"
238#endif
Kees Cookc99ee512015-06-16 10:54:14 -0700239
240#define SIBLING_EXIT_UNKILLED 0xbadbeef
241#define SIBLING_EXIT_FAILURE 0xbadface
242#define SIBLING_EXIT_NEWPRIVS 0xbadfeed
243
244TEST(mode_strict_support)
245{
246 long ret;
247
248 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, NULL, NULL);
249 ASSERT_EQ(0, ret) {
250 TH_LOG("Kernel does not support CONFIG_SECCOMP");
251 }
Mickaël Salaün369130b2017-08-07 01:23:37 +0200252 syscall(__NR_exit, 0);
Kees Cookc99ee512015-06-16 10:54:14 -0700253}
254
255TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL)
256{
257 long ret;
258
259 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, NULL, NULL);
260 ASSERT_EQ(0, ret) {
261 TH_LOG("Kernel does not support CONFIG_SECCOMP");
262 }
263 syscall(__NR_prctl, PR_SET_SECCOMP, SECCOMP_MODE_FILTER,
264 NULL, NULL, NULL);
265 EXPECT_FALSE(true) {
266 TH_LOG("Unreachable!");
267 }
268}
269
270/* Note! This doesn't test no new privs behavior */
271TEST(no_new_privs_support)
272{
273 long ret;
274
275 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
276 EXPECT_EQ(0, ret) {
277 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
278 }
279}
280
Kees Cookf3f6e302017-08-02 14:08:39 -0700281/* Tests kernel support by checking for a copy_from_user() fault on NULL. */
Kees Cookc99ee512015-06-16 10:54:14 -0700282TEST(mode_filter_support)
283{
284 long ret;
285
286 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
287 ASSERT_EQ(0, ret) {
288 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
289 }
290 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, NULL, NULL);
291 EXPECT_EQ(-1, ret);
292 EXPECT_EQ(EFAULT, errno) {
293 TH_LOG("Kernel does not support CONFIG_SECCOMP_FILTER!");
294 }
295}
296
297TEST(mode_filter_without_nnp)
298{
299 struct sock_filter filter[] = {
300 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
301 };
302 struct sock_fprog prog = {
303 .len = (unsigned short)ARRAY_SIZE(filter),
304 .filter = filter,
305 };
306 long ret;
307
308 ret = prctl(PR_GET_NO_NEW_PRIVS, 0, NULL, 0, 0);
309 ASSERT_LE(0, ret) {
310 TH_LOG("Expected 0 or unsupported for NO_NEW_PRIVS");
311 }
312 errno = 0;
313 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
314 /* Succeeds with CAP_SYS_ADMIN, fails without */
315 /* TODO(wad) check caps not euid */
316 if (geteuid()) {
317 EXPECT_EQ(-1, ret);
318 EXPECT_EQ(EACCES, errno);
319 } else {
320 EXPECT_EQ(0, ret);
321 }
322}
323
324#define MAX_INSNS_PER_PATH 32768
325
326TEST(filter_size_limits)
327{
328 int i;
329 int count = BPF_MAXINSNS + 1;
330 struct sock_filter allow[] = {
331 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
332 };
333 struct sock_filter *filter;
334 struct sock_fprog prog = { };
335 long ret;
336
337 filter = calloc(count, sizeof(*filter));
338 ASSERT_NE(NULL, filter);
339
340 for (i = 0; i < count; i++)
341 filter[i] = allow[0];
342
343 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
344 ASSERT_EQ(0, ret);
345
346 prog.filter = filter;
347 prog.len = count;
348
349 /* Too many filter instructions in a single filter. */
350 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
351 ASSERT_NE(0, ret) {
352 TH_LOG("Installing %d insn filter was allowed", prog.len);
353 }
354
355 /* One less is okay, though. */
356 prog.len -= 1;
357 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
358 ASSERT_EQ(0, ret) {
359 TH_LOG("Installing %d insn filter wasn't allowed", prog.len);
360 }
361}
362
363TEST(filter_chain_limits)
364{
365 int i;
366 int count = BPF_MAXINSNS;
367 struct sock_filter allow[] = {
368 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
369 };
370 struct sock_filter *filter;
371 struct sock_fprog prog = { };
372 long ret;
373
374 filter = calloc(count, sizeof(*filter));
375 ASSERT_NE(NULL, filter);
376
377 for (i = 0; i < count; i++)
378 filter[i] = allow[0];
379
380 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
381 ASSERT_EQ(0, ret);
382
383 prog.filter = filter;
384 prog.len = 1;
385
386 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
387 ASSERT_EQ(0, ret);
388
389 prog.len = count;
390
391 /* Too many total filter instructions. */
392 for (i = 0; i < MAX_INSNS_PER_PATH; i++) {
393 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
394 if (ret != 0)
395 break;
396 }
397 ASSERT_NE(0, ret) {
398 TH_LOG("Allowed %d %d-insn filters (total with penalties:%d)",
399 i, count, i * (count + 4));
400 }
401}
402
403TEST(mode_filter_cannot_move_to_strict)
404{
405 struct sock_filter filter[] = {
406 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
407 };
408 struct sock_fprog prog = {
409 .len = (unsigned short)ARRAY_SIZE(filter),
410 .filter = filter,
411 };
412 long ret;
413
414 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
415 ASSERT_EQ(0, ret);
416
417 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
418 ASSERT_EQ(0, ret);
419
420 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, 0, 0);
421 EXPECT_EQ(-1, ret);
422 EXPECT_EQ(EINVAL, errno);
423}
424
425
426TEST(mode_filter_get_seccomp)
427{
428 struct sock_filter filter[] = {
429 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
430 };
431 struct sock_fprog prog = {
432 .len = (unsigned short)ARRAY_SIZE(filter),
433 .filter = filter,
434 };
435 long ret;
436
437 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
438 ASSERT_EQ(0, ret);
439
440 ret = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
441 EXPECT_EQ(0, ret);
442
443 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
444 ASSERT_EQ(0, ret);
445
446 ret = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
447 EXPECT_EQ(2, ret);
448}
449
450
451TEST(ALLOW_all)
452{
453 struct sock_filter filter[] = {
454 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
455 };
456 struct sock_fprog prog = {
457 .len = (unsigned short)ARRAY_SIZE(filter),
458 .filter = filter,
459 };
460 long ret;
461
462 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
463 ASSERT_EQ(0, ret);
464
465 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
466 ASSERT_EQ(0, ret);
467}
468
469TEST(empty_prog)
470{
471 struct sock_filter filter[] = {
472 };
473 struct sock_fprog prog = {
474 .len = (unsigned short)ARRAY_SIZE(filter),
475 .filter = filter,
476 };
477 long ret;
478
479 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
480 ASSERT_EQ(0, ret);
481
482 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
483 EXPECT_EQ(-1, ret);
484 EXPECT_EQ(EINVAL, errno);
485}
486
Tyler Hicks59f5cf42017-08-11 04:33:57 +0000487TEST(log_all)
488{
489 struct sock_filter filter[] = {
490 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
491 };
492 struct sock_fprog prog = {
493 .len = (unsigned short)ARRAY_SIZE(filter),
494 .filter = filter,
495 };
496 long ret;
497 pid_t parent = getppid();
498
499 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
500 ASSERT_EQ(0, ret);
501
502 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
503 ASSERT_EQ(0, ret);
504
505 /* getppid() should succeed and be logged (no check for logging) */
506 EXPECT_EQ(parent, syscall(__NR_getppid));
507}
508
Kees Cookc99ee512015-06-16 10:54:14 -0700509TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS)
510{
511 struct sock_filter filter[] = {
512 BPF_STMT(BPF_RET|BPF_K, 0x10000000U),
513 };
514 struct sock_fprog prog = {
515 .len = (unsigned short)ARRAY_SIZE(filter),
516 .filter = filter,
517 };
518 long ret;
519
520 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
521 ASSERT_EQ(0, ret);
522
523 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
524 ASSERT_EQ(0, ret);
525 EXPECT_EQ(0, syscall(__NR_getpid)) {
526 TH_LOG("getpid() shouldn't ever return");
527 }
528}
529
530/* return code >= 0x80000000 is unused. */
531TEST_SIGNAL(unknown_ret_is_kill_above_allow, SIGSYS)
532{
533 struct sock_filter filter[] = {
534 BPF_STMT(BPF_RET|BPF_K, 0x90000000U),
535 };
536 struct sock_fprog prog = {
537 .len = (unsigned short)ARRAY_SIZE(filter),
538 .filter = filter,
539 };
540 long ret;
541
542 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
543 ASSERT_EQ(0, ret);
544
545 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
546 ASSERT_EQ(0, ret);
547 EXPECT_EQ(0, syscall(__NR_getpid)) {
548 TH_LOG("getpid() shouldn't ever return");
549 }
550}
551
552TEST_SIGNAL(KILL_all, SIGSYS)
553{
554 struct sock_filter filter[] = {
555 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
556 };
557 struct sock_fprog prog = {
558 .len = (unsigned short)ARRAY_SIZE(filter),
559 .filter = filter,
560 };
561 long ret;
562
563 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
564 ASSERT_EQ(0, ret);
565
566 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
567 ASSERT_EQ(0, ret);
568}
569
570TEST_SIGNAL(KILL_one, SIGSYS)
571{
572 struct sock_filter filter[] = {
573 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
574 offsetof(struct seccomp_data, nr)),
575 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
576 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
577 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
578 };
579 struct sock_fprog prog = {
580 .len = (unsigned short)ARRAY_SIZE(filter),
581 .filter = filter,
582 };
583 long ret;
584 pid_t parent = getppid();
585
586 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
587 ASSERT_EQ(0, ret);
588
589 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
590 ASSERT_EQ(0, ret);
591
592 EXPECT_EQ(parent, syscall(__NR_getppid));
593 /* getpid() should never return. */
594 EXPECT_EQ(0, syscall(__NR_getpid));
595}
596
597TEST_SIGNAL(KILL_one_arg_one, SIGSYS)
598{
Robert Sesekfd88d162015-11-02 15:28:49 -0500599 void *fatal_address;
Kees Cookc99ee512015-06-16 10:54:14 -0700600 struct sock_filter filter[] = {
601 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
602 offsetof(struct seccomp_data, nr)),
Robert Sesekfd88d162015-11-02 15:28:49 -0500603 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_times, 1, 0),
Kees Cookc99ee512015-06-16 10:54:14 -0700604 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
605 /* Only both with lower 32-bit for now. */
606 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(0)),
Robert Sesekfd88d162015-11-02 15:28:49 -0500607 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K,
608 (unsigned long)&fatal_address, 0, 1),
Kees Cookc99ee512015-06-16 10:54:14 -0700609 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
610 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
611 };
612 struct sock_fprog prog = {
613 .len = (unsigned short)ARRAY_SIZE(filter),
614 .filter = filter,
615 };
616 long ret;
617 pid_t parent = getppid();
Robert Sesekfd88d162015-11-02 15:28:49 -0500618 struct tms timebuf;
619 clock_t clock = times(&timebuf);
Kees Cookc99ee512015-06-16 10:54:14 -0700620
621 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
622 ASSERT_EQ(0, ret);
623
624 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
625 ASSERT_EQ(0, ret);
626
627 EXPECT_EQ(parent, syscall(__NR_getppid));
Robert Sesekfd88d162015-11-02 15:28:49 -0500628 EXPECT_LE(clock, syscall(__NR_times, &timebuf));
629 /* times() should never return. */
630 EXPECT_EQ(0, syscall(__NR_times, &fatal_address));
Kees Cookc99ee512015-06-16 10:54:14 -0700631}
632
633TEST_SIGNAL(KILL_one_arg_six, SIGSYS)
634{
Robert Sesekfd88d162015-11-02 15:28:49 -0500635#ifndef __NR_mmap2
636 int sysno = __NR_mmap;
637#else
638 int sysno = __NR_mmap2;
639#endif
Kees Cookc99ee512015-06-16 10:54:14 -0700640 struct sock_filter filter[] = {
641 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
642 offsetof(struct seccomp_data, nr)),
Robert Sesekfd88d162015-11-02 15:28:49 -0500643 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, sysno, 1, 0),
Kees Cookc99ee512015-06-16 10:54:14 -0700644 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
645 /* Only both with lower 32-bit for now. */
646 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(5)),
647 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0C0FFEE, 0, 1),
648 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
649 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
650 };
651 struct sock_fprog prog = {
652 .len = (unsigned short)ARRAY_SIZE(filter),
653 .filter = filter,
654 };
655 long ret;
656 pid_t parent = getppid();
Robert Sesekfd88d162015-11-02 15:28:49 -0500657 int fd;
658 void *map1, *map2;
Bamvor Jian Zhang2ce47b42015-11-13 11:17:51 +0800659 int page_size = sysconf(_SC_PAGESIZE);
660
661 ASSERT_LT(0, page_size);
Kees Cookc99ee512015-06-16 10:54:14 -0700662
663 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
664 ASSERT_EQ(0, ret);
665
666 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
667 ASSERT_EQ(0, ret);
668
Robert Sesekfd88d162015-11-02 15:28:49 -0500669 fd = open("/dev/zero", O_RDONLY);
670 ASSERT_NE(-1, fd);
671
Kees Cookc99ee512015-06-16 10:54:14 -0700672 EXPECT_EQ(parent, syscall(__NR_getppid));
Robert Sesekfd88d162015-11-02 15:28:49 -0500673 map1 = (void *)syscall(sysno,
Bamvor Jian Zhang2ce47b42015-11-13 11:17:51 +0800674 NULL, page_size, PROT_READ, MAP_PRIVATE, fd, page_size);
Robert Sesekfd88d162015-11-02 15:28:49 -0500675 EXPECT_NE(MAP_FAILED, map1);
676 /* mmap2() should never return. */
677 map2 = (void *)syscall(sysno,
Bamvor Jian Zhang2ce47b42015-11-13 11:17:51 +0800678 NULL, page_size, PROT_READ, MAP_PRIVATE, fd, 0x0C0FFEE);
Robert Sesekfd88d162015-11-02 15:28:49 -0500679 EXPECT_EQ(MAP_FAILED, map2);
680
681 /* The test failed, so clean up the resources. */
Bamvor Jian Zhang2ce47b42015-11-13 11:17:51 +0800682 munmap(map1, page_size);
683 munmap(map2, page_size);
Robert Sesekfd88d162015-11-02 15:28:49 -0500684 close(fd);
Kees Cookc99ee512015-06-16 10:54:14 -0700685}
686
Kees Cookf3e18212017-08-11 13:20:33 -0700687/* This is a thread task to die via seccomp filter violation. */
688void *kill_thread(void *data)
689{
690 bool die = (bool)data;
691
692 if (die) {
693 prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
694 return (void *)SIBLING_EXIT_FAILURE;
695 }
696
697 return (void *)SIBLING_EXIT_UNKILLED;
698}
699
700/* Prepare a thread that will kill itself or both of us. */
701void kill_thread_or_group(struct __test_metadata *_metadata, bool kill_process)
702{
703 pthread_t thread;
704 void *status;
705 /* Kill only when calling __NR_prctl. */
706 struct sock_filter filter_thread[] = {
707 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
708 offsetof(struct seccomp_data, nr)),
709 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
710 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
711 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
712 };
713 struct sock_fprog prog_thread = {
714 .len = (unsigned short)ARRAY_SIZE(filter_thread),
715 .filter = filter_thread,
716 };
717 struct sock_filter filter_process[] = {
718 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
719 offsetof(struct seccomp_data, nr)),
720 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
721 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_PROCESS),
722 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
723 };
724 struct sock_fprog prog_process = {
725 .len = (unsigned short)ARRAY_SIZE(filter_process),
726 .filter = filter_process,
727 };
728
729 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
730 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
731 }
732
733 ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0,
734 kill_process ? &prog_process : &prog_thread));
735
736 /*
737 * Add the KILL_THREAD rule again to make sure that the KILL_PROCESS
738 * flag cannot be downgraded by a new filter.
739 */
740 ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog_thread));
741
742 /* Start a thread that will exit immediately. */
743 ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)false));
744 ASSERT_EQ(0, pthread_join(thread, &status));
745 ASSERT_EQ(SIBLING_EXIT_UNKILLED, (unsigned long)status);
746
747 /* Start a thread that will die immediately. */
748 ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)true));
749 ASSERT_EQ(0, pthread_join(thread, &status));
750 ASSERT_NE(SIBLING_EXIT_FAILURE, (unsigned long)status);
751
752 /*
753 * If we get here, only the spawned thread died. Let the parent know
754 * the whole process didn't die (i.e. this thread, the spawner,
755 * stayed running).
756 */
757 exit(42);
758}
759
760TEST(KILL_thread)
761{
762 int status;
763 pid_t child_pid;
764
765 child_pid = fork();
766 ASSERT_LE(0, child_pid);
767 if (child_pid == 0) {
768 kill_thread_or_group(_metadata, false);
769 _exit(38);
770 }
771
772 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
773
774 /* If only the thread was killed, we'll see exit 42. */
775 ASSERT_TRUE(WIFEXITED(status));
776 ASSERT_EQ(42, WEXITSTATUS(status));
777}
778
779TEST(KILL_process)
780{
781 int status;
782 pid_t child_pid;
783
784 child_pid = fork();
785 ASSERT_LE(0, child_pid);
786 if (child_pid == 0) {
787 kill_thread_or_group(_metadata, true);
788 _exit(38);
789 }
790
791 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
792
793 /* If the entire process was killed, we'll see SIGSYS. */
794 ASSERT_TRUE(WIFSIGNALED(status));
795 ASSERT_EQ(SIGSYS, WTERMSIG(status));
796}
797
Kees Cookc99ee512015-06-16 10:54:14 -0700798/* TODO(wad) add 64-bit versus 32-bit arg tests. */
799TEST(arg_out_of_range)
800{
801 struct sock_filter filter[] = {
802 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(6)),
803 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
804 };
805 struct sock_fprog prog = {
806 .len = (unsigned short)ARRAY_SIZE(filter),
807 .filter = filter,
808 };
809 long ret;
810
811 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
812 ASSERT_EQ(0, ret);
813
814 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
815 EXPECT_EQ(-1, ret);
816 EXPECT_EQ(EINVAL, errno);
817}
818
Kees Cookf3f6e302017-08-02 14:08:39 -0700819#define ERRNO_FILTER(name, errno) \
820 struct sock_filter _read_filter_##name[] = { \
821 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, \
822 offsetof(struct seccomp_data, nr)), \
823 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1), \
824 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | errno), \
825 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), \
826 }; \
827 struct sock_fprog prog_##name = { \
828 .len = (unsigned short)ARRAY_SIZE(_read_filter_##name), \
829 .filter = _read_filter_##name, \
830 }
831
832/* Make sure basic errno values are correctly passed through a filter. */
Kees Cookc99ee512015-06-16 10:54:14 -0700833TEST(ERRNO_valid)
834{
Kees Cookf3f6e302017-08-02 14:08:39 -0700835 ERRNO_FILTER(valid, E2BIG);
Kees Cookc99ee512015-06-16 10:54:14 -0700836 long ret;
837 pid_t parent = getppid();
838
839 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
840 ASSERT_EQ(0, ret);
841
Kees Cookf3f6e302017-08-02 14:08:39 -0700842 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_valid);
Kees Cookc99ee512015-06-16 10:54:14 -0700843 ASSERT_EQ(0, ret);
844
845 EXPECT_EQ(parent, syscall(__NR_getppid));
846 EXPECT_EQ(-1, read(0, NULL, 0));
847 EXPECT_EQ(E2BIG, errno);
848}
849
Kees Cookf3f6e302017-08-02 14:08:39 -0700850/* Make sure an errno of zero is correctly handled by the arch code. */
Kees Cookc99ee512015-06-16 10:54:14 -0700851TEST(ERRNO_zero)
852{
Kees Cookf3f6e302017-08-02 14:08:39 -0700853 ERRNO_FILTER(zero, 0);
Kees Cookc99ee512015-06-16 10:54:14 -0700854 long ret;
855 pid_t parent = getppid();
856
857 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
858 ASSERT_EQ(0, ret);
859
Kees Cookf3f6e302017-08-02 14:08:39 -0700860 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_zero);
Kees Cookc99ee512015-06-16 10:54:14 -0700861 ASSERT_EQ(0, ret);
862
863 EXPECT_EQ(parent, syscall(__NR_getppid));
864 /* "errno" of 0 is ok. */
865 EXPECT_EQ(0, read(0, NULL, 0));
866}
867
Kees Cookf3f6e302017-08-02 14:08:39 -0700868/*
869 * The SECCOMP_RET_DATA mask is 16 bits wide, but errno is smaller.
870 * This tests that the errno value gets capped correctly, fixed by
871 * 580c57f10768 ("seccomp: cap SECCOMP_RET_ERRNO data to MAX_ERRNO").
872 */
Kees Cookc99ee512015-06-16 10:54:14 -0700873TEST(ERRNO_capped)
874{
Kees Cookf3f6e302017-08-02 14:08:39 -0700875 ERRNO_FILTER(capped, 4096);
Kees Cookc99ee512015-06-16 10:54:14 -0700876 long ret;
877 pid_t parent = getppid();
878
879 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
880 ASSERT_EQ(0, ret);
881
Kees Cookf3f6e302017-08-02 14:08:39 -0700882 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_capped);
Kees Cookc99ee512015-06-16 10:54:14 -0700883 ASSERT_EQ(0, ret);
884
885 EXPECT_EQ(parent, syscall(__NR_getppid));
886 EXPECT_EQ(-1, read(0, NULL, 0));
887 EXPECT_EQ(4095, errno);
888}
889
Kees Cookf3f6e302017-08-02 14:08:39 -0700890/*
891 * Filters are processed in reverse order: last applied is executed first.
892 * Since only the SECCOMP_RET_ACTION mask is tested for return values, the
893 * SECCOMP_RET_DATA mask results will follow the most recently applied
894 * matching filter return (and not the lowest or highest value).
895 */
896TEST(ERRNO_order)
897{
898 ERRNO_FILTER(first, 11);
899 ERRNO_FILTER(second, 13);
900 ERRNO_FILTER(third, 12);
901 long ret;
902 pid_t parent = getppid();
903
904 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
905 ASSERT_EQ(0, ret);
906
907 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_first);
908 ASSERT_EQ(0, ret);
909
910 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_second);
911 ASSERT_EQ(0, ret);
912
913 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_third);
914 ASSERT_EQ(0, ret);
915
916 EXPECT_EQ(parent, syscall(__NR_getppid));
917 EXPECT_EQ(-1, read(0, NULL, 0));
918 EXPECT_EQ(12, errno);
919}
920
Kees Cook1ae81d72020-03-11 12:21:28 -0700921FIXTURE(TRAP) {
Kees Cookc99ee512015-06-16 10:54:14 -0700922 struct sock_fprog prog;
923};
924
925FIXTURE_SETUP(TRAP)
926{
927 struct sock_filter filter[] = {
928 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
929 offsetof(struct seccomp_data, nr)),
930 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
931 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP),
932 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
933 };
934
935 memset(&self->prog, 0, sizeof(self->prog));
936 self->prog.filter = malloc(sizeof(filter));
937 ASSERT_NE(NULL, self->prog.filter);
938 memcpy(self->prog.filter, filter, sizeof(filter));
939 self->prog.len = (unsigned short)ARRAY_SIZE(filter);
940}
941
942FIXTURE_TEARDOWN(TRAP)
943{
944 if (self->prog.filter)
945 free(self->prog.filter);
946}
947
948TEST_F_SIGNAL(TRAP, dfl, SIGSYS)
949{
950 long ret;
951
952 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
953 ASSERT_EQ(0, ret);
954
955 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
956 ASSERT_EQ(0, ret);
957 syscall(__NR_getpid);
958}
959
960/* Ensure that SIGSYS overrides SIG_IGN */
961TEST_F_SIGNAL(TRAP, ign, SIGSYS)
962{
963 long ret;
964
965 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
966 ASSERT_EQ(0, ret);
967
968 signal(SIGSYS, SIG_IGN);
969
970 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
971 ASSERT_EQ(0, ret);
972 syscall(__NR_getpid);
973}
974
Kees Cook10859f32017-09-07 16:32:46 -0700975static siginfo_t TRAP_info;
Kees Cookc99ee512015-06-16 10:54:14 -0700976static volatile int TRAP_nr;
977static void TRAP_action(int nr, siginfo_t *info, void *void_context)
978{
979 memcpy(&TRAP_info, info, sizeof(TRAP_info));
980 TRAP_nr = nr;
981}
982
983TEST_F(TRAP, handler)
984{
985 int ret, test;
986 struct sigaction act;
987 sigset_t mask;
988
989 memset(&act, 0, sizeof(act));
990 sigemptyset(&mask);
991 sigaddset(&mask, SIGSYS);
992
993 act.sa_sigaction = &TRAP_action;
994 act.sa_flags = SA_SIGINFO;
995 ret = sigaction(SIGSYS, &act, NULL);
996 ASSERT_EQ(0, ret) {
997 TH_LOG("sigaction failed");
998 }
999 ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
1000 ASSERT_EQ(0, ret) {
1001 TH_LOG("sigprocmask failed");
1002 }
1003
1004 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1005 ASSERT_EQ(0, ret);
1006 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
1007 ASSERT_EQ(0, ret);
1008 TRAP_nr = 0;
1009 memset(&TRAP_info, 0, sizeof(TRAP_info));
1010 /* Expect the registers to be rolled back. (nr = error) may vary
1011 * based on arch. */
1012 ret = syscall(__NR_getpid);
1013 /* Silence gcc warning about volatile. */
1014 test = TRAP_nr;
1015 EXPECT_EQ(SIGSYS, test);
1016 struct local_sigsys {
1017 void *_call_addr; /* calling user insn */
1018 int _syscall; /* triggering system call number */
1019 unsigned int _arch; /* AUDIT_ARCH_* of syscall */
1020 } *sigsys = (struct local_sigsys *)
1021#ifdef si_syscall
1022 &(TRAP_info.si_call_addr);
1023#else
1024 &TRAP_info.si_pid;
1025#endif
1026 EXPECT_EQ(__NR_getpid, sigsys->_syscall);
1027 /* Make sure arch is non-zero. */
1028 EXPECT_NE(0, sigsys->_arch);
1029 EXPECT_NE(0, (unsigned long)sigsys->_call_addr);
1030}
1031
Kees Cook1ae81d72020-03-11 12:21:28 -07001032FIXTURE(precedence) {
Kees Cookc99ee512015-06-16 10:54:14 -07001033 struct sock_fprog allow;
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001034 struct sock_fprog log;
Kees Cookc99ee512015-06-16 10:54:14 -07001035 struct sock_fprog trace;
1036 struct sock_fprog error;
1037 struct sock_fprog trap;
1038 struct sock_fprog kill;
1039};
1040
1041FIXTURE_SETUP(precedence)
1042{
1043 struct sock_filter allow_insns[] = {
1044 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1045 };
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001046 struct sock_filter log_insns[] = {
1047 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1048 offsetof(struct seccomp_data, nr)),
1049 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
1050 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1051 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
1052 };
Kees Cookc99ee512015-06-16 10:54:14 -07001053 struct sock_filter trace_insns[] = {
1054 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1055 offsetof(struct seccomp_data, nr)),
1056 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
1057 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1058 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE),
1059 };
1060 struct sock_filter error_insns[] = {
1061 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1062 offsetof(struct seccomp_data, nr)),
1063 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
1064 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1065 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO),
1066 };
1067 struct sock_filter trap_insns[] = {
1068 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1069 offsetof(struct seccomp_data, nr)),
1070 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
1071 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1072 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP),
1073 };
1074 struct sock_filter kill_insns[] = {
1075 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1076 offsetof(struct seccomp_data, nr)),
1077 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
1078 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1079 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
1080 };
1081
1082 memset(self, 0, sizeof(*self));
1083#define FILTER_ALLOC(_x) \
1084 self->_x.filter = malloc(sizeof(_x##_insns)); \
1085 ASSERT_NE(NULL, self->_x.filter); \
1086 memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
1087 self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns)
1088 FILTER_ALLOC(allow);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001089 FILTER_ALLOC(log);
Kees Cookc99ee512015-06-16 10:54:14 -07001090 FILTER_ALLOC(trace);
1091 FILTER_ALLOC(error);
1092 FILTER_ALLOC(trap);
1093 FILTER_ALLOC(kill);
1094}
1095
1096FIXTURE_TEARDOWN(precedence)
1097{
1098#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
1099 FILTER_FREE(allow);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001100 FILTER_FREE(log);
Kees Cookc99ee512015-06-16 10:54:14 -07001101 FILTER_FREE(trace);
1102 FILTER_FREE(error);
1103 FILTER_FREE(trap);
1104 FILTER_FREE(kill);
1105}
1106
1107TEST_F(precedence, allow_ok)
1108{
1109 pid_t parent, res = 0;
1110 long ret;
1111
1112 parent = getppid();
1113 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1114 ASSERT_EQ(0, ret);
1115
1116 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1117 ASSERT_EQ(0, ret);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001118 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1119 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001120 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
1121 ASSERT_EQ(0, ret);
1122 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
1123 ASSERT_EQ(0, ret);
1124 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
1125 ASSERT_EQ(0, ret);
1126 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
1127 ASSERT_EQ(0, ret);
1128 /* Should work just fine. */
1129 res = syscall(__NR_getppid);
1130 EXPECT_EQ(parent, res);
1131}
1132
1133TEST_F_SIGNAL(precedence, kill_is_highest, SIGSYS)
1134{
1135 pid_t parent, res = 0;
1136 long ret;
1137
1138 parent = getppid();
1139 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1140 ASSERT_EQ(0, ret);
1141
1142 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1143 ASSERT_EQ(0, ret);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001144 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1145 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001146 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
1147 ASSERT_EQ(0, ret);
1148 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
1149 ASSERT_EQ(0, ret);
1150 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
1151 ASSERT_EQ(0, ret);
1152 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
1153 ASSERT_EQ(0, ret);
1154 /* Should work just fine. */
1155 res = syscall(__NR_getppid);
1156 EXPECT_EQ(parent, res);
1157 /* getpid() should never return. */
1158 res = syscall(__NR_getpid);
1159 EXPECT_EQ(0, res);
1160}
1161
1162TEST_F_SIGNAL(precedence, kill_is_highest_in_any_order, SIGSYS)
1163{
1164 pid_t parent;
1165 long ret;
1166
1167 parent = getppid();
1168 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1169 ASSERT_EQ(0, ret);
1170
1171 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1172 ASSERT_EQ(0, ret);
1173 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
1174 ASSERT_EQ(0, ret);
1175 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
1176 ASSERT_EQ(0, ret);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001177 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1178 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001179 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
1180 ASSERT_EQ(0, ret);
1181 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
1182 ASSERT_EQ(0, ret);
1183 /* Should work just fine. */
1184 EXPECT_EQ(parent, syscall(__NR_getppid));
1185 /* getpid() should never return. */
1186 EXPECT_EQ(0, syscall(__NR_getpid));
1187}
1188
1189TEST_F_SIGNAL(precedence, trap_is_second, SIGSYS)
1190{
1191 pid_t parent;
1192 long ret;
1193
1194 parent = getppid();
1195 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1196 ASSERT_EQ(0, ret);
1197
1198 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1199 ASSERT_EQ(0, ret);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001200 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1201 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001202 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
1203 ASSERT_EQ(0, ret);
1204 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
1205 ASSERT_EQ(0, ret);
1206 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
1207 ASSERT_EQ(0, ret);
1208 /* Should work just fine. */
1209 EXPECT_EQ(parent, syscall(__NR_getppid));
1210 /* getpid() should never return. */
1211 EXPECT_EQ(0, syscall(__NR_getpid));
1212}
1213
1214TEST_F_SIGNAL(precedence, trap_is_second_in_any_order, SIGSYS)
1215{
1216 pid_t parent;
1217 long ret;
1218
1219 parent = getppid();
1220 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1221 ASSERT_EQ(0, ret);
1222
1223 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1224 ASSERT_EQ(0, ret);
1225 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
1226 ASSERT_EQ(0, ret);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001227 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1228 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001229 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
1230 ASSERT_EQ(0, ret);
1231 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
1232 ASSERT_EQ(0, ret);
1233 /* Should work just fine. */
1234 EXPECT_EQ(parent, syscall(__NR_getppid));
1235 /* getpid() should never return. */
1236 EXPECT_EQ(0, syscall(__NR_getpid));
1237}
1238
1239TEST_F(precedence, errno_is_third)
1240{
1241 pid_t parent;
1242 long ret;
1243
1244 parent = getppid();
1245 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1246 ASSERT_EQ(0, ret);
1247
1248 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1249 ASSERT_EQ(0, ret);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001250 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1251 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001252 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
1253 ASSERT_EQ(0, ret);
1254 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
1255 ASSERT_EQ(0, ret);
1256 /* Should work just fine. */
1257 EXPECT_EQ(parent, syscall(__NR_getppid));
1258 EXPECT_EQ(0, syscall(__NR_getpid));
1259}
1260
1261TEST_F(precedence, errno_is_third_in_any_order)
1262{
1263 pid_t parent;
1264 long ret;
1265
1266 parent = getppid();
1267 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1268 ASSERT_EQ(0, ret);
1269
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001270 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1271 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001272 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
1273 ASSERT_EQ(0, ret);
1274 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
1275 ASSERT_EQ(0, ret);
1276 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1277 ASSERT_EQ(0, ret);
1278 /* Should work just fine. */
1279 EXPECT_EQ(parent, syscall(__NR_getppid));
1280 EXPECT_EQ(0, syscall(__NR_getpid));
1281}
1282
1283TEST_F(precedence, trace_is_fourth)
1284{
1285 pid_t parent;
1286 long ret;
1287
1288 parent = getppid();
1289 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1290 ASSERT_EQ(0, ret);
1291
1292 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1293 ASSERT_EQ(0, ret);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001294 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1295 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001296 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
1297 ASSERT_EQ(0, ret);
1298 /* Should work just fine. */
1299 EXPECT_EQ(parent, syscall(__NR_getppid));
1300 /* No ptracer */
1301 EXPECT_EQ(-1, syscall(__NR_getpid));
1302}
1303
1304TEST_F(precedence, trace_is_fourth_in_any_order)
1305{
1306 pid_t parent;
1307 long ret;
1308
1309 parent = getppid();
1310 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1311 ASSERT_EQ(0, ret);
1312
1313 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
1314 ASSERT_EQ(0, ret);
1315 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1316 ASSERT_EQ(0, ret);
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001317 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1318 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001319 /* Should work just fine. */
1320 EXPECT_EQ(parent, syscall(__NR_getppid));
1321 /* No ptracer */
1322 EXPECT_EQ(-1, syscall(__NR_getpid));
1323}
1324
Tyler Hicks59f5cf42017-08-11 04:33:57 +00001325TEST_F(precedence, log_is_fifth)
1326{
1327 pid_t mypid, parent;
1328 long ret;
1329
1330 mypid = getpid();
1331 parent = getppid();
1332 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1333 ASSERT_EQ(0, ret);
1334
1335 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1336 ASSERT_EQ(0, ret);
1337 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1338 ASSERT_EQ(0, ret);
1339 /* Should work just fine. */
1340 EXPECT_EQ(parent, syscall(__NR_getppid));
1341 /* Should also work just fine */
1342 EXPECT_EQ(mypid, syscall(__NR_getpid));
1343}
1344
1345TEST_F(precedence, log_is_fifth_in_any_order)
1346{
1347 pid_t mypid, parent;
1348 long ret;
1349
1350 mypid = getpid();
1351 parent = getppid();
1352 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1353 ASSERT_EQ(0, ret);
1354
1355 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1356 ASSERT_EQ(0, ret);
1357 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1358 ASSERT_EQ(0, ret);
1359 /* Should work just fine. */
1360 EXPECT_EQ(parent, syscall(__NR_getppid));
1361 /* Should also work just fine */
1362 EXPECT_EQ(mypid, syscall(__NR_getpid));
1363}
1364
Kees Cookc99ee512015-06-16 10:54:14 -07001365#ifndef PTRACE_O_TRACESECCOMP
1366#define PTRACE_O_TRACESECCOMP 0x00000080
1367#endif
1368
1369/* Catch the Ubuntu 12.04 value error. */
1370#if PTRACE_EVENT_SECCOMP != 7
1371#undef PTRACE_EVENT_SECCOMP
1372#endif
1373
1374#ifndef PTRACE_EVENT_SECCOMP
1375#define PTRACE_EVENT_SECCOMP 7
1376#endif
1377
1378#define IS_SECCOMP_EVENT(status) ((status >> 16) == PTRACE_EVENT_SECCOMP)
1379bool tracer_running;
1380void tracer_stop(int sig)
1381{
1382 tracer_running = false;
1383}
1384
1385typedef void tracer_func_t(struct __test_metadata *_metadata,
1386 pid_t tracee, int status, void *args);
1387
Kees Cook58d0a862016-05-26 11:47:01 -07001388void start_tracer(struct __test_metadata *_metadata, int fd, pid_t tracee,
1389 tracer_func_t tracer_func, void *args, bool ptrace_syscall)
Kees Cookc99ee512015-06-16 10:54:14 -07001390{
1391 int ret = -1;
1392 struct sigaction action = {
1393 .sa_handler = tracer_stop,
1394 };
1395
1396 /* Allow external shutdown. */
1397 tracer_running = true;
1398 ASSERT_EQ(0, sigaction(SIGUSR1, &action, NULL));
1399
1400 errno = 0;
1401 while (ret == -1 && errno != EINVAL)
1402 ret = ptrace(PTRACE_ATTACH, tracee, NULL, 0);
1403 ASSERT_EQ(0, ret) {
1404 kill(tracee, SIGKILL);
1405 }
1406 /* Wait for attach stop */
1407 wait(NULL);
1408
Kees Cook58d0a862016-05-26 11:47:01 -07001409 ret = ptrace(PTRACE_SETOPTIONS, tracee, NULL, ptrace_syscall ?
1410 PTRACE_O_TRACESYSGOOD :
1411 PTRACE_O_TRACESECCOMP);
Kees Cookc99ee512015-06-16 10:54:14 -07001412 ASSERT_EQ(0, ret) {
1413 TH_LOG("Failed to set PTRACE_O_TRACESECCOMP");
1414 kill(tracee, SIGKILL);
1415 }
Kees Cook58d0a862016-05-26 11:47:01 -07001416 ret = ptrace(ptrace_syscall ? PTRACE_SYSCALL : PTRACE_CONT,
1417 tracee, NULL, 0);
1418 ASSERT_EQ(0, ret);
Kees Cookc99ee512015-06-16 10:54:14 -07001419
1420 /* Unblock the tracee */
1421 ASSERT_EQ(1, write(fd, "A", 1));
1422 ASSERT_EQ(0, close(fd));
1423
1424 /* Run until we're shut down. Must assert to stop execution. */
1425 while (tracer_running) {
1426 int status;
1427
1428 if (wait(&status) != tracee)
1429 continue;
1430 if (WIFSIGNALED(status) || WIFEXITED(status))
1431 /* Child is dead. Time to go. */
1432 return;
1433
Kees Cook58d0a862016-05-26 11:47:01 -07001434 /* Check if this is a seccomp event. */
1435 ASSERT_EQ(!ptrace_syscall, IS_SECCOMP_EVENT(status));
Kees Cookc99ee512015-06-16 10:54:14 -07001436
1437 tracer_func(_metadata, tracee, status, args);
1438
Kees Cook58d0a862016-05-26 11:47:01 -07001439 ret = ptrace(ptrace_syscall ? PTRACE_SYSCALL : PTRACE_CONT,
1440 tracee, NULL, 0);
Kees Cookc99ee512015-06-16 10:54:14 -07001441 ASSERT_EQ(0, ret);
1442 }
1443 /* Directly report the status of our test harness results. */
1444 syscall(__NR_exit, _metadata->passed ? EXIT_SUCCESS : EXIT_FAILURE);
1445}
1446
1447/* Common tracer setup/teardown functions. */
1448void cont_handler(int num)
1449{ }
1450pid_t setup_trace_fixture(struct __test_metadata *_metadata,
Kees Cook58d0a862016-05-26 11:47:01 -07001451 tracer_func_t func, void *args, bool ptrace_syscall)
Kees Cookc99ee512015-06-16 10:54:14 -07001452{
1453 char sync;
1454 int pipefd[2];
1455 pid_t tracer_pid;
1456 pid_t tracee = getpid();
1457
1458 /* Setup a pipe for clean synchronization. */
1459 ASSERT_EQ(0, pipe(pipefd));
1460
1461 /* Fork a child which we'll promote to tracer */
1462 tracer_pid = fork();
1463 ASSERT_LE(0, tracer_pid);
1464 signal(SIGALRM, cont_handler);
1465 if (tracer_pid == 0) {
1466 close(pipefd[0]);
Kees Cook58d0a862016-05-26 11:47:01 -07001467 start_tracer(_metadata, pipefd[1], tracee, func, args,
1468 ptrace_syscall);
Kees Cookc99ee512015-06-16 10:54:14 -07001469 syscall(__NR_exit, 0);
1470 }
1471 close(pipefd[1]);
1472 prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
1473 read(pipefd[0], &sync, 1);
1474 close(pipefd[0]);
1475
1476 return tracer_pid;
1477}
1478void teardown_trace_fixture(struct __test_metadata *_metadata,
1479 pid_t tracer)
1480{
1481 if (tracer) {
1482 int status;
1483 /*
1484 * Extract the exit code from the other process and
1485 * adopt it for ourselves in case its asserts failed.
1486 */
1487 ASSERT_EQ(0, kill(tracer, SIGUSR1));
1488 ASSERT_EQ(tracer, waitpid(tracer, &status, 0));
1489 if (WEXITSTATUS(status))
1490 _metadata->passed = 0;
1491 }
1492}
1493
1494/* "poke" tracer arguments and function. */
1495struct tracer_args_poke_t {
1496 unsigned long poke_addr;
1497};
1498
1499void tracer_poke(struct __test_metadata *_metadata, pid_t tracee, int status,
1500 void *args)
1501{
1502 int ret;
1503 unsigned long msg;
1504 struct tracer_args_poke_t *info = (struct tracer_args_poke_t *)args;
1505
1506 ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
1507 EXPECT_EQ(0, ret);
1508 /* If this fails, don't try to recover. */
1509 ASSERT_EQ(0x1001, msg) {
1510 kill(tracee, SIGKILL);
1511 }
1512 /*
1513 * Poke in the message.
1514 * Registers are not touched to try to keep this relatively arch
1515 * agnostic.
1516 */
1517 ret = ptrace(PTRACE_POKEDATA, tracee, info->poke_addr, 0x1001);
1518 EXPECT_EQ(0, ret);
1519}
1520
Kees Cook1ae81d72020-03-11 12:21:28 -07001521FIXTURE(TRACE_poke) {
Kees Cookc99ee512015-06-16 10:54:14 -07001522 struct sock_fprog prog;
1523 pid_t tracer;
1524 long poked;
1525 struct tracer_args_poke_t tracer_args;
1526};
1527
1528FIXTURE_SETUP(TRACE_poke)
1529{
1530 struct sock_filter filter[] = {
1531 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1532 offsetof(struct seccomp_data, nr)),
1533 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
1534 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1001),
1535 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1536 };
1537
1538 self->poked = 0;
1539 memset(&self->prog, 0, sizeof(self->prog));
1540 self->prog.filter = malloc(sizeof(filter));
1541 ASSERT_NE(NULL, self->prog.filter);
1542 memcpy(self->prog.filter, filter, sizeof(filter));
1543 self->prog.len = (unsigned short)ARRAY_SIZE(filter);
1544
1545 /* Set up tracer args. */
1546 self->tracer_args.poke_addr = (unsigned long)&self->poked;
1547
1548 /* Launch tracer. */
1549 self->tracer = setup_trace_fixture(_metadata, tracer_poke,
Kees Cook58d0a862016-05-26 11:47:01 -07001550 &self->tracer_args, false);
Kees Cookc99ee512015-06-16 10:54:14 -07001551}
1552
1553FIXTURE_TEARDOWN(TRACE_poke)
1554{
1555 teardown_trace_fixture(_metadata, self->tracer);
1556 if (self->prog.filter)
1557 free(self->prog.filter);
1558}
1559
1560TEST_F(TRACE_poke, read_has_side_effects)
1561{
1562 ssize_t ret;
1563
1564 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1565 ASSERT_EQ(0, ret);
1566
1567 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1568 ASSERT_EQ(0, ret);
1569
1570 EXPECT_EQ(0, self->poked);
1571 ret = read(-1, NULL, 0);
1572 EXPECT_EQ(-1, ret);
1573 EXPECT_EQ(0x1001, self->poked);
1574}
1575
1576TEST_F(TRACE_poke, getpid_runs_normally)
1577{
1578 long ret;
1579
1580 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1581 ASSERT_EQ(0, ret);
1582
1583 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1584 ASSERT_EQ(0, ret);
1585
1586 EXPECT_EQ(0, self->poked);
1587 EXPECT_NE(0, syscall(__NR_getpid));
1588 EXPECT_EQ(0, self->poked);
1589}
1590
1591#if defined(__x86_64__)
1592# define ARCH_REGS struct user_regs_struct
1593# define SYSCALL_NUM orig_rax
1594# define SYSCALL_RET rax
1595#elif defined(__i386__)
1596# define ARCH_REGS struct user_regs_struct
1597# define SYSCALL_NUM orig_eax
1598# define SYSCALL_RET eax
1599#elif defined(__arm__)
1600# define ARCH_REGS struct pt_regs
1601# define SYSCALL_NUM ARM_r7
1602# define SYSCALL_RET ARM_r0
1603#elif defined(__aarch64__)
1604# define ARCH_REGS struct user_pt_regs
1605# define SYSCALL_NUM regs[8]
1606# define SYSCALL_RET regs[0]
David Abdurachmanov53406272019-10-04 17:12:22 -07001607#elif defined(__riscv) && __riscv_xlen == 64
1608# define ARCH_REGS struct user_regs_struct
1609# define SYSCALL_NUM a7
1610# define SYSCALL_RET a0
Helge Deller64e2a422016-04-01 22:40:53 +02001611#elif defined(__hppa__)
1612# define ARCH_REGS struct user_regs_struct
1613# define SYSCALL_NUM gr[20]
1614# define SYSCALL_RET gr[28]
Michael Ellerman5d83c2b2015-07-23 20:21:11 +10001615#elif defined(__powerpc__)
1616# define ARCH_REGS struct pt_regs
1617# define SYSCALL_NUM gpr[0]
1618# define SYSCALL_RET gpr[3]
Kees Cookb623c4d2015-08-21 11:22:35 -07001619#elif defined(__s390__)
1620# define ARCH_REGS s390_regs
1621# define SYSCALL_NUM gprs[2]
1622# define SYSCALL_RET gprs[2]
Matt Redfearn0ce105b2016-03-29 09:35:29 +01001623#elif defined(__mips__)
1624# define ARCH_REGS struct pt_regs
1625# define SYSCALL_NUM regs[2]
1626# define SYSCALL_SYSCALL_NUM regs[4]
1627# define SYSCALL_RET regs[2]
1628# define SYSCALL_NUM_RET_SHARE_REG
Kees Cookc99ee512015-06-16 10:54:14 -07001629#else
1630# error "Do not know how to find your architecture's registers and syscalls"
1631#endif
1632
Kees Cooka33b2d02016-08-08 17:46:23 -07001633/* When the syscall return can't be changed, stub out the tests for it. */
1634#ifdef SYSCALL_NUM_RET_SHARE_REG
1635# define EXPECT_SYSCALL_RETURN(val, action) EXPECT_EQ(-1, action)
1636#else
Kees Cooked5f1322019-01-25 10:33:59 -08001637# define EXPECT_SYSCALL_RETURN(val, action) \
1638 do { \
1639 errno = 0; \
1640 if (val < 0) { \
1641 EXPECT_EQ(-1, action); \
1642 EXPECT_EQ(-(val), errno); \
1643 } else { \
1644 EXPECT_EQ(val, action); \
1645 } \
1646 } while (0)
Kees Cooka33b2d02016-08-08 17:46:23 -07001647#endif
1648
Mickaël Salaün4a0b8802015-12-29 21:35:45 +01001649/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
1650 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
1651 */
Matt Redfearn0ce105b2016-03-29 09:35:29 +01001652#if defined(__x86_64__) || defined(__i386__) || defined(__mips__)
Mickaël Salaün4a0b8802015-12-29 21:35:45 +01001653#define HAVE_GETREGS
1654#endif
1655
Kees Cookc99ee512015-06-16 10:54:14 -07001656/* Architecture-specific syscall fetching routine. */
1657int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
1658{
Kees Cookc99ee512015-06-16 10:54:14 -07001659 ARCH_REGS regs;
Mickaël Salaün4a0b8802015-12-29 21:35:45 +01001660#ifdef HAVE_GETREGS
1661 EXPECT_EQ(0, ptrace(PTRACE_GETREGS, tracee, 0, &regs)) {
1662 TH_LOG("PTRACE_GETREGS failed");
1663 return -1;
1664 }
1665#else
1666 struct iovec iov;
Kees Cookc99ee512015-06-16 10:54:14 -07001667
1668 iov.iov_base = &regs;
1669 iov.iov_len = sizeof(regs);
1670 EXPECT_EQ(0, ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &iov)) {
1671 TH_LOG("PTRACE_GETREGSET failed");
1672 return -1;
1673 }
Mickaël Salaün4a0b8802015-12-29 21:35:45 +01001674#endif
Kees Cookc99ee512015-06-16 10:54:14 -07001675
Matt Redfearn0ce105b2016-03-29 09:35:29 +01001676#if defined(__mips__)
1677 if (regs.SYSCALL_NUM == __NR_O32_Linux)
1678 return regs.SYSCALL_SYSCALL_NUM;
1679#endif
Kees Cookc99ee512015-06-16 10:54:14 -07001680 return regs.SYSCALL_NUM;
1681}
1682
1683/* Architecture-specific syscall changing routine. */
1684void change_syscall(struct __test_metadata *_metadata,
Kees Cooked5f1322019-01-25 10:33:59 -08001685 pid_t tracee, int syscall, int result)
Kees Cookc99ee512015-06-16 10:54:14 -07001686{
Kees Cookc99ee512015-06-16 10:54:14 -07001687 int ret;
1688 ARCH_REGS regs;
Mickaël Salaün4a0b8802015-12-29 21:35:45 +01001689#ifdef HAVE_GETREGS
1690 ret = ptrace(PTRACE_GETREGS, tracee, 0, &regs);
1691#else
1692 struct iovec iov;
Kees Cookc99ee512015-06-16 10:54:14 -07001693 iov.iov_base = &regs;
1694 iov.iov_len = sizeof(regs);
1695 ret = ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &iov);
Mickaël Salaün4a0b8802015-12-29 21:35:45 +01001696#endif
Mickaël Salaün34a048c2017-06-11 14:32:58 +02001697 EXPECT_EQ(0, ret) {}
Kees Cookc99ee512015-06-16 10:54:14 -07001698
Kees Cook256d0af2015-10-06 12:30:25 -07001699#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \
David Abdurachmanov53406272019-10-04 17:12:22 -07001700 defined(__s390__) || defined(__hppa__) || defined(__riscv)
Kees Cookc99ee512015-06-16 10:54:14 -07001701 {
1702 regs.SYSCALL_NUM = syscall;
1703 }
Matt Redfearn0ce105b2016-03-29 09:35:29 +01001704#elif defined(__mips__)
1705 {
1706 if (regs.SYSCALL_NUM == __NR_O32_Linux)
1707 regs.SYSCALL_SYSCALL_NUM = syscall;
1708 else
1709 regs.SYSCALL_NUM = syscall;
1710 }
Kees Cookc99ee512015-06-16 10:54:14 -07001711
1712#elif defined(__arm__)
1713# ifndef PTRACE_SET_SYSCALL
1714# define PTRACE_SET_SYSCALL 23
1715# endif
1716 {
1717 ret = ptrace(PTRACE_SET_SYSCALL, tracee, NULL, syscall);
1718 EXPECT_EQ(0, ret);
1719 }
1720
Kees Cook256d0af2015-10-06 12:30:25 -07001721#elif defined(__aarch64__)
1722# ifndef NT_ARM_SYSTEM_CALL
1723# define NT_ARM_SYSTEM_CALL 0x404
1724# endif
1725 {
1726 iov.iov_base = &syscall;
1727 iov.iov_len = sizeof(syscall);
1728 ret = ptrace(PTRACE_SETREGSET, tracee, NT_ARM_SYSTEM_CALL,
1729 &iov);
1730 EXPECT_EQ(0, ret);
1731 }
1732
Kees Cookc99ee512015-06-16 10:54:14 -07001733#else
1734 ASSERT_EQ(1, 0) {
1735 TH_LOG("How is the syscall changed on this architecture?");
1736 }
1737#endif
1738
1739 /* If syscall is skipped, change return value. */
1740 if (syscall == -1)
Matt Redfearn0ce105b2016-03-29 09:35:29 +01001741#ifdef SYSCALL_NUM_RET_SHARE_REG
1742 TH_LOG("Can't modify syscall return on this architecture");
1743#else
Kees Cooked5f1322019-01-25 10:33:59 -08001744 regs.SYSCALL_RET = result;
Matt Redfearn0ce105b2016-03-29 09:35:29 +01001745#endif
Kees Cookc99ee512015-06-16 10:54:14 -07001746
Mickaël Salaün4a0b8802015-12-29 21:35:45 +01001747#ifdef HAVE_GETREGS
1748 ret = ptrace(PTRACE_SETREGS, tracee, 0, &regs);
1749#else
Kees Cook256d0af2015-10-06 12:30:25 -07001750 iov.iov_base = &regs;
1751 iov.iov_len = sizeof(regs);
Kees Cookc99ee512015-06-16 10:54:14 -07001752 ret = ptrace(PTRACE_SETREGSET, tracee, NT_PRSTATUS, &iov);
Mickaël Salaün4a0b8802015-12-29 21:35:45 +01001753#endif
Kees Cookc99ee512015-06-16 10:54:14 -07001754 EXPECT_EQ(0, ret);
1755}
1756
1757void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
1758 int status, void *args)
1759{
1760 int ret;
1761 unsigned long msg;
1762
1763 /* Make sure we got the right message. */
1764 ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
1765 EXPECT_EQ(0, ret);
1766
Kees Cookb623c4d2015-08-21 11:22:35 -07001767 /* Validate and take action on expected syscalls. */
Kees Cookc99ee512015-06-16 10:54:14 -07001768 switch (msg) {
1769 case 0x1002:
1770 /* change getpid to getppid. */
Kees Cookb623c4d2015-08-21 11:22:35 -07001771 EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
Kees Cooked5f1322019-01-25 10:33:59 -08001772 change_syscall(_metadata, tracee, __NR_getppid, 0);
Kees Cookc99ee512015-06-16 10:54:14 -07001773 break;
1774 case 0x1003:
Kees Cooked5f1322019-01-25 10:33:59 -08001775 /* skip gettid with valid return code. */
Kees Cookb623c4d2015-08-21 11:22:35 -07001776 EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
Kees Cooked5f1322019-01-25 10:33:59 -08001777 change_syscall(_metadata, tracee, -1, 45000);
Kees Cookc99ee512015-06-16 10:54:14 -07001778 break;
1779 case 0x1004:
Kees Cooked5f1322019-01-25 10:33:59 -08001780 /* skip openat with error. */
1781 EXPECT_EQ(__NR_openat, get_syscall(_metadata, tracee));
1782 change_syscall(_metadata, tracee, -1, -ESRCH);
1783 break;
1784 case 0x1005:
Kees Cookc99ee512015-06-16 10:54:14 -07001785 /* do nothing (allow getppid) */
Kees Cookb623c4d2015-08-21 11:22:35 -07001786 EXPECT_EQ(__NR_getppid, get_syscall(_metadata, tracee));
Kees Cookc99ee512015-06-16 10:54:14 -07001787 break;
1788 default:
1789 EXPECT_EQ(0, msg) {
1790 TH_LOG("Unknown PTRACE_GETEVENTMSG: 0x%lx", msg);
1791 kill(tracee, SIGKILL);
1792 }
1793 }
1794
1795}
1796
Kees Cook58d0a862016-05-26 11:47:01 -07001797void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
1798 int status, void *args)
1799{
1800 int ret, nr;
1801 unsigned long msg;
1802 static bool entry;
1803
Elvira Khabirova201766a2019-07-16 16:29:42 -07001804 /*
1805 * The traditional way to tell PTRACE_SYSCALL entry/exit
1806 * is by counting.
1807 */
1808 entry = !entry;
1809
1810 /* Make sure we got an appropriate message. */
Kees Cook58d0a862016-05-26 11:47:01 -07001811 ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
1812 EXPECT_EQ(0, ret);
Elvira Khabirova201766a2019-07-16 16:29:42 -07001813 EXPECT_EQ(entry ? PTRACE_EVENTMSG_SYSCALL_ENTRY
1814 : PTRACE_EVENTMSG_SYSCALL_EXIT, msg);
Kees Cook58d0a862016-05-26 11:47:01 -07001815
Kees Cook58d0a862016-05-26 11:47:01 -07001816 if (!entry)
1817 return;
1818
1819 nr = get_syscall(_metadata, tracee);
1820
1821 if (nr == __NR_getpid)
Kees Cooked5f1322019-01-25 10:33:59 -08001822 change_syscall(_metadata, tracee, __NR_getppid, 0);
1823 if (nr == __NR_gettid)
1824 change_syscall(_metadata, tracee, -1, 45000);
Anders Roxell912ec312018-01-05 17:31:18 +01001825 if (nr == __NR_openat)
Kees Cooked5f1322019-01-25 10:33:59 -08001826 change_syscall(_metadata, tracee, -1, -ESRCH);
Kees Cook58d0a862016-05-26 11:47:01 -07001827}
1828
Kees Cook1ae81d72020-03-11 12:21:28 -07001829FIXTURE(TRACE_syscall) {
Kees Cookc99ee512015-06-16 10:54:14 -07001830 struct sock_fprog prog;
1831 pid_t tracer, mytid, mypid, parent;
1832};
1833
1834FIXTURE_SETUP(TRACE_syscall)
1835{
1836 struct sock_filter filter[] = {
1837 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1838 offsetof(struct seccomp_data, nr)),
1839 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
1840 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1002),
1841 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_gettid, 0, 1),
1842 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1003),
Kees Cooked5f1322019-01-25 10:33:59 -08001843 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_openat, 0, 1),
Kees Cookc99ee512015-06-16 10:54:14 -07001844 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1004),
Kees Cooked5f1322019-01-25 10:33:59 -08001845 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
1846 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1005),
Kees Cookc99ee512015-06-16 10:54:14 -07001847 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1848 };
1849
1850 memset(&self->prog, 0, sizeof(self->prog));
1851 self->prog.filter = malloc(sizeof(filter));
1852 ASSERT_NE(NULL, self->prog.filter);
1853 memcpy(self->prog.filter, filter, sizeof(filter));
1854 self->prog.len = (unsigned short)ARRAY_SIZE(filter);
1855
1856 /* Prepare some testable syscall results. */
1857 self->mytid = syscall(__NR_gettid);
1858 ASSERT_GT(self->mytid, 0);
1859 ASSERT_NE(self->mytid, 1) {
1860 TH_LOG("Running this test as init is not supported. :)");
1861 }
1862
1863 self->mypid = getpid();
1864 ASSERT_GT(self->mypid, 0);
1865 ASSERT_EQ(self->mytid, self->mypid);
1866
1867 self->parent = getppid();
1868 ASSERT_GT(self->parent, 0);
1869 ASSERT_NE(self->parent, self->mypid);
1870
1871 /* Launch tracer. */
Kees Cook58d0a862016-05-26 11:47:01 -07001872 self->tracer = setup_trace_fixture(_metadata, tracer_syscall, NULL,
1873 false);
Kees Cookc99ee512015-06-16 10:54:14 -07001874}
1875
1876FIXTURE_TEARDOWN(TRACE_syscall)
1877{
1878 teardown_trace_fixture(_metadata, self->tracer);
1879 if (self->prog.filter)
1880 free(self->prog.filter);
1881}
1882
Kees Cooka33b2d02016-08-08 17:46:23 -07001883TEST_F(TRACE_syscall, ptrace_syscall_redirected)
1884{
1885 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1886 teardown_trace_fixture(_metadata, self->tracer);
1887 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1888 true);
1889
1890 /* Tracer will redirect getpid to getppid. */
1891 EXPECT_NE(self->mypid, syscall(__NR_getpid));
1892}
1893
Kees Cooked5f1322019-01-25 10:33:59 -08001894TEST_F(TRACE_syscall, ptrace_syscall_errno)
Kees Cooka33b2d02016-08-08 17:46:23 -07001895{
1896 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1897 teardown_trace_fixture(_metadata, self->tracer);
1898 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1899 true);
1900
Kees Cooked5f1322019-01-25 10:33:59 -08001901 /* Tracer should skip the open syscall, resulting in ESRCH. */
1902 EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
1903}
1904
1905TEST_F(TRACE_syscall, ptrace_syscall_faked)
1906{
1907 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1908 teardown_trace_fixture(_metadata, self->tracer);
1909 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1910 true);
1911
1912 /* Tracer should skip the gettid syscall, resulting fake pid. */
1913 EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
Kees Cooka33b2d02016-08-08 17:46:23 -07001914}
1915
Kees Cookc99ee512015-06-16 10:54:14 -07001916TEST_F(TRACE_syscall, syscall_allowed)
1917{
1918 long ret;
1919
1920 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1921 ASSERT_EQ(0, ret);
1922
1923 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1924 ASSERT_EQ(0, ret);
1925
1926 /* getppid works as expected (no changes). */
1927 EXPECT_EQ(self->parent, syscall(__NR_getppid));
1928 EXPECT_NE(self->mypid, syscall(__NR_getppid));
1929}
1930
1931TEST_F(TRACE_syscall, syscall_redirected)
1932{
1933 long ret;
1934
1935 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1936 ASSERT_EQ(0, ret);
1937
1938 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1939 ASSERT_EQ(0, ret);
1940
1941 /* getpid has been redirected to getppid as expected. */
1942 EXPECT_EQ(self->parent, syscall(__NR_getpid));
1943 EXPECT_NE(self->mypid, syscall(__NR_getpid));
1944}
1945
Kees Cooked5f1322019-01-25 10:33:59 -08001946TEST_F(TRACE_syscall, syscall_errno)
1947{
1948 long ret;
1949
1950 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1951 ASSERT_EQ(0, ret);
1952
1953 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1954 ASSERT_EQ(0, ret);
1955
1956 /* openat has been skipped and an errno return. */
1957 EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
1958}
1959
1960TEST_F(TRACE_syscall, syscall_faked)
Kees Cookc99ee512015-06-16 10:54:14 -07001961{
1962 long ret;
1963
1964 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1965 ASSERT_EQ(0, ret);
1966
1967 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1968 ASSERT_EQ(0, ret);
1969
1970 /* gettid has been skipped and an altered return value stored. */
Kees Cooked5f1322019-01-25 10:33:59 -08001971 EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
Kees Cookc99ee512015-06-16 10:54:14 -07001972}
1973
Kees Cook58d0a862016-05-26 11:47:01 -07001974TEST_F(TRACE_syscall, skip_after_RET_TRACE)
1975{
1976 struct sock_filter filter[] = {
1977 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1978 offsetof(struct seccomp_data, nr)),
1979 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
1980 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EPERM),
1981 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1982 };
1983 struct sock_fprog prog = {
1984 .len = (unsigned short)ARRAY_SIZE(filter),
1985 .filter = filter,
1986 };
1987 long ret;
1988
1989 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1990 ASSERT_EQ(0, ret);
1991
1992 /* Install fixture filter. */
1993 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1994 ASSERT_EQ(0, ret);
1995
1996 /* Install "errno on getppid" filter. */
1997 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
1998 ASSERT_EQ(0, ret);
1999
2000 /* Tracer will redirect getpid to getppid, and we should see EPERM. */
Kees Cooka33b2d02016-08-08 17:46:23 -07002001 errno = 0;
Kees Cook58d0a862016-05-26 11:47:01 -07002002 EXPECT_EQ(-1, syscall(__NR_getpid));
2003 EXPECT_EQ(EPERM, errno);
2004}
2005
2006TEST_F_SIGNAL(TRACE_syscall, kill_after_RET_TRACE, SIGSYS)
2007{
2008 struct sock_filter filter[] = {
2009 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2010 offsetof(struct seccomp_data, nr)),
2011 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
2012 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
2013 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2014 };
2015 struct sock_fprog prog = {
2016 .len = (unsigned short)ARRAY_SIZE(filter),
2017 .filter = filter,
2018 };
2019 long ret;
2020
2021 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2022 ASSERT_EQ(0, ret);
2023
2024 /* Install fixture filter. */
2025 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
2026 ASSERT_EQ(0, ret);
2027
2028 /* Install "death on getppid" filter. */
2029 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
2030 ASSERT_EQ(0, ret);
2031
2032 /* Tracer will redirect getpid to getppid, and we should die. */
2033 EXPECT_NE(self->mypid, syscall(__NR_getpid));
2034}
2035
2036TEST_F(TRACE_syscall, skip_after_ptrace)
2037{
2038 struct sock_filter filter[] = {
2039 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2040 offsetof(struct seccomp_data, nr)),
2041 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
2042 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EPERM),
2043 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2044 };
2045 struct sock_fprog prog = {
2046 .len = (unsigned short)ARRAY_SIZE(filter),
2047 .filter = filter,
2048 };
2049 long ret;
2050
2051 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
2052 teardown_trace_fixture(_metadata, self->tracer);
2053 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
2054 true);
2055
2056 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2057 ASSERT_EQ(0, ret);
2058
2059 /* Install "errno on getppid" filter. */
2060 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
2061 ASSERT_EQ(0, ret);
2062
2063 /* Tracer will redirect getpid to getppid, and we should see EPERM. */
2064 EXPECT_EQ(-1, syscall(__NR_getpid));
2065 EXPECT_EQ(EPERM, errno);
2066}
2067
2068TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS)
2069{
2070 struct sock_filter filter[] = {
2071 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2072 offsetof(struct seccomp_data, nr)),
2073 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
2074 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
2075 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2076 };
2077 struct sock_fprog prog = {
2078 .len = (unsigned short)ARRAY_SIZE(filter),
2079 .filter = filter,
2080 };
2081 long ret;
2082
2083 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
2084 teardown_trace_fixture(_metadata, self->tracer);
2085 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
2086 true);
2087
2088 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2089 ASSERT_EQ(0, ret);
2090
2091 /* Install "death on getppid" filter. */
2092 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
2093 ASSERT_EQ(0, ret);
2094
2095 /* Tracer will redirect getpid to getppid, and we should die. */
2096 EXPECT_NE(self->mypid, syscall(__NR_getpid));
2097}
2098
Kees Cookc99ee512015-06-16 10:54:14 -07002099TEST(seccomp_syscall)
2100{
2101 struct sock_filter filter[] = {
2102 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2103 };
2104 struct sock_fprog prog = {
2105 .len = (unsigned short)ARRAY_SIZE(filter),
2106 .filter = filter,
2107 };
2108 long ret;
2109
2110 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2111 ASSERT_EQ(0, ret) {
2112 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2113 }
2114
2115 /* Reject insane operation. */
2116 ret = seccomp(-1, 0, &prog);
Kees Cookb623c4d2015-08-21 11:22:35 -07002117 ASSERT_NE(ENOSYS, errno) {
2118 TH_LOG("Kernel does not support seccomp syscall!");
2119 }
Kees Cookc99ee512015-06-16 10:54:14 -07002120 EXPECT_EQ(EINVAL, errno) {
2121 TH_LOG("Did not reject crazy op value!");
2122 }
2123
2124 /* Reject strict with flags or pointer. */
2125 ret = seccomp(SECCOMP_SET_MODE_STRICT, -1, NULL);
2126 EXPECT_EQ(EINVAL, errno) {
2127 TH_LOG("Did not reject mode strict with flags!");
2128 }
2129 ret = seccomp(SECCOMP_SET_MODE_STRICT, 0, &prog);
2130 EXPECT_EQ(EINVAL, errno) {
2131 TH_LOG("Did not reject mode strict with uargs!");
2132 }
2133
2134 /* Reject insane args for filter. */
2135 ret = seccomp(SECCOMP_SET_MODE_FILTER, -1, &prog);
2136 EXPECT_EQ(EINVAL, errno) {
2137 TH_LOG("Did not reject crazy filter flags!");
2138 }
2139 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, NULL);
2140 EXPECT_EQ(EFAULT, errno) {
2141 TH_LOG("Did not reject NULL filter!");
2142 }
2143
2144 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
2145 EXPECT_EQ(0, errno) {
2146 TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER: %s",
2147 strerror(errno));
2148 }
2149}
2150
2151TEST(seccomp_syscall_mode_lock)
2152{
2153 struct sock_filter filter[] = {
2154 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2155 };
2156 struct sock_fprog prog = {
2157 .len = (unsigned short)ARRAY_SIZE(filter),
2158 .filter = filter,
2159 };
2160 long ret;
2161
2162 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
2163 ASSERT_EQ(0, ret) {
2164 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2165 }
2166
2167 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
Kees Cookb623c4d2015-08-21 11:22:35 -07002168 ASSERT_NE(ENOSYS, errno) {
2169 TH_LOG("Kernel does not support seccomp syscall!");
2170 }
Kees Cookc99ee512015-06-16 10:54:14 -07002171 EXPECT_EQ(0, ret) {
2172 TH_LOG("Could not install filter!");
2173 }
2174
2175 /* Make sure neither entry point will switch to strict. */
2176 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, 0, 0, 0);
2177 EXPECT_EQ(EINVAL, errno) {
2178 TH_LOG("Switched to mode strict!");
2179 }
2180
2181 ret = seccomp(SECCOMP_SET_MODE_STRICT, 0, NULL);
2182 EXPECT_EQ(EINVAL, errno) {
2183 TH_LOG("Switched to mode strict!");
2184 }
2185}
2186
Tyler Hicks2b7ea5b2017-08-11 04:33:55 +00002187/*
2188 * Test detection of known and unknown filter flags. Userspace needs to be able
2189 * to check if a filter flag is supported by the current kernel and a good way
2190 * of doing that is by attempting to enter filter mode, with the flag bit in
2191 * question set, and a NULL pointer for the _args_ parameter. EFAULT indicates
2192 * that the flag is valid and EINVAL indicates that the flag is invalid.
2193 */
2194TEST(detect_seccomp_filter_flags)
2195{
Tyler Hickse66a3992017-08-11 04:33:56 +00002196 unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
Kees Cook00a02d02018-05-03 14:56:12 -07002197 SECCOMP_FILTER_FLAG_LOG,
Tycho Andersen6a21cc52018-12-09 11:24:13 -07002198 SECCOMP_FILTER_FLAG_SPEC_ALLOW,
Tycho Andersen51891492020-03-04 11:05:17 -07002199 SECCOMP_FILTER_FLAG_NEW_LISTENER,
2200 SECCOMP_FILTER_FLAG_TSYNC_ESRCH };
Kees Cook4ee07762019-04-24 09:32:55 -07002201 unsigned int exclusive[] = {
2202 SECCOMP_FILTER_FLAG_TSYNC,
2203 SECCOMP_FILTER_FLAG_NEW_LISTENER };
2204 unsigned int flag, all_flags, exclusive_mask;
Tyler Hicks2b7ea5b2017-08-11 04:33:55 +00002205 int i;
2206 long ret;
2207
Kees Cook4ee07762019-04-24 09:32:55 -07002208 /* Test detection of individual known-good filter flags */
Tyler Hicks2b7ea5b2017-08-11 04:33:55 +00002209 for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
Kees Cook00a02d02018-05-03 14:56:12 -07002210 int bits = 0;
2211
Tyler Hicks2b7ea5b2017-08-11 04:33:55 +00002212 flag = flags[i];
Kees Cook00a02d02018-05-03 14:56:12 -07002213 /* Make sure the flag is a single bit! */
2214 while (flag) {
2215 if (flag & 0x1)
2216 bits ++;
2217 flag >>= 1;
2218 }
2219 ASSERT_EQ(1, bits);
2220 flag = flags[i];
2221
Tyler Hicks2b7ea5b2017-08-11 04:33:55 +00002222 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2223 ASSERT_NE(ENOSYS, errno) {
2224 TH_LOG("Kernel does not support seccomp syscall!");
2225 }
2226 EXPECT_EQ(-1, ret);
2227 EXPECT_EQ(EFAULT, errno) {
2228 TH_LOG("Failed to detect that a known-good filter flag (0x%X) is supported!",
2229 flag);
2230 }
2231
2232 all_flags |= flag;
2233 }
2234
Kees Cook4ee07762019-04-24 09:32:55 -07002235 /*
2236 * Test detection of all known-good filter flags combined. But
2237 * for the exclusive flags we need to mask them out and try them
2238 * individually for the "all flags" testing.
2239 */
2240 exclusive_mask = 0;
2241 for (i = 0; i < ARRAY_SIZE(exclusive); i++)
2242 exclusive_mask |= exclusive[i];
2243 for (i = 0; i < ARRAY_SIZE(exclusive); i++) {
2244 flag = all_flags & ~exclusive_mask;
2245 flag |= exclusive[i];
2246
2247 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2248 EXPECT_EQ(-1, ret);
2249 EXPECT_EQ(EFAULT, errno) {
2250 TH_LOG("Failed to detect that all known-good filter flags (0x%X) are supported!",
2251 flag);
2252 }
Tyler Hicks2b7ea5b2017-08-11 04:33:55 +00002253 }
2254
Kees Cook4ee07762019-04-24 09:32:55 -07002255 /* Test detection of an unknown filter flags, without exclusives. */
Tyler Hicks2b7ea5b2017-08-11 04:33:55 +00002256 flag = -1;
Kees Cook4ee07762019-04-24 09:32:55 -07002257 flag &= ~exclusive_mask;
Tyler Hicks2b7ea5b2017-08-11 04:33:55 +00002258 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2259 EXPECT_EQ(-1, ret);
2260 EXPECT_EQ(EINVAL, errno) {
2261 TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported!",
2262 flag);
2263 }
2264
2265 /*
2266 * Test detection of an unknown filter flag that may simply need to be
2267 * added to this test
2268 */
2269 flag = flags[ARRAY_SIZE(flags) - 1] << 1;
2270 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2271 EXPECT_EQ(-1, ret);
2272 EXPECT_EQ(EINVAL, errno) {
2273 TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported! Does a new flag need to be added to this test?",
2274 flag);
2275 }
2276}
2277
Kees Cookc99ee512015-06-16 10:54:14 -07002278TEST(TSYNC_first)
2279{
2280 struct sock_filter filter[] = {
2281 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2282 };
2283 struct sock_fprog prog = {
2284 .len = (unsigned short)ARRAY_SIZE(filter),
2285 .filter = filter,
2286 };
2287 long ret;
2288
2289 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
2290 ASSERT_EQ(0, ret) {
2291 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2292 }
2293
Mickaël Salaün6c045d02016-03-29 20:46:07 +02002294 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
Kees Cookc99ee512015-06-16 10:54:14 -07002295 &prog);
Kees Cookb623c4d2015-08-21 11:22:35 -07002296 ASSERT_NE(ENOSYS, errno) {
2297 TH_LOG("Kernel does not support seccomp syscall!");
2298 }
Kees Cookc99ee512015-06-16 10:54:14 -07002299 EXPECT_EQ(0, ret) {
2300 TH_LOG("Could not install initial filter with TSYNC!");
2301 }
2302}
2303
2304#define TSYNC_SIBLINGS 2
2305struct tsync_sibling {
2306 pthread_t tid;
2307 pid_t system_tid;
2308 sem_t *started;
2309 pthread_cond_t *cond;
2310 pthread_mutex_t *mutex;
2311 int diverge;
2312 int num_waits;
2313 struct sock_fprog *prog;
2314 struct __test_metadata *metadata;
2315};
2316
Kees Cook93bd70e2017-03-20 16:41:35 -07002317/*
2318 * To avoid joining joined threads (which is not allowed by Bionic),
2319 * make sure we both successfully join and clear the tid to skip a
2320 * later join attempt during fixture teardown. Any remaining threads
2321 * will be directly killed during teardown.
2322 */
2323#define PTHREAD_JOIN(tid, status) \
2324 do { \
2325 int _rc = pthread_join(tid, status); \
2326 if (_rc) { \
2327 TH_LOG("pthread_join of tid %u failed: %d\n", \
2328 (unsigned int)tid, _rc); \
2329 } else { \
2330 tid = 0; \
2331 } \
2332 } while (0)
2333
Kees Cook1ae81d72020-03-11 12:21:28 -07002334FIXTURE(TSYNC) {
Kees Cookc99ee512015-06-16 10:54:14 -07002335 struct sock_fprog root_prog, apply_prog;
2336 struct tsync_sibling sibling[TSYNC_SIBLINGS];
2337 sem_t started;
2338 pthread_cond_t cond;
2339 pthread_mutex_t mutex;
2340 int sibling_count;
2341};
2342
2343FIXTURE_SETUP(TSYNC)
2344{
2345 struct sock_filter root_filter[] = {
2346 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2347 };
2348 struct sock_filter apply_filter[] = {
2349 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2350 offsetof(struct seccomp_data, nr)),
2351 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
2352 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
2353 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2354 };
2355
2356 memset(&self->root_prog, 0, sizeof(self->root_prog));
2357 memset(&self->apply_prog, 0, sizeof(self->apply_prog));
2358 memset(&self->sibling, 0, sizeof(self->sibling));
2359 self->root_prog.filter = malloc(sizeof(root_filter));
2360 ASSERT_NE(NULL, self->root_prog.filter);
2361 memcpy(self->root_prog.filter, &root_filter, sizeof(root_filter));
2362 self->root_prog.len = (unsigned short)ARRAY_SIZE(root_filter);
2363
2364 self->apply_prog.filter = malloc(sizeof(apply_filter));
2365 ASSERT_NE(NULL, self->apply_prog.filter);
2366 memcpy(self->apply_prog.filter, &apply_filter, sizeof(apply_filter));
2367 self->apply_prog.len = (unsigned short)ARRAY_SIZE(apply_filter);
2368
2369 self->sibling_count = 0;
2370 pthread_mutex_init(&self->mutex, NULL);
2371 pthread_cond_init(&self->cond, NULL);
2372 sem_init(&self->started, 0, 0);
2373 self->sibling[0].tid = 0;
2374 self->sibling[0].cond = &self->cond;
2375 self->sibling[0].started = &self->started;
2376 self->sibling[0].mutex = &self->mutex;
2377 self->sibling[0].diverge = 0;
2378 self->sibling[0].num_waits = 1;
2379 self->sibling[0].prog = &self->root_prog;
2380 self->sibling[0].metadata = _metadata;
2381 self->sibling[1].tid = 0;
2382 self->sibling[1].cond = &self->cond;
2383 self->sibling[1].started = &self->started;
2384 self->sibling[1].mutex = &self->mutex;
2385 self->sibling[1].diverge = 0;
2386 self->sibling[1].prog = &self->root_prog;
2387 self->sibling[1].num_waits = 1;
2388 self->sibling[1].metadata = _metadata;
2389}
2390
2391FIXTURE_TEARDOWN(TSYNC)
2392{
2393 int sib = 0;
2394
2395 if (self->root_prog.filter)
2396 free(self->root_prog.filter);
2397 if (self->apply_prog.filter)
2398 free(self->apply_prog.filter);
2399
2400 for ( ; sib < self->sibling_count; ++sib) {
2401 struct tsync_sibling *s = &self->sibling[sib];
Kees Cookc99ee512015-06-16 10:54:14 -07002402
2403 if (!s->tid)
2404 continue;
Kees Cook93bd70e2017-03-20 16:41:35 -07002405 /*
2406 * If a thread is still running, it may be stuck, so hit
2407 * it over the head really hard.
2408 */
2409 pthread_kill(s->tid, 9);
Kees Cookc99ee512015-06-16 10:54:14 -07002410 }
2411 pthread_mutex_destroy(&self->mutex);
2412 pthread_cond_destroy(&self->cond);
2413 sem_destroy(&self->started);
2414}
2415
2416void *tsync_sibling(void *data)
2417{
2418 long ret = 0;
2419 struct tsync_sibling *me = data;
2420
2421 me->system_tid = syscall(__NR_gettid);
2422
2423 pthread_mutex_lock(me->mutex);
2424 if (me->diverge) {
2425 /* Just re-apply the root prog to fork the tree */
2426 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER,
2427 me->prog, 0, 0);
2428 }
2429 sem_post(me->started);
2430 /* Return outside of started so parent notices failures. */
2431 if (ret) {
2432 pthread_mutex_unlock(me->mutex);
2433 return (void *)SIBLING_EXIT_FAILURE;
2434 }
2435 do {
2436 pthread_cond_wait(me->cond, me->mutex);
2437 me->num_waits = me->num_waits - 1;
2438 } while (me->num_waits);
2439 pthread_mutex_unlock(me->mutex);
2440
2441 ret = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
2442 if (!ret)
2443 return (void *)SIBLING_EXIT_NEWPRIVS;
2444 read(0, NULL, 0);
2445 return (void *)SIBLING_EXIT_UNKILLED;
2446}
2447
2448void tsync_start_sibling(struct tsync_sibling *sibling)
2449{
2450 pthread_create(&sibling->tid, NULL, tsync_sibling, (void *)sibling);
2451}
2452
2453TEST_F(TSYNC, siblings_fail_prctl)
2454{
2455 long ret;
2456 void *status;
2457 struct sock_filter filter[] = {
2458 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2459 offsetof(struct seccomp_data, nr)),
2460 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
2461 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EINVAL),
2462 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2463 };
2464 struct sock_fprog prog = {
2465 .len = (unsigned short)ARRAY_SIZE(filter),
2466 .filter = filter,
2467 };
2468
2469 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
2470 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2471 }
2472
2473 /* Check prctl failure detection by requesting sib 0 diverge. */
2474 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
Kees Cookb623c4d2015-08-21 11:22:35 -07002475 ASSERT_NE(ENOSYS, errno) {
2476 TH_LOG("Kernel does not support seccomp syscall!");
2477 }
Kees Cookc99ee512015-06-16 10:54:14 -07002478 ASSERT_EQ(0, ret) {
2479 TH_LOG("setting filter failed");
2480 }
2481
2482 self->sibling[0].diverge = 1;
2483 tsync_start_sibling(&self->sibling[0]);
2484 tsync_start_sibling(&self->sibling[1]);
2485
2486 while (self->sibling_count < TSYNC_SIBLINGS) {
2487 sem_wait(&self->started);
2488 self->sibling_count++;
2489 }
2490
2491 /* Signal the threads to clean up*/
2492 pthread_mutex_lock(&self->mutex);
2493 ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
2494 TH_LOG("cond broadcast non-zero");
2495 }
2496 pthread_mutex_unlock(&self->mutex);
2497
2498 /* Ensure diverging sibling failed to call prctl. */
Kees Cook93bd70e2017-03-20 16:41:35 -07002499 PTHREAD_JOIN(self->sibling[0].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002500 EXPECT_EQ(SIBLING_EXIT_FAILURE, (long)status);
Kees Cook93bd70e2017-03-20 16:41:35 -07002501 PTHREAD_JOIN(self->sibling[1].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002502 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
2503}
2504
2505TEST_F(TSYNC, two_siblings_with_ancestor)
2506{
2507 long ret;
2508 void *status;
2509
2510 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
2511 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2512 }
2513
2514 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
Kees Cookb623c4d2015-08-21 11:22:35 -07002515 ASSERT_NE(ENOSYS, errno) {
2516 TH_LOG("Kernel does not support seccomp syscall!");
2517 }
Kees Cookc99ee512015-06-16 10:54:14 -07002518 ASSERT_EQ(0, ret) {
2519 TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
2520 }
2521 tsync_start_sibling(&self->sibling[0]);
2522 tsync_start_sibling(&self->sibling[1]);
2523
2524 while (self->sibling_count < TSYNC_SIBLINGS) {
2525 sem_wait(&self->started);
2526 self->sibling_count++;
2527 }
2528
Mickaël Salaün6c045d02016-03-29 20:46:07 +02002529 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
Kees Cookc99ee512015-06-16 10:54:14 -07002530 &self->apply_prog);
2531 ASSERT_EQ(0, ret) {
2532 TH_LOG("Could install filter on all threads!");
2533 }
2534 /* Tell the siblings to test the policy */
2535 pthread_mutex_lock(&self->mutex);
2536 ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
2537 TH_LOG("cond broadcast non-zero");
2538 }
2539 pthread_mutex_unlock(&self->mutex);
2540 /* Ensure they are both killed and don't exit cleanly. */
Kees Cook93bd70e2017-03-20 16:41:35 -07002541 PTHREAD_JOIN(self->sibling[0].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002542 EXPECT_EQ(0x0, (long)status);
Kees Cook93bd70e2017-03-20 16:41:35 -07002543 PTHREAD_JOIN(self->sibling[1].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002544 EXPECT_EQ(0x0, (long)status);
2545}
2546
2547TEST_F(TSYNC, two_sibling_want_nnp)
2548{
2549 void *status;
2550
2551 /* start siblings before any prctl() operations */
2552 tsync_start_sibling(&self->sibling[0]);
2553 tsync_start_sibling(&self->sibling[1]);
2554 while (self->sibling_count < TSYNC_SIBLINGS) {
2555 sem_wait(&self->started);
2556 self->sibling_count++;
2557 }
2558
2559 /* Tell the siblings to test no policy */
2560 pthread_mutex_lock(&self->mutex);
2561 ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
2562 TH_LOG("cond broadcast non-zero");
2563 }
2564 pthread_mutex_unlock(&self->mutex);
2565
2566 /* Ensure they are both upset about lacking nnp. */
Kees Cook93bd70e2017-03-20 16:41:35 -07002567 PTHREAD_JOIN(self->sibling[0].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002568 EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
Kees Cook93bd70e2017-03-20 16:41:35 -07002569 PTHREAD_JOIN(self->sibling[1].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002570 EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
2571}
2572
2573TEST_F(TSYNC, two_siblings_with_no_filter)
2574{
2575 long ret;
2576 void *status;
2577
2578 /* start siblings before any prctl() operations */
2579 tsync_start_sibling(&self->sibling[0]);
2580 tsync_start_sibling(&self->sibling[1]);
2581 while (self->sibling_count < TSYNC_SIBLINGS) {
2582 sem_wait(&self->started);
2583 self->sibling_count++;
2584 }
2585
2586 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
2587 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2588 }
2589
Mickaël Salaün6c045d02016-03-29 20:46:07 +02002590 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
Kees Cookc99ee512015-06-16 10:54:14 -07002591 &self->apply_prog);
Kees Cookb623c4d2015-08-21 11:22:35 -07002592 ASSERT_NE(ENOSYS, errno) {
2593 TH_LOG("Kernel does not support seccomp syscall!");
2594 }
Kees Cookc99ee512015-06-16 10:54:14 -07002595 ASSERT_EQ(0, ret) {
2596 TH_LOG("Could install filter on all threads!");
2597 }
2598
2599 /* Tell the siblings to test the policy */
2600 pthread_mutex_lock(&self->mutex);
2601 ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
2602 TH_LOG("cond broadcast non-zero");
2603 }
2604 pthread_mutex_unlock(&self->mutex);
2605
2606 /* Ensure they are both killed and don't exit cleanly. */
Kees Cook93bd70e2017-03-20 16:41:35 -07002607 PTHREAD_JOIN(self->sibling[0].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002608 EXPECT_EQ(0x0, (long)status);
Kees Cook93bd70e2017-03-20 16:41:35 -07002609 PTHREAD_JOIN(self->sibling[1].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002610 EXPECT_EQ(0x0, (long)status);
2611}
2612
2613TEST_F(TSYNC, two_siblings_with_one_divergence)
2614{
2615 long ret;
2616 void *status;
2617
2618 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
2619 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2620 }
2621
2622 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
Kees Cookb623c4d2015-08-21 11:22:35 -07002623 ASSERT_NE(ENOSYS, errno) {
2624 TH_LOG("Kernel does not support seccomp syscall!");
2625 }
Kees Cookc99ee512015-06-16 10:54:14 -07002626 ASSERT_EQ(0, ret) {
2627 TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
2628 }
2629 self->sibling[0].diverge = 1;
2630 tsync_start_sibling(&self->sibling[0]);
2631 tsync_start_sibling(&self->sibling[1]);
2632
2633 while (self->sibling_count < TSYNC_SIBLINGS) {
2634 sem_wait(&self->started);
2635 self->sibling_count++;
2636 }
2637
Mickaël Salaün6c045d02016-03-29 20:46:07 +02002638 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
Kees Cookc99ee512015-06-16 10:54:14 -07002639 &self->apply_prog);
2640 ASSERT_EQ(self->sibling[0].system_tid, ret) {
2641 TH_LOG("Did not fail on diverged sibling.");
2642 }
2643
2644 /* Wake the threads */
2645 pthread_mutex_lock(&self->mutex);
2646 ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
2647 TH_LOG("cond broadcast non-zero");
2648 }
2649 pthread_mutex_unlock(&self->mutex);
2650
2651 /* Ensure they are both unkilled. */
Kees Cook93bd70e2017-03-20 16:41:35 -07002652 PTHREAD_JOIN(self->sibling[0].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002653 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
Kees Cook93bd70e2017-03-20 16:41:35 -07002654 PTHREAD_JOIN(self->sibling[1].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002655 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
2656}
2657
Tycho Andersen51891492020-03-04 11:05:17 -07002658TEST_F(TSYNC, two_siblings_with_one_divergence_no_tid_in_err)
2659{
2660 long ret, flags;
2661 void *status;
2662
2663 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
2664 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2665 }
2666
2667 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
2668 ASSERT_NE(ENOSYS, errno) {
2669 TH_LOG("Kernel does not support seccomp syscall!");
2670 }
2671 ASSERT_EQ(0, ret) {
2672 TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
2673 }
2674 self->sibling[0].diverge = 1;
2675 tsync_start_sibling(&self->sibling[0]);
2676 tsync_start_sibling(&self->sibling[1]);
2677
2678 while (self->sibling_count < TSYNC_SIBLINGS) {
2679 sem_wait(&self->started);
2680 self->sibling_count++;
2681 }
2682
2683 flags = SECCOMP_FILTER_FLAG_TSYNC | \
2684 SECCOMP_FILTER_FLAG_TSYNC_ESRCH;
2685 ret = seccomp(SECCOMP_SET_MODE_FILTER, flags, &self->apply_prog);
2686 ASSERT_EQ(ESRCH, errno) {
2687 TH_LOG("Did not return ESRCH for diverged sibling.");
2688 }
2689 ASSERT_EQ(-1, ret) {
2690 TH_LOG("Did not fail on diverged sibling.");
2691 }
2692
2693 /* Wake the threads */
2694 pthread_mutex_lock(&self->mutex);
2695 ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
2696 TH_LOG("cond broadcast non-zero");
2697 }
2698 pthread_mutex_unlock(&self->mutex);
2699
2700 /* Ensure they are both unkilled. */
2701 PTHREAD_JOIN(self->sibling[0].tid, &status);
2702 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
2703 PTHREAD_JOIN(self->sibling[1].tid, &status);
2704 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
2705}
2706
Kees Cookc99ee512015-06-16 10:54:14 -07002707TEST_F(TSYNC, two_siblings_not_under_filter)
2708{
2709 long ret, sib;
2710 void *status;
Kees Cooked492c22019-01-27 01:43:57 -08002711 struct timespec delay = { .tv_nsec = 100000000 };
Kees Cookc99ee512015-06-16 10:54:14 -07002712
2713 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
2714 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2715 }
2716
2717 /*
2718 * Sibling 0 will have its own seccomp policy
2719 * and Sibling 1 will not be under seccomp at
2720 * all. Sibling 1 will enter seccomp and 0
2721 * will cause failure.
2722 */
2723 self->sibling[0].diverge = 1;
2724 tsync_start_sibling(&self->sibling[0]);
2725 tsync_start_sibling(&self->sibling[1]);
2726
2727 while (self->sibling_count < TSYNC_SIBLINGS) {
2728 sem_wait(&self->started);
2729 self->sibling_count++;
2730 }
2731
2732 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
Kees Cookb623c4d2015-08-21 11:22:35 -07002733 ASSERT_NE(ENOSYS, errno) {
2734 TH_LOG("Kernel does not support seccomp syscall!");
2735 }
Kees Cookc99ee512015-06-16 10:54:14 -07002736 ASSERT_EQ(0, ret) {
2737 TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
2738 }
2739
Mickaël Salaün6c045d02016-03-29 20:46:07 +02002740 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
Kees Cookc99ee512015-06-16 10:54:14 -07002741 &self->apply_prog);
2742 ASSERT_EQ(ret, self->sibling[0].system_tid) {
2743 TH_LOG("Did not fail on diverged sibling.");
2744 }
2745 sib = 1;
2746 if (ret == self->sibling[0].system_tid)
2747 sib = 0;
2748
2749 pthread_mutex_lock(&self->mutex);
2750
2751 /* Increment the other siblings num_waits so we can clean up
2752 * the one we just saw.
2753 */
2754 self->sibling[!sib].num_waits += 1;
2755
2756 /* Signal the thread to clean up*/
2757 ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
2758 TH_LOG("cond broadcast non-zero");
2759 }
2760 pthread_mutex_unlock(&self->mutex);
Kees Cook93bd70e2017-03-20 16:41:35 -07002761 PTHREAD_JOIN(self->sibling[sib].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002762 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
2763 /* Poll for actual task death. pthread_join doesn't guarantee it. */
2764 while (!kill(self->sibling[sib].system_tid, 0))
Kees Cooked492c22019-01-27 01:43:57 -08002765 nanosleep(&delay, NULL);
Kees Cookc99ee512015-06-16 10:54:14 -07002766 /* Switch to the remaining sibling */
2767 sib = !sib;
2768
Mickaël Salaün6c045d02016-03-29 20:46:07 +02002769 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
Kees Cookc99ee512015-06-16 10:54:14 -07002770 &self->apply_prog);
2771 ASSERT_EQ(0, ret) {
2772 TH_LOG("Expected the remaining sibling to sync");
2773 };
2774
2775 pthread_mutex_lock(&self->mutex);
2776
2777 /* If remaining sibling didn't have a chance to wake up during
2778 * the first broadcast, manually reduce the num_waits now.
2779 */
2780 if (self->sibling[sib].num_waits > 1)
2781 self->sibling[sib].num_waits = 1;
2782 ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
2783 TH_LOG("cond broadcast non-zero");
2784 }
2785 pthread_mutex_unlock(&self->mutex);
Kees Cook93bd70e2017-03-20 16:41:35 -07002786 PTHREAD_JOIN(self->sibling[sib].tid, &status);
Kees Cookc99ee512015-06-16 10:54:14 -07002787 EXPECT_EQ(0, (long)status);
2788 /* Poll for actual task death. pthread_join doesn't guarantee it. */
2789 while (!kill(self->sibling[sib].system_tid, 0))
Kees Cooked492c22019-01-27 01:43:57 -08002790 nanosleep(&delay, NULL);
Kees Cookc99ee512015-06-16 10:54:14 -07002791
Mickaël Salaün6c045d02016-03-29 20:46:07 +02002792 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
Kees Cookc99ee512015-06-16 10:54:14 -07002793 &self->apply_prog);
2794 ASSERT_EQ(0, ret); /* just us chickens */
2795}
2796
2797/* Make sure restarted syscalls are seen directly as "restart_syscall". */
2798TEST(syscall_restart)
2799{
2800 long ret;
2801 unsigned long msg;
2802 pid_t child_pid;
2803 int pipefd[2];
2804 int status;
2805 siginfo_t info = { };
2806 struct sock_filter filter[] = {
2807 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2808 offsetof(struct seccomp_data, nr)),
2809
2810#ifdef __NR_sigreturn
Thadeu Lima de Souza Cascardod42b8db2020-04-08 20:57:53 -03002811 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_sigreturn, 7, 0),
Kees Cookc99ee512015-06-16 10:54:14 -07002812#endif
Thadeu Lima de Souza Cascardod42b8db2020-04-08 20:57:53 -03002813 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 6, 0),
2814 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_exit, 5, 0),
2815 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_rt_sigreturn, 4, 0),
2816 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_nanosleep, 5, 0),
2817 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_clock_nanosleep, 4, 0),
Kees Cookc99ee512015-06-16 10:54:14 -07002818 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_restart_syscall, 4, 0),
2819
2820 /* Allow __NR_write for easy logging. */
2821 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_write, 0, 1),
2822 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2823 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
Kees Cook256d0af2015-10-06 12:30:25 -07002824 /* The nanosleep jump target. */
2825 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x100),
2826 /* The restart_syscall jump target. */
2827 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x200),
Kees Cookc99ee512015-06-16 10:54:14 -07002828 };
2829 struct sock_fprog prog = {
2830 .len = (unsigned short)ARRAY_SIZE(filter),
2831 .filter = filter,
2832 };
Kees Cook256d0af2015-10-06 12:30:25 -07002833#if defined(__arm__)
2834 struct utsname utsbuf;
2835#endif
Kees Cookc99ee512015-06-16 10:54:14 -07002836
2837 ASSERT_EQ(0, pipe(pipefd));
2838
2839 child_pid = fork();
2840 ASSERT_LE(0, child_pid);
2841 if (child_pid == 0) {
2842 /* Child uses EXPECT not ASSERT to deliver status correctly. */
2843 char buf = ' ';
Kees Cook256d0af2015-10-06 12:30:25 -07002844 struct timespec timeout = { };
Kees Cookc99ee512015-06-16 10:54:14 -07002845
2846 /* Attach parent as tracer and stop. */
2847 EXPECT_EQ(0, ptrace(PTRACE_TRACEME));
2848 EXPECT_EQ(0, raise(SIGSTOP));
2849
2850 EXPECT_EQ(0, close(pipefd[1]));
2851
2852 EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
2853 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
2854 }
2855
2856 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
2857 EXPECT_EQ(0, ret) {
2858 TH_LOG("Failed to install filter!");
2859 }
2860
2861 EXPECT_EQ(1, read(pipefd[0], &buf, 1)) {
2862 TH_LOG("Failed to read() sync from parent");
2863 }
2864 EXPECT_EQ('.', buf) {
2865 TH_LOG("Failed to get sync data from read()");
2866 }
2867
Kees Cook256d0af2015-10-06 12:30:25 -07002868 /* Start nanosleep to be interrupted. */
2869 timeout.tv_sec = 1;
Kees Cookc99ee512015-06-16 10:54:14 -07002870 errno = 0;
Kees Cook256d0af2015-10-06 12:30:25 -07002871 EXPECT_EQ(0, nanosleep(&timeout, NULL)) {
2872 TH_LOG("Call to nanosleep() failed (errno %d)", errno);
Kees Cookc99ee512015-06-16 10:54:14 -07002873 }
2874
2875 /* Read final sync from parent. */
2876 EXPECT_EQ(1, read(pipefd[0], &buf, 1)) {
2877 TH_LOG("Failed final read() from parent");
2878 }
2879 EXPECT_EQ('!', buf) {
2880 TH_LOG("Failed to get final data from read()");
2881 }
2882
2883 /* Directly report the status of our test harness results. */
2884 syscall(__NR_exit, _metadata->passed ? EXIT_SUCCESS
2885 : EXIT_FAILURE);
2886 }
2887 EXPECT_EQ(0, close(pipefd[0]));
2888
2889 /* Attach to child, setup options, and release. */
2890 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
2891 ASSERT_EQ(true, WIFSTOPPED(status));
2892 ASSERT_EQ(0, ptrace(PTRACE_SETOPTIONS, child_pid, NULL,
2893 PTRACE_O_TRACESECCOMP));
2894 ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
2895 ASSERT_EQ(1, write(pipefd[1], ".", 1));
2896
Kees Cook256d0af2015-10-06 12:30:25 -07002897 /* Wait for nanosleep() to start. */
Kees Cookc99ee512015-06-16 10:54:14 -07002898 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
2899 ASSERT_EQ(true, WIFSTOPPED(status));
2900 ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
2901 ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
2902 ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
2903 ASSERT_EQ(0x100, msg);
Thadeu Lima de Souza Cascardod42b8db2020-04-08 20:57:53 -03002904 ret = get_syscall(_metadata, child_pid);
2905 EXPECT_TRUE(ret == __NR_nanosleep || ret == __NR_clock_nanosleep);
Kees Cookc99ee512015-06-16 10:54:14 -07002906
2907 /* Might as well check siginfo for sanity while we're here. */
2908 ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
2909 ASSERT_EQ(SIGTRAP, info.si_signo);
2910 ASSERT_EQ(SIGTRAP | (PTRACE_EVENT_SECCOMP << 8), info.si_code);
2911 EXPECT_EQ(0, info.si_errno);
2912 EXPECT_EQ(getuid(), info.si_uid);
2913 /* Verify signal delivery came from child (seccomp-triggered). */
2914 EXPECT_EQ(child_pid, info.si_pid);
2915
Kees Cook256d0af2015-10-06 12:30:25 -07002916 /* Interrupt nanosleep with SIGSTOP (which we'll need to handle). */
Kees Cookc99ee512015-06-16 10:54:14 -07002917 ASSERT_EQ(0, kill(child_pid, SIGSTOP));
2918 ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
2919 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
2920 ASSERT_EQ(true, WIFSTOPPED(status));
2921 ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
Kees Cookc99ee512015-06-16 10:54:14 -07002922 ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
Kees Cook2bd61ab2018-12-06 15:50:38 -08002923 /*
2924 * There is no siginfo on SIGSTOP any more, so we can't verify
2925 * signal delivery came from parent now (getpid() == info.si_pid).
2926 * https://lkml.kernel.org/r/CAGXu5jJaZAOzP1qFz66tYrtbuywqb+UN2SOA1VLHpCCOiYvYeg@mail.gmail.com
2927 * At least verify the SIGSTOP via PTRACE_GETSIGINFO.
2928 */
2929 EXPECT_EQ(SIGSTOP, info.si_signo);
Kees Cookc99ee512015-06-16 10:54:14 -07002930
Kees Cook256d0af2015-10-06 12:30:25 -07002931 /* Restart nanosleep with SIGCONT, which triggers restart_syscall. */
Kees Cookc99ee512015-06-16 10:54:14 -07002932 ASSERT_EQ(0, kill(child_pid, SIGCONT));
2933 ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
2934 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
2935 ASSERT_EQ(true, WIFSTOPPED(status));
2936 ASSERT_EQ(SIGCONT, WSTOPSIG(status));
2937 ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
2938
2939 /* Wait for restart_syscall() to start. */
2940 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
2941 ASSERT_EQ(true, WIFSTOPPED(status));
2942 ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
2943 ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
2944 ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
Kees Cook256d0af2015-10-06 12:30:25 -07002945
Kees Cookc99ee512015-06-16 10:54:14 -07002946 ASSERT_EQ(0x200, msg);
2947 ret = get_syscall(_metadata, child_pid);
2948#if defined(__arm__)
Kees Cook256d0af2015-10-06 12:30:25 -07002949 /*
2950 * FIXME:
2951 * - native ARM registers do NOT expose true syscall.
2952 * - compat ARM registers on ARM64 DO expose true syscall.
2953 */
2954 ASSERT_EQ(0, uname(&utsbuf));
2955 if (strncmp(utsbuf.machine, "arm", 3) == 0) {
2956 EXPECT_EQ(__NR_nanosleep, ret);
2957 } else
Kees Cookc99ee512015-06-16 10:54:14 -07002958#endif
Kees Cook256d0af2015-10-06 12:30:25 -07002959 {
2960 EXPECT_EQ(__NR_restart_syscall, ret);
2961 }
Kees Cookc99ee512015-06-16 10:54:14 -07002962
Kees Cook256d0af2015-10-06 12:30:25 -07002963 /* Write again to end test. */
Kees Cookc99ee512015-06-16 10:54:14 -07002964 ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
2965 ASSERT_EQ(1, write(pipefd[1], "!", 1));
2966 EXPECT_EQ(0, close(pipefd[1]));
2967
2968 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
2969 if (WIFSIGNALED(status) || WEXITSTATUS(status))
2970 _metadata->passed = 0;
2971}
2972
Tyler Hickse66a3992017-08-11 04:33:56 +00002973TEST_SIGNAL(filter_flag_log, SIGSYS)
2974{
2975 struct sock_filter allow_filter[] = {
2976 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2977 };
2978 struct sock_filter kill_filter[] = {
2979 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2980 offsetof(struct seccomp_data, nr)),
2981 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
2982 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
2983 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2984 };
2985 struct sock_fprog allow_prog = {
2986 .len = (unsigned short)ARRAY_SIZE(allow_filter),
2987 .filter = allow_filter,
2988 };
2989 struct sock_fprog kill_prog = {
2990 .len = (unsigned short)ARRAY_SIZE(kill_filter),
2991 .filter = kill_filter,
2992 };
2993 long ret;
2994 pid_t parent = getppid();
2995
2996 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2997 ASSERT_EQ(0, ret);
2998
2999 /* Verify that the FILTER_FLAG_LOG flag isn't accepted in strict mode */
3000 ret = seccomp(SECCOMP_SET_MODE_STRICT, SECCOMP_FILTER_FLAG_LOG,
3001 &allow_prog);
3002 ASSERT_NE(ENOSYS, errno) {
3003 TH_LOG("Kernel does not support seccomp syscall!");
3004 }
3005 EXPECT_NE(0, ret) {
3006 TH_LOG("Kernel accepted FILTER_FLAG_LOG flag in strict mode!");
3007 }
3008 EXPECT_EQ(EINVAL, errno) {
3009 TH_LOG("Kernel returned unexpected errno for FILTER_FLAG_LOG flag in strict mode!");
3010 }
3011
3012 /* Verify that a simple, permissive filter can be added with no flags */
3013 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &allow_prog);
3014 EXPECT_EQ(0, ret);
3015
3016 /* See if the same filter can be added with the FILTER_FLAG_LOG flag */
3017 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
3018 &allow_prog);
3019 ASSERT_NE(EINVAL, errno) {
3020 TH_LOG("Kernel does not support the FILTER_FLAG_LOG flag!");
3021 }
3022 EXPECT_EQ(0, ret);
3023
3024 /* Ensure that the kill filter works with the FILTER_FLAG_LOG flag */
3025 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
3026 &kill_prog);
3027 EXPECT_EQ(0, ret);
3028
3029 EXPECT_EQ(parent, syscall(__NR_getppid));
3030 /* getpid() should never return. */
3031 EXPECT_EQ(0, syscall(__NR_getpid));
3032}
3033
Tyler Hicksd612b1f2017-08-11 04:33:53 +00003034TEST(get_action_avail)
3035{
Kees Cookfd768752017-08-11 12:53:18 -07003036 __u32 actions[] = { SECCOMP_RET_KILL_THREAD, SECCOMP_RET_TRAP,
Tyler Hicksd612b1f2017-08-11 04:33:53 +00003037 SECCOMP_RET_ERRNO, SECCOMP_RET_TRACE,
Tyler Hicks59f5cf42017-08-11 04:33:57 +00003038 SECCOMP_RET_LOG, SECCOMP_RET_ALLOW };
Tyler Hicksd612b1f2017-08-11 04:33:53 +00003039 __u32 unknown_action = 0x10000000U;
3040 int i;
3041 long ret;
3042
3043 ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[0]);
3044 ASSERT_NE(ENOSYS, errno) {
3045 TH_LOG("Kernel does not support seccomp syscall!");
3046 }
3047 ASSERT_NE(EINVAL, errno) {
3048 TH_LOG("Kernel does not support SECCOMP_GET_ACTION_AVAIL operation!");
3049 }
3050 EXPECT_EQ(ret, 0);
3051
3052 for (i = 0; i < ARRAY_SIZE(actions); i++) {
3053 ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[i]);
3054 EXPECT_EQ(ret, 0) {
3055 TH_LOG("Expected action (0x%X) not available!",
3056 actions[i]);
3057 }
3058 }
3059
3060 /* Check that an unknown action is handled properly (EOPNOTSUPP) */
3061 ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &unknown_action);
3062 EXPECT_EQ(ret, -1);
3063 EXPECT_EQ(errno, EOPNOTSUPP);
3064}
3065
Tycho Andersend057dc42018-02-20 19:47:47 -07003066TEST(get_metadata)
3067{
3068 pid_t pid;
3069 int pipefd[2];
3070 char buf;
3071 struct seccomp_metadata md;
Kees Cook6c3b6d52018-03-15 09:59:16 -07003072 long ret;
Tycho Andersend057dc42018-02-20 19:47:47 -07003073
Tycho Andersen3aa415dd2019-01-18 17:12:15 -07003074 /* Only real root can get metadata. */
3075 if (geteuid()) {
Kees Cook8b1bc882020-07-10 09:24:36 -07003076 SKIP(return, "get_metadata requires real root");
Tycho Andersen3aa415dd2019-01-18 17:12:15 -07003077 return;
3078 }
3079
Tycho Andersend057dc42018-02-20 19:47:47 -07003080 ASSERT_EQ(0, pipe(pipefd));
3081
3082 pid = fork();
3083 ASSERT_GE(pid, 0);
3084 if (pid == 0) {
3085 struct sock_filter filter[] = {
3086 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
3087 };
3088 struct sock_fprog prog = {
3089 .len = (unsigned short)ARRAY_SIZE(filter),
3090 .filter = filter,
3091 };
3092
3093 /* one with log, one without */
Tycho Andersenfb024a02019-01-18 17:12:12 -07003094 EXPECT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER,
Tycho Andersend057dc42018-02-20 19:47:47 -07003095 SECCOMP_FILTER_FLAG_LOG, &prog));
Tycho Andersenfb024a02019-01-18 17:12:12 -07003096 EXPECT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog));
Tycho Andersend057dc42018-02-20 19:47:47 -07003097
Tycho Andersenfb024a02019-01-18 17:12:12 -07003098 EXPECT_EQ(0, close(pipefd[0]));
Tycho Andersend057dc42018-02-20 19:47:47 -07003099 ASSERT_EQ(1, write(pipefd[1], "1", 1));
3100 ASSERT_EQ(0, close(pipefd[1]));
3101
3102 while (1)
3103 sleep(100);
3104 }
3105
3106 ASSERT_EQ(0, close(pipefd[1]));
3107 ASSERT_EQ(1, read(pipefd[0], &buf, 1));
3108
3109 ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid));
3110 ASSERT_EQ(pid, waitpid(pid, NULL, 0));
3111
Kees Cook6c3b6d52018-03-15 09:59:16 -07003112 /* Past here must not use ASSERT or child process is never killed. */
3113
Tycho Andersend057dc42018-02-20 19:47:47 -07003114 md.filter_off = 0;
Kees Cook6c3b6d52018-03-15 09:59:16 -07003115 errno = 0;
3116 ret = ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md);
3117 EXPECT_EQ(sizeof(md), ret) {
3118 if (errno == EINVAL)
Kees Cook8b1bc882020-07-10 09:24:36 -07003119 SKIP(goto skip, "Kernel does not support PTRACE_SECCOMP_GET_METADATA (missing CONFIG_CHECKPOINT_RESTORE?)");
Kees Cook6c3b6d52018-03-15 09:59:16 -07003120 }
3121
Tycho Andersend057dc42018-02-20 19:47:47 -07003122 EXPECT_EQ(md.flags, SECCOMP_FILTER_FLAG_LOG);
3123 EXPECT_EQ(md.filter_off, 0);
3124
3125 md.filter_off = 1;
Kees Cook6c3b6d52018-03-15 09:59:16 -07003126 ret = ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md);
3127 EXPECT_EQ(sizeof(md), ret);
Tycho Andersend057dc42018-02-20 19:47:47 -07003128 EXPECT_EQ(md.flags, 0);
3129 EXPECT_EQ(md.filter_off, 1);
3130
Kees Cook6c3b6d52018-03-15 09:59:16 -07003131skip:
Tycho Andersend057dc42018-02-20 19:47:47 -07003132 ASSERT_EQ(0, kill(pid, SIGKILL));
3133}
3134
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003135static int user_trap_syscall(int nr, unsigned int flags)
3136{
3137 struct sock_filter filter[] = {
3138 BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
3139 offsetof(struct seccomp_data, nr)),
3140 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, nr, 0, 1),
3141 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_USER_NOTIF),
3142 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
3143 };
3144
3145 struct sock_fprog prog = {
3146 .len = (unsigned short)ARRAY_SIZE(filter),
3147 .filter = filter,
3148 };
3149
3150 return seccomp(SECCOMP_SET_MODE_FILTER, flags, &prog);
3151}
3152
Christian Brauner223e6602019-09-20 10:30:06 +02003153#define USER_NOTIF_MAGIC INT_MAX
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003154TEST(user_notification_basic)
3155{
3156 pid_t pid;
3157 long ret;
3158 int status, listener;
3159 struct seccomp_notif req = {};
3160 struct seccomp_notif_resp resp = {};
3161 struct pollfd pollfd;
3162
3163 struct sock_filter filter[] = {
3164 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
3165 };
3166 struct sock_fprog prog = {
3167 .len = (unsigned short)ARRAY_SIZE(filter),
3168 .filter = filter,
3169 };
3170
Tycho Andersenc7140702019-01-18 17:12:16 -07003171 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
3172 ASSERT_EQ(0, ret) {
3173 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
3174 }
3175
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003176 pid = fork();
3177 ASSERT_GE(pid, 0);
3178
3179 /* Check that we get -ENOSYS with no listener attached */
3180 if (pid == 0) {
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003181 if (user_trap_syscall(__NR_getppid, 0) < 0)
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003182 exit(1);
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003183 ret = syscall(__NR_getppid);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003184 exit(ret >= 0 || errno != ENOSYS);
3185 }
3186
3187 EXPECT_EQ(waitpid(pid, &status, 0), pid);
3188 EXPECT_EQ(true, WIFEXITED(status));
3189 EXPECT_EQ(0, WEXITSTATUS(status));
3190
Tycho Andersen0b54b442019-01-18 17:12:13 -07003191 /* Add some no-op filters for grins. */
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003192 EXPECT_EQ(seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog), 0);
3193 EXPECT_EQ(seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog), 0);
3194 EXPECT_EQ(seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog), 0);
3195 EXPECT_EQ(seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog), 0);
3196
3197 /* Check that the basic notification machinery works */
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003198 listener = user_trap_syscall(__NR_getppid,
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003199 SECCOMP_FILTER_FLAG_NEW_LISTENER);
Kees Cook3d244c12019-01-16 16:35:25 -08003200 ASSERT_GE(listener, 0);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003201
3202 /* Installing a second listener in the chain should EBUSY */
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003203 EXPECT_EQ(user_trap_syscall(__NR_getppid,
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003204 SECCOMP_FILTER_FLAG_NEW_LISTENER),
3205 -1);
3206 EXPECT_EQ(errno, EBUSY);
3207
3208 pid = fork();
3209 ASSERT_GE(pid, 0);
3210
3211 if (pid == 0) {
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003212 ret = syscall(__NR_getppid);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003213 exit(ret != USER_NOTIF_MAGIC);
3214 }
3215
3216 pollfd.fd = listener;
3217 pollfd.events = POLLIN | POLLOUT;
3218
3219 EXPECT_GT(poll(&pollfd, 1, -1), 0);
3220 EXPECT_EQ(pollfd.revents, POLLIN);
3221
Sargun Dhillone4ab5cc2019-12-30 12:38:11 -08003222 /* Test that we can't pass garbage to the kernel. */
3223 memset(&req, 0, sizeof(req));
3224 req.pid = -1;
3225 errno = 0;
3226 ret = ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req);
3227 EXPECT_EQ(-1, ret);
3228 EXPECT_EQ(EINVAL, errno);
3229
3230 if (ret) {
3231 req.pid = 0;
3232 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
3233 }
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003234
3235 pollfd.fd = listener;
3236 pollfd.events = POLLIN | POLLOUT;
3237
3238 EXPECT_GT(poll(&pollfd, 1, -1), 0);
3239 EXPECT_EQ(pollfd.revents, POLLOUT);
3240
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003241 EXPECT_EQ(req.data.nr, __NR_getppid);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003242
3243 resp.id = req.id;
3244 resp.error = 0;
3245 resp.val = USER_NOTIF_MAGIC;
3246
3247 /* check that we make sure flags == 0 */
3248 resp.flags = 1;
3249 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1);
3250 EXPECT_EQ(errno, EINVAL);
3251
3252 resp.flags = 0;
3253 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
3254
3255 EXPECT_EQ(waitpid(pid, &status, 0), pid);
3256 EXPECT_EQ(true, WIFEXITED(status));
3257 EXPECT_EQ(0, WEXITSTATUS(status));
3258}
3259
Tycho Andersen51891492020-03-04 11:05:17 -07003260TEST(user_notification_with_tsync)
3261{
3262 int ret;
3263 unsigned int flags;
3264
3265 /* these were exclusive */
3266 flags = SECCOMP_FILTER_FLAG_NEW_LISTENER |
3267 SECCOMP_FILTER_FLAG_TSYNC;
3268 ASSERT_EQ(-1, user_trap_syscall(__NR_getppid, flags));
3269 ASSERT_EQ(EINVAL, errno);
3270
3271 /* but now they're not */
3272 flags |= SECCOMP_FILTER_FLAG_TSYNC_ESRCH;
3273 ret = user_trap_syscall(__NR_getppid, flags);
3274 close(ret);
3275 ASSERT_LE(0, ret);
3276}
3277
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003278TEST(user_notification_kill_in_middle)
3279{
3280 pid_t pid;
3281 long ret;
3282 int listener;
3283 struct seccomp_notif req = {};
3284 struct seccomp_notif_resp resp = {};
3285
Tycho Andersenc7140702019-01-18 17:12:16 -07003286 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
3287 ASSERT_EQ(0, ret) {
3288 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
3289 }
3290
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003291 listener = user_trap_syscall(__NR_getppid,
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003292 SECCOMP_FILTER_FLAG_NEW_LISTENER);
Kees Cook3d244c12019-01-16 16:35:25 -08003293 ASSERT_GE(listener, 0);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003294
3295 /*
3296 * Check that nothing bad happens when we kill the task in the middle
3297 * of a syscall.
3298 */
3299 pid = fork();
3300 ASSERT_GE(pid, 0);
3301
3302 if (pid == 0) {
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003303 ret = syscall(__NR_getppid);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003304 exit(ret != USER_NOTIF_MAGIC);
3305 }
3306
3307 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
3308 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ID_VALID, &req.id), 0);
3309
3310 EXPECT_EQ(kill(pid, SIGKILL), 0);
3311 EXPECT_EQ(waitpid(pid, NULL, 0), pid);
3312
3313 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ID_VALID, &req.id), -1);
3314
3315 resp.id = req.id;
3316 ret = ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp);
3317 EXPECT_EQ(ret, -1);
3318 EXPECT_EQ(errno, ENOENT);
3319}
3320
3321static int handled = -1;
3322
3323static void signal_handler(int signal)
3324{
3325 if (write(handled, "c", 1) != 1)
3326 perror("write from signal");
3327}
3328
3329TEST(user_notification_signal)
3330{
3331 pid_t pid;
3332 long ret;
3333 int status, listener, sk_pair[2];
3334 struct seccomp_notif req = {};
3335 struct seccomp_notif_resp resp = {};
3336 char c;
3337
Tycho Andersenc7140702019-01-18 17:12:16 -07003338 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
3339 ASSERT_EQ(0, ret) {
3340 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
3341 }
3342
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003343 ASSERT_EQ(socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sk_pair), 0);
3344
3345 listener = user_trap_syscall(__NR_gettid,
3346 SECCOMP_FILTER_FLAG_NEW_LISTENER);
Kees Cook3d244c12019-01-16 16:35:25 -08003347 ASSERT_GE(listener, 0);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003348
3349 pid = fork();
3350 ASSERT_GE(pid, 0);
3351
3352 if (pid == 0) {
3353 close(sk_pair[0]);
3354 handled = sk_pair[1];
3355 if (signal(SIGUSR1, signal_handler) == SIG_ERR) {
3356 perror("signal");
3357 exit(1);
3358 }
3359 /*
3360 * ERESTARTSYS behavior is a bit hard to test, because we need
3361 * to rely on a signal that has not yet been handled. Let's at
3362 * least check that the error code gets propagated through, and
3363 * hope that it doesn't break when there is actually a signal :)
3364 */
3365 ret = syscall(__NR_gettid);
3366 exit(!(ret == -1 && errno == 512));
3367 }
3368
3369 close(sk_pair[1]);
3370
Sargun Dhillon88c13f82019-12-28 22:24:49 -08003371 memset(&req, 0, sizeof(req));
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003372 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
3373
3374 EXPECT_EQ(kill(pid, SIGUSR1), 0);
3375
3376 /*
3377 * Make sure the signal really is delivered, which means we're not
3378 * stuck in the user notification code any more and the notification
3379 * should be dead.
3380 */
3381 EXPECT_EQ(read(sk_pair[0], &c, 1), 1);
3382
3383 resp.id = req.id;
3384 resp.error = -EPERM;
3385 resp.val = 0;
3386
3387 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1);
3388 EXPECT_EQ(errno, ENOENT);
3389
Sargun Dhillon88c13f82019-12-28 22:24:49 -08003390 memset(&req, 0, sizeof(req));
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003391 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
3392
3393 resp.id = req.id;
3394 resp.error = -512; /* -ERESTARTSYS */
3395 resp.val = 0;
3396
3397 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
3398
3399 EXPECT_EQ(waitpid(pid, &status, 0), pid);
3400 EXPECT_EQ(true, WIFEXITED(status));
3401 EXPECT_EQ(0, WEXITSTATUS(status));
3402}
3403
3404TEST(user_notification_closed_listener)
3405{
3406 pid_t pid;
3407 long ret;
3408 int status, listener;
3409
Tycho Andersenc7140702019-01-18 17:12:16 -07003410 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
3411 ASSERT_EQ(0, ret) {
3412 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
3413 }
3414
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003415 listener = user_trap_syscall(__NR_getppid,
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003416 SECCOMP_FILTER_FLAG_NEW_LISTENER);
Kees Cook3d244c12019-01-16 16:35:25 -08003417 ASSERT_GE(listener, 0);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003418
3419 /*
3420 * Check that we get an ENOSYS when the listener is closed.
3421 */
3422 pid = fork();
3423 ASSERT_GE(pid, 0);
3424 if (pid == 0) {
3425 close(listener);
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003426 ret = syscall(__NR_getppid);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003427 exit(ret != -1 && errno != ENOSYS);
3428 }
3429
3430 close(listener);
3431
3432 EXPECT_EQ(waitpid(pid, &status, 0), pid);
3433 EXPECT_EQ(true, WIFEXITED(status));
3434 EXPECT_EQ(0, WEXITSTATUS(status));
3435}
3436
3437/*
3438 * Check that a pid in a child namespace still shows up as valid in ours.
3439 */
3440TEST(user_notification_child_pid_ns)
3441{
3442 pid_t pid;
3443 int status, listener;
3444 struct seccomp_notif req = {};
3445 struct seccomp_notif_resp resp = {};
3446
Tycho Andersen30d53a52019-01-18 17:12:17 -07003447 ASSERT_EQ(unshare(CLONE_NEWUSER | CLONE_NEWPID), 0);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003448
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003449 listener = user_trap_syscall(__NR_getppid,
3450 SECCOMP_FILTER_FLAG_NEW_LISTENER);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003451 ASSERT_GE(listener, 0);
3452
3453 pid = fork();
3454 ASSERT_GE(pid, 0);
3455
3456 if (pid == 0)
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003457 exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003458
3459 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
3460 EXPECT_EQ(req.pid, pid);
3461
3462 resp.id = req.id;
3463 resp.error = 0;
3464 resp.val = USER_NOTIF_MAGIC;
3465
3466 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
3467
3468 EXPECT_EQ(waitpid(pid, &status, 0), pid);
3469 EXPECT_EQ(true, WIFEXITED(status));
3470 EXPECT_EQ(0, WEXITSTATUS(status));
3471 close(listener);
3472}
3473
3474/*
3475 * Check that a pid in a sibling (i.e. unrelated) namespace shows up as 0, i.e.
3476 * invalid.
3477 */
3478TEST(user_notification_sibling_pid_ns)
3479{
3480 pid_t pid, pid2;
3481 int status, listener;
3482 struct seccomp_notif req = {};
3483 struct seccomp_notif_resp resp = {};
3484
Tycho Andersenc7140702019-01-18 17:12:16 -07003485 ASSERT_EQ(prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0), 0) {
3486 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
3487 }
3488
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003489 listener = user_trap_syscall(__NR_getppid,
3490 SECCOMP_FILTER_FLAG_NEW_LISTENER);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003491 ASSERT_GE(listener, 0);
3492
3493 pid = fork();
3494 ASSERT_GE(pid, 0);
3495
3496 if (pid == 0) {
3497 ASSERT_EQ(unshare(CLONE_NEWPID), 0);
3498
3499 pid2 = fork();
3500 ASSERT_GE(pid2, 0);
3501
3502 if (pid2 == 0)
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003503 exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003504
3505 EXPECT_EQ(waitpid(pid2, &status, 0), pid2);
3506 EXPECT_EQ(true, WIFEXITED(status));
3507 EXPECT_EQ(0, WEXITSTATUS(status));
3508 exit(WEXITSTATUS(status));
3509 }
3510
3511 /* Create the sibling ns, and sibling in it. */
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003512 ASSERT_EQ(unshare(CLONE_NEWPID), 0);
3513 ASSERT_EQ(errno, 0);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003514
3515 pid2 = fork();
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003516 ASSERT_GE(pid2, 0);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003517
3518 if (pid2 == 0) {
3519 ASSERT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
3520 /*
3521 * The pid should be 0, i.e. the task is in some namespace that
3522 * we can't "see".
3523 */
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003524 EXPECT_EQ(req.pid, 0);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003525
3526 resp.id = req.id;
3527 resp.error = 0;
3528 resp.val = USER_NOTIF_MAGIC;
3529
3530 ASSERT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
3531 exit(0);
3532 }
3533
3534 close(listener);
3535
3536 EXPECT_EQ(waitpid(pid, &status, 0), pid);
3537 EXPECT_EQ(true, WIFEXITED(status));
3538 EXPECT_EQ(0, WEXITSTATUS(status));
3539
3540 EXPECT_EQ(waitpid(pid2, &status, 0), pid2);
3541 EXPECT_EQ(true, WIFEXITED(status));
3542 EXPECT_EQ(0, WEXITSTATUS(status));
3543}
3544
3545TEST(user_notification_fault_recv)
3546{
3547 pid_t pid;
3548 int status, listener;
3549 struct seccomp_notif req = {};
3550 struct seccomp_notif_resp resp = {};
3551
Tycho Andersen30d53a52019-01-18 17:12:17 -07003552 ASSERT_EQ(unshare(CLONE_NEWUSER), 0);
3553
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003554 listener = user_trap_syscall(__NR_getppid,
3555 SECCOMP_FILTER_FLAG_NEW_LISTENER);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003556 ASSERT_GE(listener, 0);
3557
3558 pid = fork();
3559 ASSERT_GE(pid, 0);
3560
3561 if (pid == 0)
Kees Cook9dd3fcb2019-04-11 16:56:31 -07003562 exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003563
3564 /* Do a bad recv() */
3565 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, NULL), -1);
3566 EXPECT_EQ(errno, EFAULT);
3567
3568 /* We should still be able to receive this notification, though. */
3569 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
3570 EXPECT_EQ(req.pid, pid);
3571
3572 resp.id = req.id;
3573 resp.error = 0;
3574 resp.val = USER_NOTIF_MAGIC;
3575
3576 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
3577
3578 EXPECT_EQ(waitpid(pid, &status, 0), pid);
3579 EXPECT_EQ(true, WIFEXITED(status));
3580 EXPECT_EQ(0, WEXITSTATUS(status));
3581}
3582
3583TEST(seccomp_get_notif_sizes)
3584{
3585 struct seccomp_notif_sizes sizes;
3586
Kees Cook3d244c12019-01-16 16:35:25 -08003587 ASSERT_EQ(seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes), 0);
Tycho Andersen6a21cc52018-12-09 11:24:13 -07003588 EXPECT_EQ(sizes.seccomp_notif, sizeof(struct seccomp_notif));
3589 EXPECT_EQ(sizes.seccomp_notif_resp, sizeof(struct seccomp_notif_resp));
3590}
3591
Christian Brauner0eebfed2019-09-20 10:30:07 +02003592static int filecmp(pid_t pid1, pid_t pid2, int fd1, int fd2)
3593{
3594#ifdef __NR_kcmp
3595 return syscall(__NR_kcmp, pid1, pid2, KCMP_FILE, fd1, fd2);
3596#else
3597 errno = ENOSYS;
3598 return -1;
3599#endif
3600}
3601
3602TEST(user_notification_continue)
3603{
3604 pid_t pid;
3605 long ret;
3606 int status, listener;
3607 struct seccomp_notif req = {};
3608 struct seccomp_notif_resp resp = {};
3609 struct pollfd pollfd;
3610
3611 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
3612 ASSERT_EQ(0, ret) {
3613 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
3614 }
3615
3616 listener = user_trap_syscall(__NR_dup, SECCOMP_FILTER_FLAG_NEW_LISTENER);
3617 ASSERT_GE(listener, 0);
3618
3619 pid = fork();
3620 ASSERT_GE(pid, 0);
3621
3622 if (pid == 0) {
3623 int dup_fd, pipe_fds[2];
3624 pid_t self;
3625
3626 ret = pipe(pipe_fds);
3627 if (ret < 0)
3628 exit(1);
3629
3630 dup_fd = dup(pipe_fds[0]);
3631 if (dup_fd < 0)
3632 exit(1);
3633
3634 self = getpid();
3635
3636 ret = filecmp(self, self, pipe_fds[0], dup_fd);
3637 if (ret)
3638 exit(2);
3639
3640 exit(0);
3641 }
3642
3643 pollfd.fd = listener;
3644 pollfd.events = POLLIN | POLLOUT;
3645
3646 EXPECT_GT(poll(&pollfd, 1, -1), 0);
3647 EXPECT_EQ(pollfd.revents, POLLIN);
3648
3649 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
3650
3651 pollfd.fd = listener;
3652 pollfd.events = POLLIN | POLLOUT;
3653
3654 EXPECT_GT(poll(&pollfd, 1, -1), 0);
3655 EXPECT_EQ(pollfd.revents, POLLOUT);
3656
3657 EXPECT_EQ(req.data.nr, __NR_dup);
3658
3659 resp.id = req.id;
3660 resp.flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
3661
3662 /*
3663 * Verify that setting SECCOMP_USER_NOTIF_FLAG_CONTINUE enforces other
3664 * args be set to 0.
3665 */
3666 resp.error = 0;
3667 resp.val = USER_NOTIF_MAGIC;
3668 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1);
3669 EXPECT_EQ(errno, EINVAL);
3670
3671 resp.error = USER_NOTIF_MAGIC;
3672 resp.val = 0;
3673 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1);
3674 EXPECT_EQ(errno, EINVAL);
3675
3676 resp.error = 0;
3677 resp.val = 0;
3678 EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0) {
3679 if (errno == EINVAL)
Kees Cook8b1bc882020-07-10 09:24:36 -07003680 SKIP(goto skip, "Kernel does not support SECCOMP_USER_NOTIF_FLAG_CONTINUE");
Christian Brauner0eebfed2019-09-20 10:30:07 +02003681 }
3682
3683skip:
3684 EXPECT_EQ(waitpid(pid, &status, 0), pid);
3685 EXPECT_EQ(true, WIFEXITED(status));
3686 EXPECT_EQ(0, WEXITSTATUS(status)) {
3687 if (WEXITSTATUS(status) == 2) {
Kees Cook8b1bc882020-07-10 09:24:36 -07003688 SKIP(return, "Kernel does not support kcmp() syscall");
Christian Brauner0eebfed2019-09-20 10:30:07 +02003689 return;
3690 }
3691 }
3692}
3693
Kees Cookc99ee512015-06-16 10:54:14 -07003694/*
3695 * TODO:
3696 * - add microbenchmarks
3697 * - expand NNP testing
3698 * - better arch-specific TRACE and TRAP handlers.
3699 * - endianness checking when appropriate
3700 * - 64-bit arg prodding
3701 * - arch value testing (x86 modes especially)
Tyler Hickse66a3992017-08-11 04:33:56 +00003702 * - verify that FILTER_FLAG_LOG filters generate log messages
Tyler Hicks59f5cf42017-08-11 04:33:57 +00003703 * - verify that RET_LOG generates log messages
Kees Cookc99ee512015-06-16 10:54:14 -07003704 * - ...
3705 */
3706
3707TEST_HARNESS_MAIN