18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Test code for seccomp bpf.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define _GNU_SOURCE
98c2ecf20Sopenharmony_ci#include <sys/types.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/*
128c2ecf20Sopenharmony_ci * glibc 2.26 and later have SIGSYS in siginfo_t. Before that,
138c2ecf20Sopenharmony_ci * we need to use the kernel's siginfo.h file and trick glibc
148c2ecf20Sopenharmony_ci * into accepting it.
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci#if !__GLIBC_PREREQ(2, 26)
178c2ecf20Sopenharmony_ci# include <asm/siginfo.h>
188c2ecf20Sopenharmony_ci# define __have_siginfo_t 1
198c2ecf20Sopenharmony_ci# define __have_sigval_t 1
208c2ecf20Sopenharmony_ci# define __have_sigevent_t 1
218c2ecf20Sopenharmony_ci#endif
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include <errno.h>
248c2ecf20Sopenharmony_ci#include <linux/filter.h>
258c2ecf20Sopenharmony_ci#include <sys/prctl.h>
268c2ecf20Sopenharmony_ci#include <sys/ptrace.h>
278c2ecf20Sopenharmony_ci#include <sys/user.h>
288c2ecf20Sopenharmony_ci#include <linux/prctl.h>
298c2ecf20Sopenharmony_ci#include <linux/ptrace.h>
308c2ecf20Sopenharmony_ci#include <linux/seccomp.h>
318c2ecf20Sopenharmony_ci#include <pthread.h>
328c2ecf20Sopenharmony_ci#include <semaphore.h>
338c2ecf20Sopenharmony_ci#include <signal.h>
348c2ecf20Sopenharmony_ci#include <stddef.h>
358c2ecf20Sopenharmony_ci#include <stdbool.h>
368c2ecf20Sopenharmony_ci#include <string.h>
378c2ecf20Sopenharmony_ci#include <time.h>
388c2ecf20Sopenharmony_ci#include <limits.h>
398c2ecf20Sopenharmony_ci#include <linux/elf.h>
408c2ecf20Sopenharmony_ci#include <sys/uio.h>
418c2ecf20Sopenharmony_ci#include <sys/utsname.h>
428c2ecf20Sopenharmony_ci#include <sys/fcntl.h>
438c2ecf20Sopenharmony_ci#include <sys/mman.h>
448c2ecf20Sopenharmony_ci#include <sys/times.h>
458c2ecf20Sopenharmony_ci#include <sys/socket.h>
468c2ecf20Sopenharmony_ci#include <sys/ioctl.h>
478c2ecf20Sopenharmony_ci#include <linux/kcmp.h>
488c2ecf20Sopenharmony_ci#include <sys/resource.h>
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#include <unistd.h>
518c2ecf20Sopenharmony_ci#include <sys/syscall.h>
528c2ecf20Sopenharmony_ci#include <poll.h>
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#include "../kselftest_harness.h"
558c2ecf20Sopenharmony_ci#include "../clone3/clone3_selftests.h"
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/* Attempt to de-conflict with the selftests tree. */
588c2ecf20Sopenharmony_ci#ifndef SKIP
598c2ecf20Sopenharmony_ci#define SKIP(s, ...)	XFAIL(s, ##__VA_ARGS__)
608c2ecf20Sopenharmony_ci#endif
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#ifndef PR_SET_PTRACER
638c2ecf20Sopenharmony_ci# define PR_SET_PTRACER 0x59616d61
648c2ecf20Sopenharmony_ci#endif
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#ifndef PR_SET_NO_NEW_PRIVS
678c2ecf20Sopenharmony_ci#define PR_SET_NO_NEW_PRIVS 38
688c2ecf20Sopenharmony_ci#define PR_GET_NO_NEW_PRIVS 39
698c2ecf20Sopenharmony_ci#endif
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci#ifndef PR_SECCOMP_EXT
728c2ecf20Sopenharmony_ci#define PR_SECCOMP_EXT 43
738c2ecf20Sopenharmony_ci#endif
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#ifndef SECCOMP_EXT_ACT
768c2ecf20Sopenharmony_ci#define SECCOMP_EXT_ACT 1
778c2ecf20Sopenharmony_ci#endif
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci#ifndef SECCOMP_EXT_ACT_TSYNC
808c2ecf20Sopenharmony_ci#define SECCOMP_EXT_ACT_TSYNC 1
818c2ecf20Sopenharmony_ci#endif
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#ifndef SECCOMP_MODE_STRICT
848c2ecf20Sopenharmony_ci#define SECCOMP_MODE_STRICT 1
858c2ecf20Sopenharmony_ci#endif
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#ifndef SECCOMP_MODE_FILTER
888c2ecf20Sopenharmony_ci#define SECCOMP_MODE_FILTER 2
898c2ecf20Sopenharmony_ci#endif
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci#ifndef SECCOMP_RET_ALLOW
928c2ecf20Sopenharmony_cistruct seccomp_data {
938c2ecf20Sopenharmony_ci	int nr;
948c2ecf20Sopenharmony_ci	__u32 arch;
958c2ecf20Sopenharmony_ci	__u64 instruction_pointer;
968c2ecf20Sopenharmony_ci	__u64 args[6];
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci#endif
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#ifndef SECCOMP_RET_KILL_PROCESS
1018c2ecf20Sopenharmony_ci#define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */
1028c2ecf20Sopenharmony_ci#define SECCOMP_RET_KILL_THREAD	 0x00000000U /* kill the thread */
1038c2ecf20Sopenharmony_ci#endif
1048c2ecf20Sopenharmony_ci#ifndef SECCOMP_RET_KILL
1058c2ecf20Sopenharmony_ci#define SECCOMP_RET_KILL	 SECCOMP_RET_KILL_THREAD
1068c2ecf20Sopenharmony_ci#define SECCOMP_RET_TRAP	 0x00030000U /* disallow and force a SIGSYS */
1078c2ecf20Sopenharmony_ci#define SECCOMP_RET_ERRNO	 0x00050000U /* returns an errno */
1088c2ecf20Sopenharmony_ci#define SECCOMP_RET_TRACE	 0x7ff00000U /* pass to a tracer or disallow */
1098c2ecf20Sopenharmony_ci#define SECCOMP_RET_ALLOW	 0x7fff0000U /* allow */
1108c2ecf20Sopenharmony_ci#endif
1118c2ecf20Sopenharmony_ci#ifndef SECCOMP_RET_LOG
1128c2ecf20Sopenharmony_ci#define SECCOMP_RET_LOG		 0x7ffc0000U /* allow after logging */
1138c2ecf20Sopenharmony_ci#endif
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci#ifndef __NR_seccomp
1168c2ecf20Sopenharmony_ci# if defined(__i386__)
1178c2ecf20Sopenharmony_ci#  define __NR_seccomp 354
1188c2ecf20Sopenharmony_ci# elif defined(__x86_64__)
1198c2ecf20Sopenharmony_ci#  define __NR_seccomp 317
1208c2ecf20Sopenharmony_ci# elif defined(__arm__)
1218c2ecf20Sopenharmony_ci#  define __NR_seccomp 383
1228c2ecf20Sopenharmony_ci# elif defined(__aarch64__)
1238c2ecf20Sopenharmony_ci#  define __NR_seccomp 277
1248c2ecf20Sopenharmony_ci# elif defined(__riscv)
1258c2ecf20Sopenharmony_ci#  define __NR_seccomp 277
1268c2ecf20Sopenharmony_ci# elif defined(__csky__)
1278c2ecf20Sopenharmony_ci#  define __NR_seccomp 277
1288c2ecf20Sopenharmony_ci# elif defined(__loongarch__)
1298c2ecf20Sopenharmony_ci#  define __NR_seccomp 277
1308c2ecf20Sopenharmony_ci# elif defined(__hppa__)
1318c2ecf20Sopenharmony_ci#  define __NR_seccomp 338
1328c2ecf20Sopenharmony_ci# elif defined(__powerpc__)
1338c2ecf20Sopenharmony_ci#  define __NR_seccomp 358
1348c2ecf20Sopenharmony_ci# elif defined(__s390__)
1358c2ecf20Sopenharmony_ci#  define __NR_seccomp 348
1368c2ecf20Sopenharmony_ci# elif defined(__xtensa__)
1378c2ecf20Sopenharmony_ci#  define __NR_seccomp 337
1388c2ecf20Sopenharmony_ci# elif defined(__sh__)
1398c2ecf20Sopenharmony_ci#  define __NR_seccomp 372
1408c2ecf20Sopenharmony_ci# else
1418c2ecf20Sopenharmony_ci#  warning "seccomp syscall number unknown for this architecture"
1428c2ecf20Sopenharmony_ci#  define __NR_seccomp 0xffff
1438c2ecf20Sopenharmony_ci# endif
1448c2ecf20Sopenharmony_ci#endif
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci#ifndef SECCOMP_SET_MODE_STRICT
1478c2ecf20Sopenharmony_ci#define SECCOMP_SET_MODE_STRICT 0
1488c2ecf20Sopenharmony_ci#endif
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci#ifndef SECCOMP_SET_MODE_FILTER
1518c2ecf20Sopenharmony_ci#define SECCOMP_SET_MODE_FILTER 1
1528c2ecf20Sopenharmony_ci#endif
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci#ifndef SECCOMP_GET_ACTION_AVAIL
1558c2ecf20Sopenharmony_ci#define SECCOMP_GET_ACTION_AVAIL 2
1568c2ecf20Sopenharmony_ci#endif
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci#ifndef SECCOMP_GET_NOTIF_SIZES
1598c2ecf20Sopenharmony_ci#define SECCOMP_GET_NOTIF_SIZES 3
1608c2ecf20Sopenharmony_ci#endif
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci#ifndef SECCOMP_FILTER_FLAG_TSYNC
1638c2ecf20Sopenharmony_ci#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
1648c2ecf20Sopenharmony_ci#endif
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci#ifndef SECCOMP_FILTER_FLAG_LOG
1678c2ecf20Sopenharmony_ci#define SECCOMP_FILTER_FLAG_LOG (1UL << 1)
1688c2ecf20Sopenharmony_ci#endif
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci#ifndef SECCOMP_FILTER_FLAG_SPEC_ALLOW
1718c2ecf20Sopenharmony_ci#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
1728c2ecf20Sopenharmony_ci#endif
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci#ifndef PTRACE_SECCOMP_GET_METADATA
1758c2ecf20Sopenharmony_ci#define PTRACE_SECCOMP_GET_METADATA	0x420d
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistruct seccomp_metadata {
1788c2ecf20Sopenharmony_ci	__u64 filter_off;       /* Input: which filter */
1798c2ecf20Sopenharmony_ci	__u64 flags;             /* Output: filter's flags */
1808c2ecf20Sopenharmony_ci};
1818c2ecf20Sopenharmony_ci#endif
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci#ifndef SECCOMP_FILTER_FLAG_NEW_LISTENER
1848c2ecf20Sopenharmony_ci#define SECCOMP_FILTER_FLAG_NEW_LISTENER	(1UL << 3)
1858c2ecf20Sopenharmony_ci#endif
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci#ifndef SECCOMP_RET_USER_NOTIF
1888c2ecf20Sopenharmony_ci#define SECCOMP_RET_USER_NOTIF 0x7fc00000U
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci#define SECCOMP_IOC_MAGIC		'!'
1918c2ecf20Sopenharmony_ci#define SECCOMP_IO(nr)			_IO(SECCOMP_IOC_MAGIC, nr)
1928c2ecf20Sopenharmony_ci#define SECCOMP_IOR(nr, type)		_IOR(SECCOMP_IOC_MAGIC, nr, type)
1938c2ecf20Sopenharmony_ci#define SECCOMP_IOW(nr, type)		_IOW(SECCOMP_IOC_MAGIC, nr, type)
1948c2ecf20Sopenharmony_ci#define SECCOMP_IOWR(nr, type)		_IOWR(SECCOMP_IOC_MAGIC, nr, type)
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci/* Flags for seccomp notification fd ioctl. */
1978c2ecf20Sopenharmony_ci#define SECCOMP_IOCTL_NOTIF_RECV	SECCOMP_IOWR(0, struct seccomp_notif)
1988c2ecf20Sopenharmony_ci#define SECCOMP_IOCTL_NOTIF_SEND	SECCOMP_IOWR(1,	\
1998c2ecf20Sopenharmony_ci						struct seccomp_notif_resp)
2008c2ecf20Sopenharmony_ci#define SECCOMP_IOCTL_NOTIF_ID_VALID	SECCOMP_IOW(2, __u64)
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistruct seccomp_notif {
2038c2ecf20Sopenharmony_ci	__u64 id;
2048c2ecf20Sopenharmony_ci	__u32 pid;
2058c2ecf20Sopenharmony_ci	__u32 flags;
2068c2ecf20Sopenharmony_ci	struct seccomp_data data;
2078c2ecf20Sopenharmony_ci};
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cistruct seccomp_notif_resp {
2108c2ecf20Sopenharmony_ci	__u64 id;
2118c2ecf20Sopenharmony_ci	__s64 val;
2128c2ecf20Sopenharmony_ci	__s32 error;
2138c2ecf20Sopenharmony_ci	__u32 flags;
2148c2ecf20Sopenharmony_ci};
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistruct seccomp_notif_sizes {
2178c2ecf20Sopenharmony_ci	__u16 seccomp_notif;
2188c2ecf20Sopenharmony_ci	__u16 seccomp_notif_resp;
2198c2ecf20Sopenharmony_ci	__u16 seccomp_data;
2208c2ecf20Sopenharmony_ci};
2218c2ecf20Sopenharmony_ci#endif
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci#ifndef SECCOMP_IOCTL_NOTIF_ADDFD
2248c2ecf20Sopenharmony_ci/* On success, the return value is the remote process's added fd number */
2258c2ecf20Sopenharmony_ci#define SECCOMP_IOCTL_NOTIF_ADDFD	SECCOMP_IOW(3,	\
2268c2ecf20Sopenharmony_ci						struct seccomp_notif_addfd)
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/* valid flags for seccomp_notif_addfd */
2298c2ecf20Sopenharmony_ci#define SECCOMP_ADDFD_FLAG_SETFD	(1UL << 0) /* Specify remote fd */
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistruct seccomp_notif_addfd {
2328c2ecf20Sopenharmony_ci	__u64 id;
2338c2ecf20Sopenharmony_ci	__u32 flags;
2348c2ecf20Sopenharmony_ci	__u32 srcfd;
2358c2ecf20Sopenharmony_ci	__u32 newfd;
2368c2ecf20Sopenharmony_ci	__u32 newfd_flags;
2378c2ecf20Sopenharmony_ci};
2388c2ecf20Sopenharmony_ci#endif
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cistruct seccomp_notif_addfd_small {
2418c2ecf20Sopenharmony_ci	__u64 id;
2428c2ecf20Sopenharmony_ci	char weird[4];
2438c2ecf20Sopenharmony_ci};
2448c2ecf20Sopenharmony_ci#define SECCOMP_IOCTL_NOTIF_ADDFD_SMALL	\
2458c2ecf20Sopenharmony_ci	SECCOMP_IOW(3, struct seccomp_notif_addfd_small)
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistruct seccomp_notif_addfd_big {
2488c2ecf20Sopenharmony_ci	union {
2498c2ecf20Sopenharmony_ci		struct seccomp_notif_addfd addfd;
2508c2ecf20Sopenharmony_ci		char buf[sizeof(struct seccomp_notif_addfd) + 8];
2518c2ecf20Sopenharmony_ci	};
2528c2ecf20Sopenharmony_ci};
2538c2ecf20Sopenharmony_ci#define SECCOMP_IOCTL_NOTIF_ADDFD_BIG	\
2548c2ecf20Sopenharmony_ci	SECCOMP_IOWR(3, struct seccomp_notif_addfd_big)
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci#ifndef PTRACE_EVENTMSG_SYSCALL_ENTRY
2578c2ecf20Sopenharmony_ci#define PTRACE_EVENTMSG_SYSCALL_ENTRY	1
2588c2ecf20Sopenharmony_ci#define PTRACE_EVENTMSG_SYSCALL_EXIT	2
2598c2ecf20Sopenharmony_ci#endif
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci#ifndef SECCOMP_USER_NOTIF_FLAG_CONTINUE
2628c2ecf20Sopenharmony_ci#define SECCOMP_USER_NOTIF_FLAG_CONTINUE 0x00000001
2638c2ecf20Sopenharmony_ci#endif
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci#ifndef SECCOMP_FILTER_FLAG_TSYNC_ESRCH
2668c2ecf20Sopenharmony_ci#define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4)
2678c2ecf20Sopenharmony_ci#endif
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci#ifndef seccomp
2708c2ecf20Sopenharmony_ciint seccomp(unsigned int op, unsigned int flags, void *args)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	errno = 0;
2738c2ecf20Sopenharmony_ci	return syscall(__NR_seccomp, op, flags, args);
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci#endif
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci#if __BYTE_ORDER == __LITTLE_ENDIAN
2788c2ecf20Sopenharmony_ci#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
2798c2ecf20Sopenharmony_ci#elif __BYTE_ORDER == __BIG_ENDIAN
2808c2ecf20Sopenharmony_ci#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]) + sizeof(__u32))
2818c2ecf20Sopenharmony_ci#else
2828c2ecf20Sopenharmony_ci#error "wut? Unknown __BYTE_ORDER?!"
2838c2ecf20Sopenharmony_ci#endif
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci#define SIBLING_EXIT_UNKILLED	0xbadbeef
2868c2ecf20Sopenharmony_ci#define SIBLING_EXIT_FAILURE	0xbadface
2878c2ecf20Sopenharmony_ci#define SIBLING_EXIT_NEWPRIVS	0xbadfeed
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_cistatic int __filecmp(pid_t pid1, pid_t pid2, int fd1, int fd2)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci#ifdef __NR_kcmp
2928c2ecf20Sopenharmony_ci	errno = 0;
2938c2ecf20Sopenharmony_ci	return syscall(__NR_kcmp, pid1, pid2, KCMP_FILE, fd1, fd2);
2948c2ecf20Sopenharmony_ci#else
2958c2ecf20Sopenharmony_ci	errno = ENOSYS;
2968c2ecf20Sopenharmony_ci	return -1;
2978c2ecf20Sopenharmony_ci#endif
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci/* Have TH_LOG report actual location filecmp() is used. */
3018c2ecf20Sopenharmony_ci#define filecmp(pid1, pid2, fd1, fd2)	({		\
3028c2ecf20Sopenharmony_ci	int _ret;					\
3038c2ecf20Sopenharmony_ci							\
3048c2ecf20Sopenharmony_ci	_ret = __filecmp(pid1, pid2, fd1, fd2);		\
3058c2ecf20Sopenharmony_ci	if (_ret != 0) {				\
3068c2ecf20Sopenharmony_ci		if (_ret < 0 && errno == ENOSYS) {	\
3078c2ecf20Sopenharmony_ci			TH_LOG("kcmp() syscall missing (test is less accurate)");\
3088c2ecf20Sopenharmony_ci			_ret = 0;			\
3098c2ecf20Sopenharmony_ci		}					\
3108c2ecf20Sopenharmony_ci	}						\
3118c2ecf20Sopenharmony_ci	_ret; })
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ciTEST(kcmp)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	int ret;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	ret = __filecmp(getpid(), getpid(), 1, 1);
3188c2ecf20Sopenharmony_ci	EXPECT_EQ(ret, 0);
3198c2ecf20Sopenharmony_ci	if (ret != 0 && errno == ENOSYS)
3208c2ecf20Sopenharmony_ci		SKIP(return, "Kernel does not support kcmp() (missing CONFIG_KCMP?)");
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ciTEST(mode_strict_support)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	long ret;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, NULL, NULL);
3288c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
3298c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support CONFIG_SECCOMP");
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci	syscall(__NR_exit, 0);
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ciTEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL)
3358c2ecf20Sopenharmony_ci{
3368c2ecf20Sopenharmony_ci	long ret;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, NULL, NULL);
3398c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
3408c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support CONFIG_SECCOMP");
3418c2ecf20Sopenharmony_ci	}
3428c2ecf20Sopenharmony_ci	syscall(__NR_prctl, PR_SET_SECCOMP, SECCOMP_MODE_FILTER,
3438c2ecf20Sopenharmony_ci		NULL, NULL, NULL);
3448c2ecf20Sopenharmony_ci	EXPECT_FALSE(true) {
3458c2ecf20Sopenharmony_ci		TH_LOG("Unreachable!");
3468c2ecf20Sopenharmony_ci	}
3478c2ecf20Sopenharmony_ci}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci/* Note! This doesn't test no new privs behavior */
3508c2ecf20Sopenharmony_ciTEST(no_new_privs_support)
3518c2ecf20Sopenharmony_ci{
3528c2ecf20Sopenharmony_ci	long ret;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
3558c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret) {
3568c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
3578c2ecf20Sopenharmony_ci	}
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci/* Tests kernel support by checking for a copy_from_user() fault on NULL. */
3618c2ecf20Sopenharmony_ciTEST(mode_filter_support)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	long ret;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
3668c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
3678c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
3688c2ecf20Sopenharmony_ci	}
3698c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, NULL, NULL);
3708c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, ret);
3718c2ecf20Sopenharmony_ci	EXPECT_EQ(EFAULT, errno) {
3728c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support CONFIG_SECCOMP_FILTER!");
3738c2ecf20Sopenharmony_ci	}
3748c2ecf20Sopenharmony_ci}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ciTEST(mode_filter_without_nnp)
3778c2ecf20Sopenharmony_ci{
3788c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
3798c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
3808c2ecf20Sopenharmony_ci	};
3818c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
3828c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
3838c2ecf20Sopenharmony_ci		.filter = filter,
3848c2ecf20Sopenharmony_ci	};
3858c2ecf20Sopenharmony_ci	long ret;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	ret = prctl(PR_GET_NO_NEW_PRIVS, 0, NULL, 0, 0);
3888c2ecf20Sopenharmony_ci	ASSERT_LE(0, ret) {
3898c2ecf20Sopenharmony_ci		TH_LOG("Expected 0 or unsupported for NO_NEW_PRIVS");
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci	errno = 0;
3928c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
3938c2ecf20Sopenharmony_ci	/* Succeeds with CAP_SYS_ADMIN, fails without */
3948c2ecf20Sopenharmony_ci	/* TODO(wad) check caps not euid */
3958c2ecf20Sopenharmony_ci	if (geteuid()) {
3968c2ecf20Sopenharmony_ci		EXPECT_EQ(-1, ret);
3978c2ecf20Sopenharmony_ci		EXPECT_EQ(EACCES, errno);
3988c2ecf20Sopenharmony_ci	} else {
3998c2ecf20Sopenharmony_ci		EXPECT_EQ(0, ret);
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci#define MAX_INSNS_PER_PATH 32768
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ciTEST(filter_size_limits)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	int i;
4088c2ecf20Sopenharmony_ci	int count = BPF_MAXINSNS + 1;
4098c2ecf20Sopenharmony_ci	struct sock_filter allow[] = {
4108c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
4118c2ecf20Sopenharmony_ci	};
4128c2ecf20Sopenharmony_ci	struct sock_filter *filter;
4138c2ecf20Sopenharmony_ci	struct sock_fprog prog = { };
4148c2ecf20Sopenharmony_ci	long ret;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	filter = calloc(count, sizeof(*filter));
4178c2ecf20Sopenharmony_ci	ASSERT_NE(NULL, filter);
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++)
4208c2ecf20Sopenharmony_ci		filter[i] = allow[0];
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
4238c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	prog.filter = filter;
4268c2ecf20Sopenharmony_ci	prog.len = count;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* Too many filter instructions in a single filter. */
4298c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
4308c2ecf20Sopenharmony_ci	ASSERT_NE(0, ret) {
4318c2ecf20Sopenharmony_ci		TH_LOG("Installing %d insn filter was allowed", prog.len);
4328c2ecf20Sopenharmony_ci	}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	/* One less is okay, though. */
4358c2ecf20Sopenharmony_ci	prog.len -= 1;
4368c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
4378c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
4388c2ecf20Sopenharmony_ci		TH_LOG("Installing %d insn filter wasn't allowed", prog.len);
4398c2ecf20Sopenharmony_ci	}
4408c2ecf20Sopenharmony_ci}
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ciTEST(filter_chain_limits)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	int i;
4458c2ecf20Sopenharmony_ci	int count = BPF_MAXINSNS;
4468c2ecf20Sopenharmony_ci	struct sock_filter allow[] = {
4478c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
4488c2ecf20Sopenharmony_ci	};
4498c2ecf20Sopenharmony_ci	struct sock_filter *filter;
4508c2ecf20Sopenharmony_ci	struct sock_fprog prog = { };
4518c2ecf20Sopenharmony_ci	long ret;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	filter = calloc(count, sizeof(*filter));
4548c2ecf20Sopenharmony_ci	ASSERT_NE(NULL, filter);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++)
4578c2ecf20Sopenharmony_ci		filter[i] = allow[0];
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
4608c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	prog.filter = filter;
4638c2ecf20Sopenharmony_ci	prog.len = 1;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
4668c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	prog.len = count;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	/* Too many total filter instructions. */
4718c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_INSNS_PER_PATH; i++) {
4728c2ecf20Sopenharmony_ci		ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
4738c2ecf20Sopenharmony_ci		if (ret != 0)
4748c2ecf20Sopenharmony_ci			break;
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci	ASSERT_NE(0, ret) {
4778c2ecf20Sopenharmony_ci		TH_LOG("Allowed %d %d-insn filters (total with penalties:%d)",
4788c2ecf20Sopenharmony_ci		       i, count, i * (count + 4));
4798c2ecf20Sopenharmony_ci	}
4808c2ecf20Sopenharmony_ci}
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ciTEST(mode_filter_cannot_move_to_strict)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
4858c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
4868c2ecf20Sopenharmony_ci	};
4878c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
4888c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
4898c2ecf20Sopenharmony_ci		.filter = filter,
4908c2ecf20Sopenharmony_ci	};
4918c2ecf20Sopenharmony_ci	long ret;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
4948c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
4978c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, 0, 0);
5008c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, ret);
5018c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno);
5028c2ecf20Sopenharmony_ci}
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ciTEST(mode_filter_get_seccomp)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
5088c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
5098c2ecf20Sopenharmony_ci	};
5108c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
5118c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
5128c2ecf20Sopenharmony_ci		.filter = filter,
5138c2ecf20Sopenharmony_ci	};
5148c2ecf20Sopenharmony_ci	long ret;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
5178c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	ret = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
5208c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
5238c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	ret = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
5268c2ecf20Sopenharmony_ci	EXPECT_EQ(2, ret);
5278c2ecf20Sopenharmony_ci}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ciTEST(ALLOW_all)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
5338c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
5348c2ecf20Sopenharmony_ci	};
5358c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
5368c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
5378c2ecf20Sopenharmony_ci		.filter = filter,
5388c2ecf20Sopenharmony_ci	};
5398c2ecf20Sopenharmony_ci	long ret;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
5428c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
5458c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
5468c2ecf20Sopenharmony_ci}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ciTEST(empty_prog)
5498c2ecf20Sopenharmony_ci{
5508c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
5518c2ecf20Sopenharmony_ci	};
5528c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
5538c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
5548c2ecf20Sopenharmony_ci		.filter = filter,
5558c2ecf20Sopenharmony_ci	};
5568c2ecf20Sopenharmony_ci	long ret;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
5598c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
5628c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, ret);
5638c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno);
5648c2ecf20Sopenharmony_ci}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ciTEST(log_all)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
5698c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
5708c2ecf20Sopenharmony_ci	};
5718c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
5728c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
5738c2ecf20Sopenharmony_ci		.filter = filter,
5748c2ecf20Sopenharmony_ci	};
5758c2ecf20Sopenharmony_ci	long ret;
5768c2ecf20Sopenharmony_ci	pid_t parent = getppid();
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
5798c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
5828c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	/* getppid() should succeed and be logged (no check for logging) */
5858c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
5868c2ecf20Sopenharmony_ci}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ciTEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
5918c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, 0x10000000U),
5928c2ecf20Sopenharmony_ci	};
5938c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
5948c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
5958c2ecf20Sopenharmony_ci		.filter = filter,
5968c2ecf20Sopenharmony_ci	};
5978c2ecf20Sopenharmony_ci	long ret;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
6008c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
6038c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
6048c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_getpid)) {
6058c2ecf20Sopenharmony_ci		TH_LOG("getpid() shouldn't ever return");
6068c2ecf20Sopenharmony_ci	}
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci/* return code >= 0x80000000 is unused. */
6108c2ecf20Sopenharmony_ciTEST_SIGNAL(unknown_ret_is_kill_above_allow, SIGSYS)
6118c2ecf20Sopenharmony_ci{
6128c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
6138c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, 0x90000000U),
6148c2ecf20Sopenharmony_ci	};
6158c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
6168c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
6178c2ecf20Sopenharmony_ci		.filter = filter,
6188c2ecf20Sopenharmony_ci	};
6198c2ecf20Sopenharmony_ci	long ret;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
6228c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
6258c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
6268c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_getpid)) {
6278c2ecf20Sopenharmony_ci		TH_LOG("getpid() shouldn't ever return");
6288c2ecf20Sopenharmony_ci	}
6298c2ecf20Sopenharmony_ci}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ciTEST_SIGNAL(KILL_all, SIGSYS)
6328c2ecf20Sopenharmony_ci{
6338c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
6348c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
6358c2ecf20Sopenharmony_ci	};
6368c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
6378c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
6388c2ecf20Sopenharmony_ci		.filter = filter,
6398c2ecf20Sopenharmony_ci	};
6408c2ecf20Sopenharmony_ci	long ret;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
6438c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
6468c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
6478c2ecf20Sopenharmony_ci}
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ciTEST_SIGNAL(KILL_one, SIGSYS)
6508c2ecf20Sopenharmony_ci{
6518c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
6528c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
6538c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
6548c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
6558c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
6568c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
6578c2ecf20Sopenharmony_ci	};
6588c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
6598c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
6608c2ecf20Sopenharmony_ci		.filter = filter,
6618c2ecf20Sopenharmony_ci	};
6628c2ecf20Sopenharmony_ci	long ret;
6638c2ecf20Sopenharmony_ci	pid_t parent = getppid();
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
6668c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
6698c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
6728c2ecf20Sopenharmony_ci	/* getpid() should never return. */
6738c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_getpid));
6748c2ecf20Sopenharmony_ci}
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ciTEST_SIGNAL(KILL_one_arg_one, SIGSYS)
6778c2ecf20Sopenharmony_ci{
6788c2ecf20Sopenharmony_ci	void *fatal_address;
6798c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
6808c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
6818c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
6828c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_times, 1, 0),
6838c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
6848c2ecf20Sopenharmony_ci		/* Only both with lower 32-bit for now. */
6858c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(0)),
6868c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K,
6878c2ecf20Sopenharmony_ci			(unsigned long)&fatal_address, 0, 1),
6888c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
6898c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
6908c2ecf20Sopenharmony_ci	};
6918c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
6928c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
6938c2ecf20Sopenharmony_ci		.filter = filter,
6948c2ecf20Sopenharmony_ci	};
6958c2ecf20Sopenharmony_ci	long ret;
6968c2ecf20Sopenharmony_ci	pid_t parent = getppid();
6978c2ecf20Sopenharmony_ci	struct tms timebuf;
6988c2ecf20Sopenharmony_ci	clock_t clock = times(&timebuf);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
7018c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
7048c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
7078c2ecf20Sopenharmony_ci	EXPECT_LE(clock, syscall(__NR_times, &timebuf));
7088c2ecf20Sopenharmony_ci	/* times() should never return. */
7098c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_times, &fatal_address));
7108c2ecf20Sopenharmony_ci}
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ciTEST_SIGNAL(KILL_one_arg_six, SIGSYS)
7138c2ecf20Sopenharmony_ci{
7148c2ecf20Sopenharmony_ci#ifndef __NR_mmap2
7158c2ecf20Sopenharmony_ci	int sysno = __NR_mmap;
7168c2ecf20Sopenharmony_ci#else
7178c2ecf20Sopenharmony_ci	int sysno = __NR_mmap2;
7188c2ecf20Sopenharmony_ci#endif
7198c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
7208c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
7218c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
7228c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, sysno, 1, 0),
7238c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
7248c2ecf20Sopenharmony_ci		/* Only both with lower 32-bit for now. */
7258c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(5)),
7268c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0C0FFEE, 0, 1),
7278c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
7288c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
7298c2ecf20Sopenharmony_ci	};
7308c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
7318c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
7328c2ecf20Sopenharmony_ci		.filter = filter,
7338c2ecf20Sopenharmony_ci	};
7348c2ecf20Sopenharmony_ci	long ret;
7358c2ecf20Sopenharmony_ci	pid_t parent = getppid();
7368c2ecf20Sopenharmony_ci	int fd;
7378c2ecf20Sopenharmony_ci	void *map1, *map2;
7388c2ecf20Sopenharmony_ci	int page_size = sysconf(_SC_PAGESIZE);
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	ASSERT_LT(0, page_size);
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
7438c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
7468c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	fd = open("/dev/zero", O_RDONLY);
7498c2ecf20Sopenharmony_ci	ASSERT_NE(-1, fd);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
7528c2ecf20Sopenharmony_ci	map1 = (void *)syscall(sysno,
7538c2ecf20Sopenharmony_ci		NULL, page_size, PROT_READ, MAP_PRIVATE, fd, page_size);
7548c2ecf20Sopenharmony_ci	EXPECT_NE(MAP_FAILED, map1);
7558c2ecf20Sopenharmony_ci	/* mmap2() should never return. */
7568c2ecf20Sopenharmony_ci	map2 = (void *)syscall(sysno,
7578c2ecf20Sopenharmony_ci		 NULL, page_size, PROT_READ, MAP_PRIVATE, fd, 0x0C0FFEE);
7588c2ecf20Sopenharmony_ci	EXPECT_EQ(MAP_FAILED, map2);
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	/* The test failed, so clean up the resources. */
7618c2ecf20Sopenharmony_ci	munmap(map1, page_size);
7628c2ecf20Sopenharmony_ci	munmap(map2, page_size);
7638c2ecf20Sopenharmony_ci	close(fd);
7648c2ecf20Sopenharmony_ci}
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci/* This is a thread task to die via seccomp filter violation. */
7678c2ecf20Sopenharmony_civoid *kill_thread(void *data)
7688c2ecf20Sopenharmony_ci{
7698c2ecf20Sopenharmony_ci	bool die = (bool)data;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	if (die) {
7728c2ecf20Sopenharmony_ci		prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
7738c2ecf20Sopenharmony_ci		return (void *)SIBLING_EXIT_FAILURE;
7748c2ecf20Sopenharmony_ci	}
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	return (void *)SIBLING_EXIT_UNKILLED;
7778c2ecf20Sopenharmony_ci}
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_cienum kill_t {
7808c2ecf20Sopenharmony_ci	KILL_THREAD,
7818c2ecf20Sopenharmony_ci	KILL_PROCESS,
7828c2ecf20Sopenharmony_ci	RET_UNKNOWN
7838c2ecf20Sopenharmony_ci};
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci/* Prepare a thread that will kill itself or both of us. */
7868c2ecf20Sopenharmony_civoid kill_thread_or_group(struct __test_metadata *_metadata,
7878c2ecf20Sopenharmony_ci			  enum kill_t kill_how)
7888c2ecf20Sopenharmony_ci{
7898c2ecf20Sopenharmony_ci	pthread_t thread;
7908c2ecf20Sopenharmony_ci	void *status;
7918c2ecf20Sopenharmony_ci	/* Kill only when calling __NR_prctl. */
7928c2ecf20Sopenharmony_ci	struct sock_filter filter_thread[] = {
7938c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
7948c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
7958c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
7968c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
7978c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
7988c2ecf20Sopenharmony_ci	};
7998c2ecf20Sopenharmony_ci	struct sock_fprog prog_thread = {
8008c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter_thread),
8018c2ecf20Sopenharmony_ci		.filter = filter_thread,
8028c2ecf20Sopenharmony_ci	};
8038c2ecf20Sopenharmony_ci	int kill = kill_how == KILL_PROCESS ? SECCOMP_RET_KILL_PROCESS : 0xAAAAAAAA;
8048c2ecf20Sopenharmony_ci	struct sock_filter filter_process[] = {
8058c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
8068c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
8078c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
8088c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, kill),
8098c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
8108c2ecf20Sopenharmony_ci	};
8118c2ecf20Sopenharmony_ci	struct sock_fprog prog_process = {
8128c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter_process),
8138c2ecf20Sopenharmony_ci		.filter = filter_process,
8148c2ecf20Sopenharmony_ci	};
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
8178c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0,
8218c2ecf20Sopenharmony_ci			     kill_how == KILL_THREAD ? &prog_thread
8228c2ecf20Sopenharmony_ci						     : &prog_process));
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	/*
8258c2ecf20Sopenharmony_ci	 * Add the KILL_THREAD rule again to make sure that the KILL_PROCESS
8268c2ecf20Sopenharmony_ci	 * flag cannot be downgraded by a new filter.
8278c2ecf20Sopenharmony_ci	 */
8288c2ecf20Sopenharmony_ci	if (kill_how == KILL_PROCESS)
8298c2ecf20Sopenharmony_ci		ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog_thread));
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	/* Start a thread that will exit immediately. */
8328c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)false));
8338c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_join(thread, &status));
8348c2ecf20Sopenharmony_ci	ASSERT_EQ(SIBLING_EXIT_UNKILLED, (unsigned long)status);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	/* Start a thread that will die immediately. */
8378c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)true));
8388c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_join(thread, &status));
8398c2ecf20Sopenharmony_ci	ASSERT_NE(SIBLING_EXIT_FAILURE, (unsigned long)status);
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	/*
8428c2ecf20Sopenharmony_ci	 * If we get here, only the spawned thread died. Let the parent know
8438c2ecf20Sopenharmony_ci	 * the whole process didn't die (i.e. this thread, the spawner,
8448c2ecf20Sopenharmony_ci	 * stayed running).
8458c2ecf20Sopenharmony_ci	 */
8468c2ecf20Sopenharmony_ci	exit(42);
8478c2ecf20Sopenharmony_ci}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ciTEST(KILL_thread)
8508c2ecf20Sopenharmony_ci{
8518c2ecf20Sopenharmony_ci	int status;
8528c2ecf20Sopenharmony_ci	pid_t child_pid;
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	child_pid = fork();
8558c2ecf20Sopenharmony_ci	ASSERT_LE(0, child_pid);
8568c2ecf20Sopenharmony_ci	if (child_pid == 0) {
8578c2ecf20Sopenharmony_ci		kill_thread_or_group(_metadata, KILL_THREAD);
8588c2ecf20Sopenharmony_ci		_exit(38);
8598c2ecf20Sopenharmony_ci	}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	/* If only the thread was killed, we'll see exit 42. */
8648c2ecf20Sopenharmony_ci	ASSERT_TRUE(WIFEXITED(status));
8658c2ecf20Sopenharmony_ci	ASSERT_EQ(42, WEXITSTATUS(status));
8668c2ecf20Sopenharmony_ci}
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ciTEST(KILL_process)
8698c2ecf20Sopenharmony_ci{
8708c2ecf20Sopenharmony_ci	int status;
8718c2ecf20Sopenharmony_ci	pid_t child_pid;
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	child_pid = fork();
8748c2ecf20Sopenharmony_ci	ASSERT_LE(0, child_pid);
8758c2ecf20Sopenharmony_ci	if (child_pid == 0) {
8768c2ecf20Sopenharmony_ci		kill_thread_or_group(_metadata, KILL_PROCESS);
8778c2ecf20Sopenharmony_ci		_exit(38);
8788c2ecf20Sopenharmony_ci	}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	/* If the entire process was killed, we'll see SIGSYS. */
8838c2ecf20Sopenharmony_ci	ASSERT_TRUE(WIFSIGNALED(status));
8848c2ecf20Sopenharmony_ci	ASSERT_EQ(SIGSYS, WTERMSIG(status));
8858c2ecf20Sopenharmony_ci}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ciTEST(KILL_unknown)
8888c2ecf20Sopenharmony_ci{
8898c2ecf20Sopenharmony_ci	int status;
8908c2ecf20Sopenharmony_ci	pid_t child_pid;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	child_pid = fork();
8938c2ecf20Sopenharmony_ci	ASSERT_LE(0, child_pid);
8948c2ecf20Sopenharmony_ci	if (child_pid == 0) {
8958c2ecf20Sopenharmony_ci		kill_thread_or_group(_metadata, RET_UNKNOWN);
8968c2ecf20Sopenharmony_ci		_exit(38);
8978c2ecf20Sopenharmony_ci	}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	/* If the entire process was killed, we'll see SIGSYS. */
9028c2ecf20Sopenharmony_ci	EXPECT_TRUE(WIFSIGNALED(status)) {
9038c2ecf20Sopenharmony_ci		TH_LOG("Unknown SECCOMP_RET is only killing the thread?");
9048c2ecf20Sopenharmony_ci	}
9058c2ecf20Sopenharmony_ci	ASSERT_EQ(SIGSYS, WTERMSIG(status));
9068c2ecf20Sopenharmony_ci}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci/* TODO(wad) add 64-bit versus 32-bit arg tests. */
9098c2ecf20Sopenharmony_ciTEST(arg_out_of_range)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
9128c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(6)),
9138c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
9148c2ecf20Sopenharmony_ci	};
9158c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
9168c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
9178c2ecf20Sopenharmony_ci		.filter = filter,
9188c2ecf20Sopenharmony_ci	};
9198c2ecf20Sopenharmony_ci	long ret;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
9228c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
9258c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, ret);
9268c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno);
9278c2ecf20Sopenharmony_ci}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci#define ERRNO_FILTER(name, errno)					\
9308c2ecf20Sopenharmony_ci	struct sock_filter _read_filter_##name[] = {			\
9318c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,				\
9328c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),		\
9338c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),	\
9348c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | errno),	\
9358c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),		\
9368c2ecf20Sopenharmony_ci	};								\
9378c2ecf20Sopenharmony_ci	struct sock_fprog prog_##name = {				\
9388c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(_read_filter_##name),	\
9398c2ecf20Sopenharmony_ci		.filter = _read_filter_##name,				\
9408c2ecf20Sopenharmony_ci	}
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci/* Make sure basic errno values are correctly passed through a filter. */
9438c2ecf20Sopenharmony_ciTEST(ERRNO_valid)
9448c2ecf20Sopenharmony_ci{
9458c2ecf20Sopenharmony_ci	ERRNO_FILTER(valid, E2BIG);
9468c2ecf20Sopenharmony_ci	long ret;
9478c2ecf20Sopenharmony_ci	pid_t parent = getppid();
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
9508c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_valid);
9538c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
9568c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, read(-1, NULL, 0));
9578c2ecf20Sopenharmony_ci	EXPECT_EQ(E2BIG, errno);
9588c2ecf20Sopenharmony_ci}
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci/* Make sure an errno of zero is correctly handled by the arch code. */
9618c2ecf20Sopenharmony_ciTEST(ERRNO_zero)
9628c2ecf20Sopenharmony_ci{
9638c2ecf20Sopenharmony_ci	ERRNO_FILTER(zero, 0);
9648c2ecf20Sopenharmony_ci	long ret;
9658c2ecf20Sopenharmony_ci	pid_t parent = getppid();
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
9688c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_zero);
9718c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
9748c2ecf20Sopenharmony_ci	/* "errno" of 0 is ok. */
9758c2ecf20Sopenharmony_ci	EXPECT_EQ(0, read(-1, NULL, 0));
9768c2ecf20Sopenharmony_ci}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci/*
9798c2ecf20Sopenharmony_ci * The SECCOMP_RET_DATA mask is 16 bits wide, but errno is smaller.
9808c2ecf20Sopenharmony_ci * This tests that the errno value gets capped correctly, fixed by
9818c2ecf20Sopenharmony_ci * 580c57f10768 ("seccomp: cap SECCOMP_RET_ERRNO data to MAX_ERRNO").
9828c2ecf20Sopenharmony_ci */
9838c2ecf20Sopenharmony_ciTEST(ERRNO_capped)
9848c2ecf20Sopenharmony_ci{
9858c2ecf20Sopenharmony_ci	ERRNO_FILTER(capped, 4096);
9868c2ecf20Sopenharmony_ci	long ret;
9878c2ecf20Sopenharmony_ci	pid_t parent = getppid();
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
9908c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_capped);
9938c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
9968c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, read(-1, NULL, 0));
9978c2ecf20Sopenharmony_ci	EXPECT_EQ(4095, errno);
9988c2ecf20Sopenharmony_ci}
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci/*
10018c2ecf20Sopenharmony_ci * Filters are processed in reverse order: last applied is executed first.
10028c2ecf20Sopenharmony_ci * Since only the SECCOMP_RET_ACTION mask is tested for return values, the
10038c2ecf20Sopenharmony_ci * SECCOMP_RET_DATA mask results will follow the most recently applied
10048c2ecf20Sopenharmony_ci * matching filter return (and not the lowest or highest value).
10058c2ecf20Sopenharmony_ci */
10068c2ecf20Sopenharmony_ciTEST(ERRNO_order)
10078c2ecf20Sopenharmony_ci{
10088c2ecf20Sopenharmony_ci	ERRNO_FILTER(first,  11);
10098c2ecf20Sopenharmony_ci	ERRNO_FILTER(second, 13);
10108c2ecf20Sopenharmony_ci	ERRNO_FILTER(third,  12);
10118c2ecf20Sopenharmony_ci	long ret;
10128c2ecf20Sopenharmony_ci	pid_t parent = getppid();
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
10158c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_first);
10188c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_second);
10218c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_third);
10248c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
10278c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, read(-1, NULL, 0));
10288c2ecf20Sopenharmony_ci	EXPECT_EQ(12, errno);
10298c2ecf20Sopenharmony_ci}
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ciFIXTURE(TRAP) {
10328c2ecf20Sopenharmony_ci	struct sock_fprog prog;
10338c2ecf20Sopenharmony_ci};
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ciFIXTURE_SETUP(TRAP)
10368c2ecf20Sopenharmony_ci{
10378c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
10388c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
10398c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
10408c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
10418c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP),
10428c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
10438c2ecf20Sopenharmony_ci	};
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	memset(&self->prog, 0, sizeof(self->prog));
10468c2ecf20Sopenharmony_ci	self->prog.filter = malloc(sizeof(filter));
10478c2ecf20Sopenharmony_ci	ASSERT_NE(NULL, self->prog.filter);
10488c2ecf20Sopenharmony_ci	memcpy(self->prog.filter, filter, sizeof(filter));
10498c2ecf20Sopenharmony_ci	self->prog.len = (unsigned short)ARRAY_SIZE(filter);
10508c2ecf20Sopenharmony_ci}
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ciFIXTURE_TEARDOWN(TRAP)
10538c2ecf20Sopenharmony_ci{
10548c2ecf20Sopenharmony_ci	if (self->prog.filter)
10558c2ecf20Sopenharmony_ci		free(self->prog.filter);
10568c2ecf20Sopenharmony_ci}
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ciTEST_F_SIGNAL(TRAP, dfl, SIGSYS)
10598c2ecf20Sopenharmony_ci{
10608c2ecf20Sopenharmony_ci	long ret;
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
10638c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
10668c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
10678c2ecf20Sopenharmony_ci	syscall(__NR_getpid);
10688c2ecf20Sopenharmony_ci}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci/* Ensure that SIGSYS overrides SIG_IGN */
10718c2ecf20Sopenharmony_ciTEST_F_SIGNAL(TRAP, ign, SIGSYS)
10728c2ecf20Sopenharmony_ci{
10738c2ecf20Sopenharmony_ci	long ret;
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
10768c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	signal(SIGSYS, SIG_IGN);
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
10818c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
10828c2ecf20Sopenharmony_ci	syscall(__NR_getpid);
10838c2ecf20Sopenharmony_ci}
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_cistatic siginfo_t TRAP_info;
10868c2ecf20Sopenharmony_cistatic volatile int TRAP_nr;
10878c2ecf20Sopenharmony_cistatic void TRAP_action(int nr, siginfo_t *info, void *void_context)
10888c2ecf20Sopenharmony_ci{
10898c2ecf20Sopenharmony_ci	memcpy(&TRAP_info, info, sizeof(TRAP_info));
10908c2ecf20Sopenharmony_ci	TRAP_nr = nr;
10918c2ecf20Sopenharmony_ci}
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ciTEST_F(TRAP, handler)
10948c2ecf20Sopenharmony_ci{
10958c2ecf20Sopenharmony_ci	int ret, test;
10968c2ecf20Sopenharmony_ci	struct sigaction act;
10978c2ecf20Sopenharmony_ci	sigset_t mask;
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	memset(&act, 0, sizeof(act));
11008c2ecf20Sopenharmony_ci	sigemptyset(&mask);
11018c2ecf20Sopenharmony_ci	sigaddset(&mask, SIGSYS);
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	act.sa_sigaction = &TRAP_action;
11048c2ecf20Sopenharmony_ci	act.sa_flags = SA_SIGINFO;
11058c2ecf20Sopenharmony_ci	ret = sigaction(SIGSYS, &act, NULL);
11068c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
11078c2ecf20Sopenharmony_ci		TH_LOG("sigaction failed");
11088c2ecf20Sopenharmony_ci	}
11098c2ecf20Sopenharmony_ci	ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
11108c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
11118c2ecf20Sopenharmony_ci		TH_LOG("sigprocmask failed");
11128c2ecf20Sopenharmony_ci	}
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
11158c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
11168c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
11178c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
11188c2ecf20Sopenharmony_ci	TRAP_nr = 0;
11198c2ecf20Sopenharmony_ci	memset(&TRAP_info, 0, sizeof(TRAP_info));
11208c2ecf20Sopenharmony_ci	/* Expect the registers to be rolled back. (nr = error) may vary
11218c2ecf20Sopenharmony_ci	 * based on arch. */
11228c2ecf20Sopenharmony_ci	ret = syscall(__NR_getpid);
11238c2ecf20Sopenharmony_ci	/* Silence gcc warning about volatile. */
11248c2ecf20Sopenharmony_ci	test = TRAP_nr;
11258c2ecf20Sopenharmony_ci	EXPECT_EQ(SIGSYS, test);
11268c2ecf20Sopenharmony_ci	struct local_sigsys {
11278c2ecf20Sopenharmony_ci		void *_call_addr;	/* calling user insn */
11288c2ecf20Sopenharmony_ci		int _syscall;		/* triggering system call number */
11298c2ecf20Sopenharmony_ci		unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
11308c2ecf20Sopenharmony_ci	} *sigsys = (struct local_sigsys *)
11318c2ecf20Sopenharmony_ci#ifdef si_syscall
11328c2ecf20Sopenharmony_ci		&(TRAP_info.si_call_addr);
11338c2ecf20Sopenharmony_ci#else
11348c2ecf20Sopenharmony_ci		&TRAP_info.si_pid;
11358c2ecf20Sopenharmony_ci#endif
11368c2ecf20Sopenharmony_ci	EXPECT_EQ(__NR_getpid, sigsys->_syscall);
11378c2ecf20Sopenharmony_ci	/* Make sure arch is non-zero. */
11388c2ecf20Sopenharmony_ci	EXPECT_NE(0, sigsys->_arch);
11398c2ecf20Sopenharmony_ci	EXPECT_NE(0, (unsigned long)sigsys->_call_addr);
11408c2ecf20Sopenharmony_ci}
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ciFIXTURE(precedence) {
11438c2ecf20Sopenharmony_ci	struct sock_fprog allow;
11448c2ecf20Sopenharmony_ci	struct sock_fprog log;
11458c2ecf20Sopenharmony_ci	struct sock_fprog trace;
11468c2ecf20Sopenharmony_ci	struct sock_fprog error;
11478c2ecf20Sopenharmony_ci	struct sock_fprog trap;
11488c2ecf20Sopenharmony_ci	struct sock_fprog kill;
11498c2ecf20Sopenharmony_ci};
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ciFIXTURE_SETUP(precedence)
11528c2ecf20Sopenharmony_ci{
11538c2ecf20Sopenharmony_ci	struct sock_filter allow_insns[] = {
11548c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
11558c2ecf20Sopenharmony_ci	};
11568c2ecf20Sopenharmony_ci	struct sock_filter log_insns[] = {
11578c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
11588c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
11598c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
11608c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
11618c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
11628c2ecf20Sopenharmony_ci	};
11638c2ecf20Sopenharmony_ci	struct sock_filter trace_insns[] = {
11648c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
11658c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
11668c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
11678c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
11688c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE),
11698c2ecf20Sopenharmony_ci	};
11708c2ecf20Sopenharmony_ci	struct sock_filter error_insns[] = {
11718c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
11728c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
11738c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
11748c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
11758c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO),
11768c2ecf20Sopenharmony_ci	};
11778c2ecf20Sopenharmony_ci	struct sock_filter trap_insns[] = {
11788c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
11798c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
11808c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
11818c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
11828c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP),
11838c2ecf20Sopenharmony_ci	};
11848c2ecf20Sopenharmony_ci	struct sock_filter kill_insns[] = {
11858c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
11868c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
11878c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
11888c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
11898c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
11908c2ecf20Sopenharmony_ci	};
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	memset(self, 0, sizeof(*self));
11938c2ecf20Sopenharmony_ci#define FILTER_ALLOC(_x) \
11948c2ecf20Sopenharmony_ci	self->_x.filter = malloc(sizeof(_x##_insns)); \
11958c2ecf20Sopenharmony_ci	ASSERT_NE(NULL, self->_x.filter); \
11968c2ecf20Sopenharmony_ci	memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
11978c2ecf20Sopenharmony_ci	self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns)
11988c2ecf20Sopenharmony_ci	FILTER_ALLOC(allow);
11998c2ecf20Sopenharmony_ci	FILTER_ALLOC(log);
12008c2ecf20Sopenharmony_ci	FILTER_ALLOC(trace);
12018c2ecf20Sopenharmony_ci	FILTER_ALLOC(error);
12028c2ecf20Sopenharmony_ci	FILTER_ALLOC(trap);
12038c2ecf20Sopenharmony_ci	FILTER_ALLOC(kill);
12048c2ecf20Sopenharmony_ci}
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ciFIXTURE_TEARDOWN(precedence)
12078c2ecf20Sopenharmony_ci{
12088c2ecf20Sopenharmony_ci#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
12098c2ecf20Sopenharmony_ci	FILTER_FREE(allow);
12108c2ecf20Sopenharmony_ci	FILTER_FREE(log);
12118c2ecf20Sopenharmony_ci	FILTER_FREE(trace);
12128c2ecf20Sopenharmony_ci	FILTER_FREE(error);
12138c2ecf20Sopenharmony_ci	FILTER_FREE(trap);
12148c2ecf20Sopenharmony_ci	FILTER_FREE(kill);
12158c2ecf20Sopenharmony_ci}
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ciTEST_F(precedence, allow_ok)
12188c2ecf20Sopenharmony_ci{
12198c2ecf20Sopenharmony_ci	pid_t parent, res = 0;
12208c2ecf20Sopenharmony_ci	long ret;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	parent = getppid();
12238c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
12248c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
12278c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12288c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
12298c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12308c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
12318c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12328c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
12338c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12348c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
12358c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12368c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
12378c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12388c2ecf20Sopenharmony_ci	/* Should work just fine. */
12398c2ecf20Sopenharmony_ci	res = syscall(__NR_getppid);
12408c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, res);
12418c2ecf20Sopenharmony_ci}
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ciTEST_F_SIGNAL(precedence, kill_is_highest, SIGSYS)
12448c2ecf20Sopenharmony_ci{
12458c2ecf20Sopenharmony_ci	pid_t parent, res = 0;
12468c2ecf20Sopenharmony_ci	long ret;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	parent = getppid();
12498c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
12508c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
12538c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12548c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
12558c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12568c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
12578c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12588c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
12598c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12608c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
12618c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12628c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
12638c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12648c2ecf20Sopenharmony_ci	/* Should work just fine. */
12658c2ecf20Sopenharmony_ci	res = syscall(__NR_getppid);
12668c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, res);
12678c2ecf20Sopenharmony_ci	/* getpid() should never return. */
12688c2ecf20Sopenharmony_ci	res = syscall(__NR_getpid);
12698c2ecf20Sopenharmony_ci	EXPECT_EQ(0, res);
12708c2ecf20Sopenharmony_ci}
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ciTEST_F_SIGNAL(precedence, kill_is_highest_in_any_order, SIGSYS)
12738c2ecf20Sopenharmony_ci{
12748c2ecf20Sopenharmony_ci	pid_t parent;
12758c2ecf20Sopenharmony_ci	long ret;
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	parent = getppid();
12788c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
12798c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
12828c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12838c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
12848c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12858c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
12868c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12878c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
12888c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12898c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
12908c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12918c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
12928c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
12938c2ecf20Sopenharmony_ci	/* Should work just fine. */
12948c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
12958c2ecf20Sopenharmony_ci	/* getpid() should never return. */
12968c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_getpid));
12978c2ecf20Sopenharmony_ci}
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ciTEST_F_SIGNAL(precedence, trap_is_second, SIGSYS)
13008c2ecf20Sopenharmony_ci{
13018c2ecf20Sopenharmony_ci	pid_t parent;
13028c2ecf20Sopenharmony_ci	long ret;
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	parent = getppid();
13058c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
13068c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
13098c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13108c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
13118c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13128c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
13138c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13148c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
13158c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13168c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
13178c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13188c2ecf20Sopenharmony_ci	/* Should work just fine. */
13198c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
13208c2ecf20Sopenharmony_ci	/* getpid() should never return. */
13218c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_getpid));
13228c2ecf20Sopenharmony_ci}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ciTEST_F_SIGNAL(precedence, trap_is_second_in_any_order, SIGSYS)
13258c2ecf20Sopenharmony_ci{
13268c2ecf20Sopenharmony_ci	pid_t parent;
13278c2ecf20Sopenharmony_ci	long ret;
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	parent = getppid();
13308c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
13318c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
13348c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13358c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
13368c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13378c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
13388c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13398c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
13408c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13418c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
13428c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13438c2ecf20Sopenharmony_ci	/* Should work just fine. */
13448c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
13458c2ecf20Sopenharmony_ci	/* getpid() should never return. */
13468c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_getpid));
13478c2ecf20Sopenharmony_ci}
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ciTEST_F(precedence, errno_is_third)
13508c2ecf20Sopenharmony_ci{
13518c2ecf20Sopenharmony_ci	pid_t parent;
13528c2ecf20Sopenharmony_ci	long ret;
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	parent = getppid();
13558c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
13568c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
13598c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13608c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
13618c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13628c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
13638c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13648c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
13658c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13668c2ecf20Sopenharmony_ci	/* Should work just fine. */
13678c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
13688c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_getpid));
13698c2ecf20Sopenharmony_ci}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ciTEST_F(precedence, errno_is_third_in_any_order)
13728c2ecf20Sopenharmony_ci{
13738c2ecf20Sopenharmony_ci	pid_t parent;
13748c2ecf20Sopenharmony_ci	long ret;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	parent = getppid();
13778c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
13788c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
13818c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13828c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
13838c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13848c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
13858c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13868c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
13878c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
13888c2ecf20Sopenharmony_ci	/* Should work just fine. */
13898c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
13908c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_getpid));
13918c2ecf20Sopenharmony_ci}
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ciTEST_F(precedence, trace_is_fourth)
13948c2ecf20Sopenharmony_ci{
13958c2ecf20Sopenharmony_ci	pid_t parent;
13968c2ecf20Sopenharmony_ci	long ret;
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	parent = getppid();
13998c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
14008c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
14038c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14048c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
14058c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14068c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
14078c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14088c2ecf20Sopenharmony_ci	/* Should work just fine. */
14098c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
14108c2ecf20Sopenharmony_ci	/* No ptracer */
14118c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, syscall(__NR_getpid));
14128c2ecf20Sopenharmony_ci}
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ciTEST_F(precedence, trace_is_fourth_in_any_order)
14158c2ecf20Sopenharmony_ci{
14168c2ecf20Sopenharmony_ci	pid_t parent;
14178c2ecf20Sopenharmony_ci	long ret;
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	parent = getppid();
14208c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
14218c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
14248c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14258c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
14268c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14278c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
14288c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14298c2ecf20Sopenharmony_ci	/* Should work just fine. */
14308c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
14318c2ecf20Sopenharmony_ci	/* No ptracer */
14328c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, syscall(__NR_getpid));
14338c2ecf20Sopenharmony_ci}
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ciTEST_F(precedence, log_is_fifth)
14368c2ecf20Sopenharmony_ci{
14378c2ecf20Sopenharmony_ci	pid_t mypid, parent;
14388c2ecf20Sopenharmony_ci	long ret;
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	mypid = getpid();
14418c2ecf20Sopenharmony_ci	parent = getppid();
14428c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
14438c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
14468c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14478c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
14488c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14498c2ecf20Sopenharmony_ci	/* Should work just fine. */
14508c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
14518c2ecf20Sopenharmony_ci	/* Should also work just fine */
14528c2ecf20Sopenharmony_ci	EXPECT_EQ(mypid, syscall(__NR_getpid));
14538c2ecf20Sopenharmony_ci}
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ciTEST_F(precedence, log_is_fifth_in_any_order)
14568c2ecf20Sopenharmony_ci{
14578c2ecf20Sopenharmony_ci	pid_t mypid, parent;
14588c2ecf20Sopenharmony_ci	long ret;
14598c2ecf20Sopenharmony_ci
14608c2ecf20Sopenharmony_ci	mypid = getpid();
14618c2ecf20Sopenharmony_ci	parent = getppid();
14628c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
14638c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
14668c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14678c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
14688c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
14698c2ecf20Sopenharmony_ci	/* Should work just fine. */
14708c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
14718c2ecf20Sopenharmony_ci	/* Should also work just fine */
14728c2ecf20Sopenharmony_ci	EXPECT_EQ(mypid, syscall(__NR_getpid));
14738c2ecf20Sopenharmony_ci}
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci#ifndef PTRACE_O_TRACESECCOMP
14768c2ecf20Sopenharmony_ci#define PTRACE_O_TRACESECCOMP	0x00000080
14778c2ecf20Sopenharmony_ci#endif
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci/* Catch the Ubuntu 12.04 value error. */
14808c2ecf20Sopenharmony_ci#if PTRACE_EVENT_SECCOMP != 7
14818c2ecf20Sopenharmony_ci#undef PTRACE_EVENT_SECCOMP
14828c2ecf20Sopenharmony_ci#endif
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci#ifndef PTRACE_EVENT_SECCOMP
14858c2ecf20Sopenharmony_ci#define PTRACE_EVENT_SECCOMP 7
14868c2ecf20Sopenharmony_ci#endif
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci#define IS_SECCOMP_EVENT(status) ((status >> 16) == PTRACE_EVENT_SECCOMP)
14898c2ecf20Sopenharmony_cibool tracer_running;
14908c2ecf20Sopenharmony_civoid tracer_stop(int sig)
14918c2ecf20Sopenharmony_ci{
14928c2ecf20Sopenharmony_ci	tracer_running = false;
14938c2ecf20Sopenharmony_ci}
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_citypedef void tracer_func_t(struct __test_metadata *_metadata,
14968c2ecf20Sopenharmony_ci			   pid_t tracee, int status, void *args);
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_civoid start_tracer(struct __test_metadata *_metadata, int fd, pid_t tracee,
14998c2ecf20Sopenharmony_ci	    tracer_func_t tracer_func, void *args, bool ptrace_syscall)
15008c2ecf20Sopenharmony_ci{
15018c2ecf20Sopenharmony_ci	int ret = -1;
15028c2ecf20Sopenharmony_ci	struct sigaction action = {
15038c2ecf20Sopenharmony_ci		.sa_handler = tracer_stop,
15048c2ecf20Sopenharmony_ci	};
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	/* Allow external shutdown. */
15078c2ecf20Sopenharmony_ci	tracer_running = true;
15088c2ecf20Sopenharmony_ci	ASSERT_EQ(0, sigaction(SIGUSR1, &action, NULL));
15098c2ecf20Sopenharmony_ci
15108c2ecf20Sopenharmony_ci	errno = 0;
15118c2ecf20Sopenharmony_ci	while (ret == -1 && errno != EINVAL)
15128c2ecf20Sopenharmony_ci		ret = ptrace(PTRACE_ATTACH, tracee, NULL, 0);
15138c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
15148c2ecf20Sopenharmony_ci		kill(tracee, SIGKILL);
15158c2ecf20Sopenharmony_ci	}
15168c2ecf20Sopenharmony_ci	/* Wait for attach stop */
15178c2ecf20Sopenharmony_ci	wait(NULL);
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	ret = ptrace(PTRACE_SETOPTIONS, tracee, NULL, ptrace_syscall ?
15208c2ecf20Sopenharmony_ci						      PTRACE_O_TRACESYSGOOD :
15218c2ecf20Sopenharmony_ci						      PTRACE_O_TRACESECCOMP);
15228c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
15238c2ecf20Sopenharmony_ci		TH_LOG("Failed to set PTRACE_O_TRACESECCOMP");
15248c2ecf20Sopenharmony_ci		kill(tracee, SIGKILL);
15258c2ecf20Sopenharmony_ci	}
15268c2ecf20Sopenharmony_ci	ret = ptrace(ptrace_syscall ? PTRACE_SYSCALL : PTRACE_CONT,
15278c2ecf20Sopenharmony_ci		     tracee, NULL, 0);
15288c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci	/* Unblock the tracee */
15318c2ecf20Sopenharmony_ci	ASSERT_EQ(1, write(fd, "A", 1));
15328c2ecf20Sopenharmony_ci	ASSERT_EQ(0, close(fd));
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ci	/* Run until we're shut down. Must assert to stop execution. */
15358c2ecf20Sopenharmony_ci	while (tracer_running) {
15368c2ecf20Sopenharmony_ci		int status;
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci		if (wait(&status) != tracee)
15398c2ecf20Sopenharmony_ci			continue;
15408c2ecf20Sopenharmony_ci		if (WIFSIGNALED(status) || WIFEXITED(status))
15418c2ecf20Sopenharmony_ci			/* Child is dead. Time to go. */
15428c2ecf20Sopenharmony_ci			return;
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ci		/* Check if this is a seccomp event. */
15458c2ecf20Sopenharmony_ci		ASSERT_EQ(!ptrace_syscall, IS_SECCOMP_EVENT(status));
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci		tracer_func(_metadata, tracee, status, args);
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci		ret = ptrace(ptrace_syscall ? PTRACE_SYSCALL : PTRACE_CONT,
15508c2ecf20Sopenharmony_ci			     tracee, NULL, 0);
15518c2ecf20Sopenharmony_ci		ASSERT_EQ(0, ret);
15528c2ecf20Sopenharmony_ci	}
15538c2ecf20Sopenharmony_ci	/* Directly report the status of our test harness results. */
15548c2ecf20Sopenharmony_ci	syscall(__NR_exit, _metadata->passed ? EXIT_SUCCESS : EXIT_FAILURE);
15558c2ecf20Sopenharmony_ci}
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci/* Common tracer setup/teardown functions. */
15588c2ecf20Sopenharmony_civoid cont_handler(int num)
15598c2ecf20Sopenharmony_ci{ }
15608c2ecf20Sopenharmony_cipid_t setup_trace_fixture(struct __test_metadata *_metadata,
15618c2ecf20Sopenharmony_ci			  tracer_func_t func, void *args, bool ptrace_syscall)
15628c2ecf20Sopenharmony_ci{
15638c2ecf20Sopenharmony_ci	char sync;
15648c2ecf20Sopenharmony_ci	int pipefd[2];
15658c2ecf20Sopenharmony_ci	pid_t tracer_pid;
15668c2ecf20Sopenharmony_ci	pid_t tracee = getpid();
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci	/* Setup a pipe for clean synchronization. */
15698c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pipe(pipefd));
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	/* Fork a child which we'll promote to tracer */
15728c2ecf20Sopenharmony_ci	tracer_pid = fork();
15738c2ecf20Sopenharmony_ci	ASSERT_LE(0, tracer_pid);
15748c2ecf20Sopenharmony_ci	signal(SIGALRM, cont_handler);
15758c2ecf20Sopenharmony_ci	if (tracer_pid == 0) {
15768c2ecf20Sopenharmony_ci		close(pipefd[0]);
15778c2ecf20Sopenharmony_ci		start_tracer(_metadata, pipefd[1], tracee, func, args,
15788c2ecf20Sopenharmony_ci			     ptrace_syscall);
15798c2ecf20Sopenharmony_ci		syscall(__NR_exit, 0);
15808c2ecf20Sopenharmony_ci	}
15818c2ecf20Sopenharmony_ci	close(pipefd[1]);
15828c2ecf20Sopenharmony_ci	prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
15838c2ecf20Sopenharmony_ci	read(pipefd[0], &sync, 1);
15848c2ecf20Sopenharmony_ci	close(pipefd[0]);
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	return tracer_pid;
15878c2ecf20Sopenharmony_ci}
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_civoid teardown_trace_fixture(struct __test_metadata *_metadata,
15908c2ecf20Sopenharmony_ci			    pid_t tracer)
15918c2ecf20Sopenharmony_ci{
15928c2ecf20Sopenharmony_ci	if (tracer) {
15938c2ecf20Sopenharmony_ci		int status;
15948c2ecf20Sopenharmony_ci		/*
15958c2ecf20Sopenharmony_ci		 * Extract the exit code from the other process and
15968c2ecf20Sopenharmony_ci		 * adopt it for ourselves in case its asserts failed.
15978c2ecf20Sopenharmony_ci		 */
15988c2ecf20Sopenharmony_ci		ASSERT_EQ(0, kill(tracer, SIGUSR1));
15998c2ecf20Sopenharmony_ci		ASSERT_EQ(tracer, waitpid(tracer, &status, 0));
16008c2ecf20Sopenharmony_ci		if (WEXITSTATUS(status))
16018c2ecf20Sopenharmony_ci			_metadata->passed = 0;
16028c2ecf20Sopenharmony_ci	}
16038c2ecf20Sopenharmony_ci}
16048c2ecf20Sopenharmony_ci
16058c2ecf20Sopenharmony_ci/* "poke" tracer arguments and function. */
16068c2ecf20Sopenharmony_cistruct tracer_args_poke_t {
16078c2ecf20Sopenharmony_ci	unsigned long poke_addr;
16088c2ecf20Sopenharmony_ci};
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_civoid tracer_poke(struct __test_metadata *_metadata, pid_t tracee, int status,
16118c2ecf20Sopenharmony_ci		 void *args)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	int ret;
16148c2ecf20Sopenharmony_ci	unsigned long msg;
16158c2ecf20Sopenharmony_ci	struct tracer_args_poke_t *info = (struct tracer_args_poke_t *)args;
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
16188c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret);
16198c2ecf20Sopenharmony_ci	/* If this fails, don't try to recover. */
16208c2ecf20Sopenharmony_ci	ASSERT_EQ(0x1001, msg) {
16218c2ecf20Sopenharmony_ci		kill(tracee, SIGKILL);
16228c2ecf20Sopenharmony_ci	}
16238c2ecf20Sopenharmony_ci	/*
16248c2ecf20Sopenharmony_ci	 * Poke in the message.
16258c2ecf20Sopenharmony_ci	 * Registers are not touched to try to keep this relatively arch
16268c2ecf20Sopenharmony_ci	 * agnostic.
16278c2ecf20Sopenharmony_ci	 */
16288c2ecf20Sopenharmony_ci	ret = ptrace(PTRACE_POKEDATA, tracee, info->poke_addr, 0x1001);
16298c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret);
16308c2ecf20Sopenharmony_ci}
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ciFIXTURE(TRACE_poke) {
16338c2ecf20Sopenharmony_ci	struct sock_fprog prog;
16348c2ecf20Sopenharmony_ci	pid_t tracer;
16358c2ecf20Sopenharmony_ci	long poked;
16368c2ecf20Sopenharmony_ci	struct tracer_args_poke_t tracer_args;
16378c2ecf20Sopenharmony_ci};
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ciFIXTURE_SETUP(TRACE_poke)
16408c2ecf20Sopenharmony_ci{
16418c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
16428c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
16438c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
16448c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
16458c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1001),
16468c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
16478c2ecf20Sopenharmony_ci	};
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	self->poked = 0;
16508c2ecf20Sopenharmony_ci	memset(&self->prog, 0, sizeof(self->prog));
16518c2ecf20Sopenharmony_ci	self->prog.filter = malloc(sizeof(filter));
16528c2ecf20Sopenharmony_ci	ASSERT_NE(NULL, self->prog.filter);
16538c2ecf20Sopenharmony_ci	memcpy(self->prog.filter, filter, sizeof(filter));
16548c2ecf20Sopenharmony_ci	self->prog.len = (unsigned short)ARRAY_SIZE(filter);
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	/* Set up tracer args. */
16578c2ecf20Sopenharmony_ci	self->tracer_args.poke_addr = (unsigned long)&self->poked;
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	/* Launch tracer. */
16608c2ecf20Sopenharmony_ci	self->tracer = setup_trace_fixture(_metadata, tracer_poke,
16618c2ecf20Sopenharmony_ci					   &self->tracer_args, false);
16628c2ecf20Sopenharmony_ci}
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ciFIXTURE_TEARDOWN(TRACE_poke)
16658c2ecf20Sopenharmony_ci{
16668c2ecf20Sopenharmony_ci	teardown_trace_fixture(_metadata, self->tracer);
16678c2ecf20Sopenharmony_ci	if (self->prog.filter)
16688c2ecf20Sopenharmony_ci		free(self->prog.filter);
16698c2ecf20Sopenharmony_ci}
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ciTEST_F(TRACE_poke, read_has_side_effects)
16728c2ecf20Sopenharmony_ci{
16738c2ecf20Sopenharmony_ci	ssize_t ret;
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
16768c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
16798c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci	EXPECT_EQ(0, self->poked);
16828c2ecf20Sopenharmony_ci	ret = read(-1, NULL, 0);
16838c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, ret);
16848c2ecf20Sopenharmony_ci	EXPECT_EQ(0x1001, self->poked);
16858c2ecf20Sopenharmony_ci}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ciTEST_F(TRACE_poke, getpid_runs_normally)
16888c2ecf20Sopenharmony_ci{
16898c2ecf20Sopenharmony_ci	long ret;
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
16928c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
16958c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci	EXPECT_EQ(0, self->poked);
16988c2ecf20Sopenharmony_ci	EXPECT_NE(0, syscall(__NR_getpid));
16998c2ecf20Sopenharmony_ci	EXPECT_EQ(0, self->poked);
17008c2ecf20Sopenharmony_ci}
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci#if defined(__x86_64__)
17038c2ecf20Sopenharmony_ci# define ARCH_REGS		struct user_regs_struct
17048c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).orig_rax
17058c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).rax
17068c2ecf20Sopenharmony_ci#elif defined(__i386__)
17078c2ecf20Sopenharmony_ci# define ARCH_REGS		struct user_regs_struct
17088c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).orig_eax
17098c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).eax
17108c2ecf20Sopenharmony_ci#elif defined(__arm__)
17118c2ecf20Sopenharmony_ci# define ARCH_REGS		struct pt_regs
17128c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).ARM_r7
17138c2ecf20Sopenharmony_ci# ifndef PTRACE_SET_SYSCALL
17148c2ecf20Sopenharmony_ci#  define PTRACE_SET_SYSCALL   23
17158c2ecf20Sopenharmony_ci# endif
17168c2ecf20Sopenharmony_ci# define SYSCALL_NUM_SET(_regs, _nr)	\
17178c2ecf20Sopenharmony_ci		EXPECT_EQ(0, ptrace(PTRACE_SET_SYSCALL, tracee, NULL, _nr))
17188c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).ARM_r0
17198c2ecf20Sopenharmony_ci#elif defined(__aarch64__)
17208c2ecf20Sopenharmony_ci# define ARCH_REGS		struct user_pt_regs
17218c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).regs[8]
17228c2ecf20Sopenharmony_ci# ifndef NT_ARM_SYSTEM_CALL
17238c2ecf20Sopenharmony_ci#  define NT_ARM_SYSTEM_CALL 0x404
17248c2ecf20Sopenharmony_ci# endif
17258c2ecf20Sopenharmony_ci# define SYSCALL_NUM_SET(_regs, _nr)				\
17268c2ecf20Sopenharmony_ci	do {							\
17278c2ecf20Sopenharmony_ci		struct iovec __v;				\
17288c2ecf20Sopenharmony_ci		typeof(_nr) __nr = (_nr);			\
17298c2ecf20Sopenharmony_ci		__v.iov_base = &__nr;				\
17308c2ecf20Sopenharmony_ci		__v.iov_len = sizeof(__nr);			\
17318c2ecf20Sopenharmony_ci		EXPECT_EQ(0, ptrace(PTRACE_SETREGSET, tracee,	\
17328c2ecf20Sopenharmony_ci				    NT_ARM_SYSTEM_CALL, &__v));	\
17338c2ecf20Sopenharmony_ci	} while (0)
17348c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).regs[0]
17358c2ecf20Sopenharmony_ci#elif defined(__loongarch__)
17368c2ecf20Sopenharmony_ci# define ARCH_REGS		struct user_pt_regs
17378c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).regs[11]
17388c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).regs[4]
17398c2ecf20Sopenharmony_ci#elif defined(__riscv) && __riscv_xlen == 64
17408c2ecf20Sopenharmony_ci# define ARCH_REGS		struct user_regs_struct
17418c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).a7
17428c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).a0
17438c2ecf20Sopenharmony_ci#elif defined(__csky__)
17448c2ecf20Sopenharmony_ci# define ARCH_REGS		struct pt_regs
17458c2ecf20Sopenharmony_ci#  if defined(__CSKYABIV2__)
17468c2ecf20Sopenharmony_ci#   define SYSCALL_NUM(_regs)	(_regs).regs[3]
17478c2ecf20Sopenharmony_ci#  else
17488c2ecf20Sopenharmony_ci#   define SYSCALL_NUM(_regs)	(_regs).regs[9]
17498c2ecf20Sopenharmony_ci#  endif
17508c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).a0
17518c2ecf20Sopenharmony_ci#elif defined(__hppa__)
17528c2ecf20Sopenharmony_ci# define ARCH_REGS		struct user_regs_struct
17538c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).gr[20]
17548c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).gr[28]
17558c2ecf20Sopenharmony_ci#elif defined(__powerpc__)
17568c2ecf20Sopenharmony_ci# define ARCH_REGS		struct pt_regs
17578c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).gpr[0]
17588c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).gpr[3]
17598c2ecf20Sopenharmony_ci# define SYSCALL_RET_SET(_regs, _val)				\
17608c2ecf20Sopenharmony_ci	do {							\
17618c2ecf20Sopenharmony_ci		typeof(_val) _result = (_val);			\
17628c2ecf20Sopenharmony_ci		if ((_regs.trap & 0xfff0) == 0x3000) {		\
17638c2ecf20Sopenharmony_ci			/*					\
17648c2ecf20Sopenharmony_ci			 * scv 0 system call uses -ve result	\
17658c2ecf20Sopenharmony_ci			 * for error, so no need to adjust.	\
17668c2ecf20Sopenharmony_ci			 */					\
17678c2ecf20Sopenharmony_ci			SYSCALL_RET(_regs) = _result;		\
17688c2ecf20Sopenharmony_ci		} else {					\
17698c2ecf20Sopenharmony_ci			/*					\
17708c2ecf20Sopenharmony_ci			 * A syscall error is signaled by the	\
17718c2ecf20Sopenharmony_ci			 * CR0 SO bit and the code is stored as	\
17728c2ecf20Sopenharmony_ci			 * a positive value.			\
17738c2ecf20Sopenharmony_ci			 */					\
17748c2ecf20Sopenharmony_ci			if (_result < 0) {			\
17758c2ecf20Sopenharmony_ci				SYSCALL_RET(_regs) = -_result;	\
17768c2ecf20Sopenharmony_ci				(_regs).ccr |= 0x10000000;	\
17778c2ecf20Sopenharmony_ci			} else {				\
17788c2ecf20Sopenharmony_ci				SYSCALL_RET(_regs) = _result;	\
17798c2ecf20Sopenharmony_ci				(_regs).ccr &= ~0x10000000;	\
17808c2ecf20Sopenharmony_ci			}					\
17818c2ecf20Sopenharmony_ci		}						\
17828c2ecf20Sopenharmony_ci	} while (0)
17838c2ecf20Sopenharmony_ci# define SYSCALL_RET_SET_ON_PTRACE_EXIT
17848c2ecf20Sopenharmony_ci#elif defined(__s390__)
17858c2ecf20Sopenharmony_ci# define ARCH_REGS		s390_regs
17868c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).gprs[2]
17878c2ecf20Sopenharmony_ci# define SYSCALL_RET_SET(_regs, _val)			\
17888c2ecf20Sopenharmony_ci		TH_LOG("Can't modify syscall return on this architecture")
17898c2ecf20Sopenharmony_ci#elif defined(__mips__)
17908c2ecf20Sopenharmony_ci# include <asm/unistd_nr_n32.h>
17918c2ecf20Sopenharmony_ci# include <asm/unistd_nr_n64.h>
17928c2ecf20Sopenharmony_ci# include <asm/unistd_nr_o32.h>
17938c2ecf20Sopenharmony_ci# define ARCH_REGS		struct pt_regs
17948c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)				\
17958c2ecf20Sopenharmony_ci	({						\
17968c2ecf20Sopenharmony_ci		typeof((_regs).regs[2]) _nr;		\
17978c2ecf20Sopenharmony_ci		if ((_regs).regs[2] == __NR_O32_Linux)	\
17988c2ecf20Sopenharmony_ci			_nr = (_regs).regs[4];		\
17998c2ecf20Sopenharmony_ci		else					\
18008c2ecf20Sopenharmony_ci			_nr = (_regs).regs[2];		\
18018c2ecf20Sopenharmony_ci		_nr;					\
18028c2ecf20Sopenharmony_ci	})
18038c2ecf20Sopenharmony_ci# define SYSCALL_NUM_SET(_regs, _nr)			\
18048c2ecf20Sopenharmony_ci	do {						\
18058c2ecf20Sopenharmony_ci		if ((_regs).regs[2] == __NR_O32_Linux)	\
18068c2ecf20Sopenharmony_ci			(_regs).regs[4] = _nr;		\
18078c2ecf20Sopenharmony_ci		else					\
18088c2ecf20Sopenharmony_ci			(_regs).regs[2] = _nr;		\
18098c2ecf20Sopenharmony_ci	} while (0)
18108c2ecf20Sopenharmony_ci# define SYSCALL_RET_SET(_regs, _val)			\
18118c2ecf20Sopenharmony_ci		TH_LOG("Can't modify syscall return on this architecture")
18128c2ecf20Sopenharmony_ci#elif defined(__xtensa__)
18138c2ecf20Sopenharmony_ci# define ARCH_REGS		struct user_pt_regs
18148c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).syscall
18158c2ecf20Sopenharmony_ci/*
18168c2ecf20Sopenharmony_ci * On xtensa syscall return value is in the register
18178c2ecf20Sopenharmony_ci * a2 of the current window which is not fixed.
18188c2ecf20Sopenharmony_ci */
18198c2ecf20Sopenharmony_ci#define SYSCALL_RET(_regs)	(_regs).a[(_regs).windowbase * 4 + 2]
18208c2ecf20Sopenharmony_ci#elif defined(__sh__)
18218c2ecf20Sopenharmony_ci# define ARCH_REGS		struct pt_regs
18228c2ecf20Sopenharmony_ci# define SYSCALL_NUM(_regs)	(_regs).regs[3]
18238c2ecf20Sopenharmony_ci# define SYSCALL_RET(_regs)	(_regs).regs[0]
18248c2ecf20Sopenharmony_ci#else
18258c2ecf20Sopenharmony_ci# error "Do not know how to find your architecture's registers and syscalls"
18268c2ecf20Sopenharmony_ci#endif
18278c2ecf20Sopenharmony_ci
18288c2ecf20Sopenharmony_ci/*
18298c2ecf20Sopenharmony_ci * Most architectures can change the syscall by just updating the
18308c2ecf20Sopenharmony_ci * associated register. This is the default if not defined above.
18318c2ecf20Sopenharmony_ci */
18328c2ecf20Sopenharmony_ci#ifndef SYSCALL_NUM_SET
18338c2ecf20Sopenharmony_ci# define SYSCALL_NUM_SET(_regs, _nr)		\
18348c2ecf20Sopenharmony_ci	do {					\
18358c2ecf20Sopenharmony_ci		SYSCALL_NUM(_regs) = (_nr);	\
18368c2ecf20Sopenharmony_ci	} while (0)
18378c2ecf20Sopenharmony_ci#endif
18388c2ecf20Sopenharmony_ci/*
18398c2ecf20Sopenharmony_ci * Most architectures can change the syscall return value by just
18408c2ecf20Sopenharmony_ci * writing to the SYSCALL_RET register. This is the default if not
18418c2ecf20Sopenharmony_ci * defined above. If an architecture cannot set the return value
18428c2ecf20Sopenharmony_ci * (for example when the syscall and return value register is
18438c2ecf20Sopenharmony_ci * shared), report it with TH_LOG() in an arch-specific definition
18448c2ecf20Sopenharmony_ci * of SYSCALL_RET_SET() above, and leave SYSCALL_RET undefined.
18458c2ecf20Sopenharmony_ci */
18468c2ecf20Sopenharmony_ci#if !defined(SYSCALL_RET) && !defined(SYSCALL_RET_SET)
18478c2ecf20Sopenharmony_ci# error "One of SYSCALL_RET or SYSCALL_RET_SET is needed for this arch"
18488c2ecf20Sopenharmony_ci#endif
18498c2ecf20Sopenharmony_ci#ifndef SYSCALL_RET_SET
18508c2ecf20Sopenharmony_ci# define SYSCALL_RET_SET(_regs, _val)		\
18518c2ecf20Sopenharmony_ci	do {					\
18528c2ecf20Sopenharmony_ci		SYSCALL_RET(_regs) = (_val);	\
18538c2ecf20Sopenharmony_ci	} while (0)
18548c2ecf20Sopenharmony_ci#endif
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci/* When the syscall return can't be changed, stub out the tests for it. */
18578c2ecf20Sopenharmony_ci#ifndef SYSCALL_RET
18588c2ecf20Sopenharmony_ci# define EXPECT_SYSCALL_RETURN(val, action)	EXPECT_EQ(-1, action)
18598c2ecf20Sopenharmony_ci#else
18608c2ecf20Sopenharmony_ci# define EXPECT_SYSCALL_RETURN(val, action)		\
18618c2ecf20Sopenharmony_ci	do {						\
18628c2ecf20Sopenharmony_ci		errno = 0;				\
18638c2ecf20Sopenharmony_ci		if (val < 0) {				\
18648c2ecf20Sopenharmony_ci			EXPECT_EQ(-1, action);		\
18658c2ecf20Sopenharmony_ci			EXPECT_EQ(-(val), errno);	\
18668c2ecf20Sopenharmony_ci		} else {				\
18678c2ecf20Sopenharmony_ci			EXPECT_EQ(val, action);		\
18688c2ecf20Sopenharmony_ci		}					\
18698c2ecf20Sopenharmony_ci	} while (0)
18708c2ecf20Sopenharmony_ci#endif
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci/*
18738c2ecf20Sopenharmony_ci * Some architectures (e.g. powerpc) can only set syscall
18748c2ecf20Sopenharmony_ci * return values on syscall exit during ptrace.
18758c2ecf20Sopenharmony_ci */
18768c2ecf20Sopenharmony_ciconst bool ptrace_entry_set_syscall_nr = true;
18778c2ecf20Sopenharmony_ciconst bool ptrace_entry_set_syscall_ret =
18788c2ecf20Sopenharmony_ci#ifndef SYSCALL_RET_SET_ON_PTRACE_EXIT
18798c2ecf20Sopenharmony_ci	true;
18808c2ecf20Sopenharmony_ci#else
18818c2ecf20Sopenharmony_ci	false;
18828c2ecf20Sopenharmony_ci#endif
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci/*
18858c2ecf20Sopenharmony_ci * Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
18868c2ecf20Sopenharmony_ci * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
18878c2ecf20Sopenharmony_ci */
18888c2ecf20Sopenharmony_ci#if defined(__x86_64__) || defined(__i386__) || defined(__mips__)
18898c2ecf20Sopenharmony_ci# define ARCH_GETREGS(_regs)	ptrace(PTRACE_GETREGS, tracee, 0, &(_regs))
18908c2ecf20Sopenharmony_ci# define ARCH_SETREGS(_regs)	ptrace(PTRACE_SETREGS, tracee, 0, &(_regs))
18918c2ecf20Sopenharmony_ci#else
18928c2ecf20Sopenharmony_ci# define ARCH_GETREGS(_regs)	({					\
18938c2ecf20Sopenharmony_ci		struct iovec __v;					\
18948c2ecf20Sopenharmony_ci		__v.iov_base = &(_regs);				\
18958c2ecf20Sopenharmony_ci		__v.iov_len = sizeof(_regs);				\
18968c2ecf20Sopenharmony_ci		ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &__v);	\
18978c2ecf20Sopenharmony_ci	})
18988c2ecf20Sopenharmony_ci# define ARCH_SETREGS(_regs)	({					\
18998c2ecf20Sopenharmony_ci		struct iovec __v;					\
19008c2ecf20Sopenharmony_ci		__v.iov_base = &(_regs);				\
19018c2ecf20Sopenharmony_ci		__v.iov_len = sizeof(_regs);				\
19028c2ecf20Sopenharmony_ci		ptrace(PTRACE_SETREGSET, tracee, NT_PRSTATUS, &__v);	\
19038c2ecf20Sopenharmony_ci	})
19048c2ecf20Sopenharmony_ci#endif
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ci/* Architecture-specific syscall fetching routine. */
19078c2ecf20Sopenharmony_ciint get_syscall(struct __test_metadata *_metadata, pid_t tracee)
19088c2ecf20Sopenharmony_ci{
19098c2ecf20Sopenharmony_ci	ARCH_REGS regs;
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ARCH_GETREGS(regs)) {
19128c2ecf20Sopenharmony_ci		return -1;
19138c2ecf20Sopenharmony_ci	}
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	return SYSCALL_NUM(regs);
19168c2ecf20Sopenharmony_ci}
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_ci/* Architecture-specific syscall changing routine. */
19198c2ecf20Sopenharmony_civoid __change_syscall(struct __test_metadata *_metadata,
19208c2ecf20Sopenharmony_ci		    pid_t tracee, long *syscall, long *ret)
19218c2ecf20Sopenharmony_ci{
19228c2ecf20Sopenharmony_ci	ARCH_REGS orig, regs;
19238c2ecf20Sopenharmony_ci
19248c2ecf20Sopenharmony_ci	/* Do not get/set registers if we have nothing to do. */
19258c2ecf20Sopenharmony_ci	if (!syscall && !ret)
19268c2ecf20Sopenharmony_ci		return;
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ARCH_GETREGS(regs)) {
19298c2ecf20Sopenharmony_ci		return;
19308c2ecf20Sopenharmony_ci	}
19318c2ecf20Sopenharmony_ci	orig = regs;
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci	if (syscall)
19348c2ecf20Sopenharmony_ci		SYSCALL_NUM_SET(regs, *syscall);
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	if (ret)
19378c2ecf20Sopenharmony_ci		SYSCALL_RET_SET(regs, *ret);
19388c2ecf20Sopenharmony_ci
19398c2ecf20Sopenharmony_ci	/* Flush any register changes made. */
19408c2ecf20Sopenharmony_ci	if (memcmp(&orig, &regs, sizeof(orig)) != 0)
19418c2ecf20Sopenharmony_ci		EXPECT_EQ(0, ARCH_SETREGS(regs));
19428c2ecf20Sopenharmony_ci}
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci/* Change only syscall number. */
19458c2ecf20Sopenharmony_civoid change_syscall_nr(struct __test_metadata *_metadata,
19468c2ecf20Sopenharmony_ci		       pid_t tracee, long syscall)
19478c2ecf20Sopenharmony_ci{
19488c2ecf20Sopenharmony_ci	__change_syscall(_metadata, tracee, &syscall, NULL);
19498c2ecf20Sopenharmony_ci}
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci/* Change syscall return value (and set syscall number to -1). */
19528c2ecf20Sopenharmony_civoid change_syscall_ret(struct __test_metadata *_metadata,
19538c2ecf20Sopenharmony_ci			pid_t tracee, long ret)
19548c2ecf20Sopenharmony_ci{
19558c2ecf20Sopenharmony_ci	long syscall = -1;
19568c2ecf20Sopenharmony_ci
19578c2ecf20Sopenharmony_ci	__change_syscall(_metadata, tracee, &syscall, &ret);
19588c2ecf20Sopenharmony_ci}
19598c2ecf20Sopenharmony_ci
19608c2ecf20Sopenharmony_civoid tracer_seccomp(struct __test_metadata *_metadata, pid_t tracee,
19618c2ecf20Sopenharmony_ci		    int status, void *args)
19628c2ecf20Sopenharmony_ci{
19638c2ecf20Sopenharmony_ci	int ret;
19648c2ecf20Sopenharmony_ci	unsigned long msg;
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_ci	/* Make sure we got the right message. */
19678c2ecf20Sopenharmony_ci	ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
19688c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret);
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_ci	/* Validate and take action on expected syscalls. */
19718c2ecf20Sopenharmony_ci	switch (msg) {
19728c2ecf20Sopenharmony_ci	case 0x1002:
19738c2ecf20Sopenharmony_ci		/* change getpid to getppid. */
19748c2ecf20Sopenharmony_ci		EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
19758c2ecf20Sopenharmony_ci		change_syscall_nr(_metadata, tracee, __NR_getppid);
19768c2ecf20Sopenharmony_ci		break;
19778c2ecf20Sopenharmony_ci	case 0x1003:
19788c2ecf20Sopenharmony_ci		/* skip gettid with valid return code. */
19798c2ecf20Sopenharmony_ci		EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
19808c2ecf20Sopenharmony_ci		change_syscall_ret(_metadata, tracee, 45000);
19818c2ecf20Sopenharmony_ci		break;
19828c2ecf20Sopenharmony_ci	case 0x1004:
19838c2ecf20Sopenharmony_ci		/* skip openat with error. */
19848c2ecf20Sopenharmony_ci		EXPECT_EQ(__NR_openat, get_syscall(_metadata, tracee));
19858c2ecf20Sopenharmony_ci		change_syscall_ret(_metadata, tracee, -ESRCH);
19868c2ecf20Sopenharmony_ci		break;
19878c2ecf20Sopenharmony_ci	case 0x1005:
19888c2ecf20Sopenharmony_ci		/* do nothing (allow getppid) */
19898c2ecf20Sopenharmony_ci		EXPECT_EQ(__NR_getppid, get_syscall(_metadata, tracee));
19908c2ecf20Sopenharmony_ci		break;
19918c2ecf20Sopenharmony_ci	default:
19928c2ecf20Sopenharmony_ci		EXPECT_EQ(0, msg) {
19938c2ecf20Sopenharmony_ci			TH_LOG("Unknown PTRACE_GETEVENTMSG: 0x%lx", msg);
19948c2ecf20Sopenharmony_ci			kill(tracee, SIGKILL);
19958c2ecf20Sopenharmony_ci		}
19968c2ecf20Sopenharmony_ci	}
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci}
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ciFIXTURE(TRACE_syscall) {
20018c2ecf20Sopenharmony_ci	struct sock_fprog prog;
20028c2ecf20Sopenharmony_ci	pid_t tracer, mytid, mypid, parent;
20038c2ecf20Sopenharmony_ci	long syscall_nr;
20048c2ecf20Sopenharmony_ci};
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_civoid tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
20078c2ecf20Sopenharmony_ci		   int status, void *args)
20088c2ecf20Sopenharmony_ci{
20098c2ecf20Sopenharmony_ci	int ret;
20108c2ecf20Sopenharmony_ci	unsigned long msg;
20118c2ecf20Sopenharmony_ci	static bool entry;
20128c2ecf20Sopenharmony_ci	long syscall_nr_val, syscall_ret_val;
20138c2ecf20Sopenharmony_ci	long *syscall_nr = NULL, *syscall_ret = NULL;
20148c2ecf20Sopenharmony_ci	FIXTURE_DATA(TRACE_syscall) *self = args;
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci	/*
20178c2ecf20Sopenharmony_ci	 * The traditional way to tell PTRACE_SYSCALL entry/exit
20188c2ecf20Sopenharmony_ci	 * is by counting.
20198c2ecf20Sopenharmony_ci	 */
20208c2ecf20Sopenharmony_ci	entry = !entry;
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	/* Make sure we got an appropriate message. */
20238c2ecf20Sopenharmony_ci	ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
20248c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret);
20258c2ecf20Sopenharmony_ci	EXPECT_EQ(entry ? PTRACE_EVENTMSG_SYSCALL_ENTRY
20268c2ecf20Sopenharmony_ci			: PTRACE_EVENTMSG_SYSCALL_EXIT, msg);
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci	/*
20298c2ecf20Sopenharmony_ci	 * Some architectures only support setting return values during
20308c2ecf20Sopenharmony_ci	 * syscall exit under ptrace, and on exit the syscall number may
20318c2ecf20Sopenharmony_ci	 * no longer be available. Therefore, save the initial sycall
20328c2ecf20Sopenharmony_ci	 * number here, so it can be examined during both entry and exit
20338c2ecf20Sopenharmony_ci	 * phases.
20348c2ecf20Sopenharmony_ci	 */
20358c2ecf20Sopenharmony_ci	if (entry)
20368c2ecf20Sopenharmony_ci		self->syscall_nr = get_syscall(_metadata, tracee);
20378c2ecf20Sopenharmony_ci
20388c2ecf20Sopenharmony_ci	/*
20398c2ecf20Sopenharmony_ci	 * Depending on the architecture's syscall setting abilities, we
20408c2ecf20Sopenharmony_ci	 * pick which things to set during this phase (entry or exit).
20418c2ecf20Sopenharmony_ci	 */
20428c2ecf20Sopenharmony_ci	if (entry == ptrace_entry_set_syscall_nr)
20438c2ecf20Sopenharmony_ci		syscall_nr = &syscall_nr_val;
20448c2ecf20Sopenharmony_ci	if (entry == ptrace_entry_set_syscall_ret)
20458c2ecf20Sopenharmony_ci		syscall_ret = &syscall_ret_val;
20468c2ecf20Sopenharmony_ci
20478c2ecf20Sopenharmony_ci	/* Now handle the actual rewriting cases. */
20488c2ecf20Sopenharmony_ci	switch (self->syscall_nr) {
20498c2ecf20Sopenharmony_ci	case __NR_getpid:
20508c2ecf20Sopenharmony_ci		syscall_nr_val = __NR_getppid;
20518c2ecf20Sopenharmony_ci		/* Never change syscall return for this case. */
20528c2ecf20Sopenharmony_ci		syscall_ret = NULL;
20538c2ecf20Sopenharmony_ci		break;
20548c2ecf20Sopenharmony_ci	case __NR_gettid:
20558c2ecf20Sopenharmony_ci		syscall_nr_val = -1;
20568c2ecf20Sopenharmony_ci		syscall_ret_val = 45000;
20578c2ecf20Sopenharmony_ci		break;
20588c2ecf20Sopenharmony_ci	case __NR_openat:
20598c2ecf20Sopenharmony_ci		syscall_nr_val = -1;
20608c2ecf20Sopenharmony_ci		syscall_ret_val = -ESRCH;
20618c2ecf20Sopenharmony_ci		break;
20628c2ecf20Sopenharmony_ci	default:
20638c2ecf20Sopenharmony_ci		/* Unhandled, do nothing. */
20648c2ecf20Sopenharmony_ci		return;
20658c2ecf20Sopenharmony_ci	}
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ci	__change_syscall(_metadata, tracee, syscall_nr, syscall_ret);
20688c2ecf20Sopenharmony_ci}
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_ciFIXTURE_VARIANT(TRACE_syscall) {
20718c2ecf20Sopenharmony_ci	/*
20728c2ecf20Sopenharmony_ci	 * All of the SECCOMP_RET_TRACE behaviors can be tested with either
20738c2ecf20Sopenharmony_ci	 * SECCOMP_RET_TRACE+PTRACE_CONT or plain ptrace()+PTRACE_SYSCALL.
20748c2ecf20Sopenharmony_ci	 * This indicates if we should use SECCOMP_RET_TRACE (false), or
20758c2ecf20Sopenharmony_ci	 * ptrace (true).
20768c2ecf20Sopenharmony_ci	 */
20778c2ecf20Sopenharmony_ci	bool use_ptrace;
20788c2ecf20Sopenharmony_ci};
20798c2ecf20Sopenharmony_ci
20808c2ecf20Sopenharmony_ciFIXTURE_VARIANT_ADD(TRACE_syscall, ptrace) {
20818c2ecf20Sopenharmony_ci	.use_ptrace = true,
20828c2ecf20Sopenharmony_ci};
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_ciFIXTURE_VARIANT_ADD(TRACE_syscall, seccomp) {
20858c2ecf20Sopenharmony_ci	.use_ptrace = false,
20868c2ecf20Sopenharmony_ci};
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_ciFIXTURE_SETUP(TRACE_syscall)
20898c2ecf20Sopenharmony_ci{
20908c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
20918c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
20928c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
20938c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
20948c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1002),
20958c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_gettid, 0, 1),
20968c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1003),
20978c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_openat, 0, 1),
20988c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1004),
20998c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
21008c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1005),
21018c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
21028c2ecf20Sopenharmony_ci	};
21038c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
21048c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
21058c2ecf20Sopenharmony_ci		.filter = filter,
21068c2ecf20Sopenharmony_ci	};
21078c2ecf20Sopenharmony_ci	long ret;
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci	/* Prepare some testable syscall results. */
21108c2ecf20Sopenharmony_ci	self->mytid = syscall(__NR_gettid);
21118c2ecf20Sopenharmony_ci	ASSERT_GT(self->mytid, 0);
21128c2ecf20Sopenharmony_ci	ASSERT_NE(self->mytid, 1) {
21138c2ecf20Sopenharmony_ci		TH_LOG("Running this test as init is not supported. :)");
21148c2ecf20Sopenharmony_ci	}
21158c2ecf20Sopenharmony_ci
21168c2ecf20Sopenharmony_ci	self->mypid = getpid();
21178c2ecf20Sopenharmony_ci	ASSERT_GT(self->mypid, 0);
21188c2ecf20Sopenharmony_ci	ASSERT_EQ(self->mytid, self->mypid);
21198c2ecf20Sopenharmony_ci
21208c2ecf20Sopenharmony_ci	self->parent = getppid();
21218c2ecf20Sopenharmony_ci	ASSERT_GT(self->parent, 0);
21228c2ecf20Sopenharmony_ci	ASSERT_NE(self->parent, self->mypid);
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci	/* Launch tracer. */
21258c2ecf20Sopenharmony_ci	self->tracer = setup_trace_fixture(_metadata,
21268c2ecf20Sopenharmony_ci					   variant->use_ptrace ? tracer_ptrace
21278c2ecf20Sopenharmony_ci							       : tracer_seccomp,
21288c2ecf20Sopenharmony_ci					   self, variant->use_ptrace);
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
21318c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci	if (variant->use_ptrace)
21348c2ecf20Sopenharmony_ci		return;
21358c2ecf20Sopenharmony_ci
21368c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
21378c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
21388c2ecf20Sopenharmony_ci}
21398c2ecf20Sopenharmony_ci
21408c2ecf20Sopenharmony_ciFIXTURE_TEARDOWN(TRACE_syscall)
21418c2ecf20Sopenharmony_ci{
21428c2ecf20Sopenharmony_ci	teardown_trace_fixture(_metadata, self->tracer);
21438c2ecf20Sopenharmony_ci}
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_ciTEST(negative_ENOSYS)
21468c2ecf20Sopenharmony_ci{
21478c2ecf20Sopenharmony_ci	/*
21488c2ecf20Sopenharmony_ci	 * There should be no difference between an "internal" skip
21498c2ecf20Sopenharmony_ci	 * and userspace asking for syscall "-1".
21508c2ecf20Sopenharmony_ci	 */
21518c2ecf20Sopenharmony_ci	errno = 0;
21528c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, syscall(-1));
21538c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, ENOSYS);
21548c2ecf20Sopenharmony_ci	/* And no difference for "still not valid but not -1". */
21558c2ecf20Sopenharmony_ci	errno = 0;
21568c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, syscall(-101));
21578c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, ENOSYS);
21588c2ecf20Sopenharmony_ci}
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ciTEST_F(TRACE_syscall, negative_ENOSYS)
21618c2ecf20Sopenharmony_ci{
21628c2ecf20Sopenharmony_ci	negative_ENOSYS(_metadata);
21638c2ecf20Sopenharmony_ci}
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ciTEST_F(TRACE_syscall, syscall_allowed)
21668c2ecf20Sopenharmony_ci{
21678c2ecf20Sopenharmony_ci	/* getppid works as expected (no changes). */
21688c2ecf20Sopenharmony_ci	EXPECT_EQ(self->parent, syscall(__NR_getppid));
21698c2ecf20Sopenharmony_ci	EXPECT_NE(self->mypid, syscall(__NR_getppid));
21708c2ecf20Sopenharmony_ci}
21718c2ecf20Sopenharmony_ci
21728c2ecf20Sopenharmony_ciTEST_F(TRACE_syscall, syscall_redirected)
21738c2ecf20Sopenharmony_ci{
21748c2ecf20Sopenharmony_ci	/* getpid has been redirected to getppid as expected. */
21758c2ecf20Sopenharmony_ci	EXPECT_EQ(self->parent, syscall(__NR_getpid));
21768c2ecf20Sopenharmony_ci	EXPECT_NE(self->mypid, syscall(__NR_getpid));
21778c2ecf20Sopenharmony_ci}
21788c2ecf20Sopenharmony_ci
21798c2ecf20Sopenharmony_ciTEST_F(TRACE_syscall, syscall_errno)
21808c2ecf20Sopenharmony_ci{
21818c2ecf20Sopenharmony_ci	/* Tracer should skip the open syscall, resulting in ESRCH. */
21828c2ecf20Sopenharmony_ci	EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
21838c2ecf20Sopenharmony_ci}
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_ciTEST_F(TRACE_syscall, syscall_faked)
21868c2ecf20Sopenharmony_ci{
21878c2ecf20Sopenharmony_ci	/* Tracer skips the gettid syscall and store altered return value. */
21888c2ecf20Sopenharmony_ci	EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
21898c2ecf20Sopenharmony_ci}
21908c2ecf20Sopenharmony_ci
21918c2ecf20Sopenharmony_ciTEST_F(TRACE_syscall, skip_after)
21928c2ecf20Sopenharmony_ci{
21938c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
21948c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
21958c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
21968c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
21978c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EPERM),
21988c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
21998c2ecf20Sopenharmony_ci	};
22008c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
22018c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
22028c2ecf20Sopenharmony_ci		.filter = filter,
22038c2ecf20Sopenharmony_ci	};
22048c2ecf20Sopenharmony_ci	long ret;
22058c2ecf20Sopenharmony_ci
22068c2ecf20Sopenharmony_ci	/* Install additional "errno on getppid" filter. */
22078c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
22088c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci	/* Tracer will redirect getpid to getppid, and we should see EPERM. */
22118c2ecf20Sopenharmony_ci	errno = 0;
22128c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, syscall(__NR_getpid));
22138c2ecf20Sopenharmony_ci	EXPECT_EQ(EPERM, errno);
22148c2ecf20Sopenharmony_ci}
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_ciTEST_F_SIGNAL(TRACE_syscall, kill_after, SIGSYS)
22178c2ecf20Sopenharmony_ci{
22188c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
22198c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
22208c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
22218c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
22228c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
22238c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
22248c2ecf20Sopenharmony_ci	};
22258c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
22268c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
22278c2ecf20Sopenharmony_ci		.filter = filter,
22288c2ecf20Sopenharmony_ci	};
22298c2ecf20Sopenharmony_ci	long ret;
22308c2ecf20Sopenharmony_ci
22318c2ecf20Sopenharmony_ci	/* Install additional "death on getppid" filter. */
22328c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
22338c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_ci	/* Tracer will redirect getpid to getppid, and we should die. */
22368c2ecf20Sopenharmony_ci	EXPECT_NE(self->mypid, syscall(__NR_getpid));
22378c2ecf20Sopenharmony_ci}
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ciTEST(seccomp_syscall)
22408c2ecf20Sopenharmony_ci{
22418c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
22428c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
22438c2ecf20Sopenharmony_ci	};
22448c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
22458c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
22468c2ecf20Sopenharmony_ci		.filter = filter,
22478c2ecf20Sopenharmony_ci	};
22488c2ecf20Sopenharmony_ci	long ret;
22498c2ecf20Sopenharmony_ci
22508c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
22518c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
22528c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
22538c2ecf20Sopenharmony_ci	}
22548c2ecf20Sopenharmony_ci
22558c2ecf20Sopenharmony_ci	/* Reject insane operation. */
22568c2ecf20Sopenharmony_ci	ret = seccomp(-1, 0, &prog);
22578c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
22588c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
22598c2ecf20Sopenharmony_ci	}
22608c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno) {
22618c2ecf20Sopenharmony_ci		TH_LOG("Did not reject crazy op value!");
22628c2ecf20Sopenharmony_ci	}
22638c2ecf20Sopenharmony_ci
22648c2ecf20Sopenharmony_ci	/* Reject strict with flags or pointer. */
22658c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_STRICT, -1, NULL);
22668c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno) {
22678c2ecf20Sopenharmony_ci		TH_LOG("Did not reject mode strict with flags!");
22688c2ecf20Sopenharmony_ci	}
22698c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_STRICT, 0, &prog);
22708c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno) {
22718c2ecf20Sopenharmony_ci		TH_LOG("Did not reject mode strict with uargs!");
22728c2ecf20Sopenharmony_ci	}
22738c2ecf20Sopenharmony_ci
22748c2ecf20Sopenharmony_ci	/* Reject insane args for filter. */
22758c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, -1, &prog);
22768c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno) {
22778c2ecf20Sopenharmony_ci		TH_LOG("Did not reject crazy filter flags!");
22788c2ecf20Sopenharmony_ci	}
22798c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, NULL);
22808c2ecf20Sopenharmony_ci	EXPECT_EQ(EFAULT, errno) {
22818c2ecf20Sopenharmony_ci		TH_LOG("Did not reject NULL filter!");
22828c2ecf20Sopenharmony_ci	}
22838c2ecf20Sopenharmony_ci
22848c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
22858c2ecf20Sopenharmony_ci	EXPECT_EQ(0, errno) {
22868c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER: %s",
22878c2ecf20Sopenharmony_ci			strerror(errno));
22888c2ecf20Sopenharmony_ci	}
22898c2ecf20Sopenharmony_ci}
22908c2ecf20Sopenharmony_ci
22918c2ecf20Sopenharmony_ciTEST(seccomp_syscall_mode_lock)
22928c2ecf20Sopenharmony_ci{
22938c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
22948c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
22958c2ecf20Sopenharmony_ci	};
22968c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
22978c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
22988c2ecf20Sopenharmony_ci		.filter = filter,
22998c2ecf20Sopenharmony_ci	};
23008c2ecf20Sopenharmony_ci	long ret;
23018c2ecf20Sopenharmony_ci
23028c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
23038c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
23048c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
23058c2ecf20Sopenharmony_ci	}
23068c2ecf20Sopenharmony_ci
23078c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
23088c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
23098c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
23108c2ecf20Sopenharmony_ci	}
23118c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret) {
23128c2ecf20Sopenharmony_ci		TH_LOG("Could not install filter!");
23138c2ecf20Sopenharmony_ci	}
23148c2ecf20Sopenharmony_ci
23158c2ecf20Sopenharmony_ci	/* Make sure neither entry point will switch to strict. */
23168c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, 0, 0, 0);
23178c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno) {
23188c2ecf20Sopenharmony_ci		TH_LOG("Switched to mode strict!");
23198c2ecf20Sopenharmony_ci	}
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_STRICT, 0, NULL);
23228c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno) {
23238c2ecf20Sopenharmony_ci		TH_LOG("Switched to mode strict!");
23248c2ecf20Sopenharmony_ci	}
23258c2ecf20Sopenharmony_ci}
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci/*
23288c2ecf20Sopenharmony_ci * Test detection of known and unknown filter flags. Userspace needs to be able
23298c2ecf20Sopenharmony_ci * to check if a filter flag is supported by the current kernel and a good way
23308c2ecf20Sopenharmony_ci * of doing that is by attempting to enter filter mode, with the flag bit in
23318c2ecf20Sopenharmony_ci * question set, and a NULL pointer for the _args_ parameter. EFAULT indicates
23328c2ecf20Sopenharmony_ci * that the flag is valid and EINVAL indicates that the flag is invalid.
23338c2ecf20Sopenharmony_ci */
23348c2ecf20Sopenharmony_ciTEST(detect_seccomp_filter_flags)
23358c2ecf20Sopenharmony_ci{
23368c2ecf20Sopenharmony_ci	unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
23378c2ecf20Sopenharmony_ci				 SECCOMP_FILTER_FLAG_LOG,
23388c2ecf20Sopenharmony_ci				 SECCOMP_FILTER_FLAG_SPEC_ALLOW,
23398c2ecf20Sopenharmony_ci				 SECCOMP_FILTER_FLAG_NEW_LISTENER,
23408c2ecf20Sopenharmony_ci				 SECCOMP_FILTER_FLAG_TSYNC_ESRCH };
23418c2ecf20Sopenharmony_ci	unsigned int exclusive[] = {
23428c2ecf20Sopenharmony_ci				SECCOMP_FILTER_FLAG_TSYNC,
23438c2ecf20Sopenharmony_ci				SECCOMP_FILTER_FLAG_NEW_LISTENER };
23448c2ecf20Sopenharmony_ci	unsigned int flag, all_flags, exclusive_mask;
23458c2ecf20Sopenharmony_ci	int i;
23468c2ecf20Sopenharmony_ci	long ret;
23478c2ecf20Sopenharmony_ci
23488c2ecf20Sopenharmony_ci	/* Test detection of individual known-good filter flags */
23498c2ecf20Sopenharmony_ci	for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
23508c2ecf20Sopenharmony_ci		int bits = 0;
23518c2ecf20Sopenharmony_ci
23528c2ecf20Sopenharmony_ci		flag = flags[i];
23538c2ecf20Sopenharmony_ci		/* Make sure the flag is a single bit! */
23548c2ecf20Sopenharmony_ci		while (flag) {
23558c2ecf20Sopenharmony_ci			if (flag & 0x1)
23568c2ecf20Sopenharmony_ci				bits ++;
23578c2ecf20Sopenharmony_ci			flag >>= 1;
23588c2ecf20Sopenharmony_ci		}
23598c2ecf20Sopenharmony_ci		ASSERT_EQ(1, bits);
23608c2ecf20Sopenharmony_ci		flag = flags[i];
23618c2ecf20Sopenharmony_ci
23628c2ecf20Sopenharmony_ci		ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
23638c2ecf20Sopenharmony_ci		ASSERT_NE(ENOSYS, errno) {
23648c2ecf20Sopenharmony_ci			TH_LOG("Kernel does not support seccomp syscall!");
23658c2ecf20Sopenharmony_ci		}
23668c2ecf20Sopenharmony_ci		EXPECT_EQ(-1, ret);
23678c2ecf20Sopenharmony_ci		EXPECT_EQ(EFAULT, errno) {
23688c2ecf20Sopenharmony_ci			TH_LOG("Failed to detect that a known-good filter flag (0x%X) is supported!",
23698c2ecf20Sopenharmony_ci			       flag);
23708c2ecf20Sopenharmony_ci		}
23718c2ecf20Sopenharmony_ci
23728c2ecf20Sopenharmony_ci		all_flags |= flag;
23738c2ecf20Sopenharmony_ci	}
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci	/*
23768c2ecf20Sopenharmony_ci	 * Test detection of all known-good filter flags combined. But
23778c2ecf20Sopenharmony_ci	 * for the exclusive flags we need to mask them out and try them
23788c2ecf20Sopenharmony_ci	 * individually for the "all flags" testing.
23798c2ecf20Sopenharmony_ci	 */
23808c2ecf20Sopenharmony_ci	exclusive_mask = 0;
23818c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(exclusive); i++)
23828c2ecf20Sopenharmony_ci		exclusive_mask |= exclusive[i];
23838c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(exclusive); i++) {
23848c2ecf20Sopenharmony_ci		flag = all_flags & ~exclusive_mask;
23858c2ecf20Sopenharmony_ci		flag |= exclusive[i];
23868c2ecf20Sopenharmony_ci
23878c2ecf20Sopenharmony_ci		ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
23888c2ecf20Sopenharmony_ci		EXPECT_EQ(-1, ret);
23898c2ecf20Sopenharmony_ci		EXPECT_EQ(EFAULT, errno) {
23908c2ecf20Sopenharmony_ci			TH_LOG("Failed to detect that all known-good filter flags (0x%X) are supported!",
23918c2ecf20Sopenharmony_ci			       flag);
23928c2ecf20Sopenharmony_ci		}
23938c2ecf20Sopenharmony_ci	}
23948c2ecf20Sopenharmony_ci
23958c2ecf20Sopenharmony_ci	/* Test detection of an unknown filter flags, without exclusives. */
23968c2ecf20Sopenharmony_ci	flag = -1;
23978c2ecf20Sopenharmony_ci	flag &= ~exclusive_mask;
23988c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
23998c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, ret);
24008c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno) {
24018c2ecf20Sopenharmony_ci		TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported!",
24028c2ecf20Sopenharmony_ci		       flag);
24038c2ecf20Sopenharmony_ci	}
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci	/*
24068c2ecf20Sopenharmony_ci	 * Test detection of an unknown filter flag that may simply need to be
24078c2ecf20Sopenharmony_ci	 * added to this test
24088c2ecf20Sopenharmony_ci	 */
24098c2ecf20Sopenharmony_ci	flag = flags[ARRAY_SIZE(flags) - 1] << 1;
24108c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
24118c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, ret);
24128c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno) {
24138c2ecf20Sopenharmony_ci		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?",
24148c2ecf20Sopenharmony_ci		       flag);
24158c2ecf20Sopenharmony_ci	}
24168c2ecf20Sopenharmony_ci}
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_ciTEST(TSYNC_first)
24198c2ecf20Sopenharmony_ci{
24208c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
24218c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
24228c2ecf20Sopenharmony_ci	};
24238c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
24248c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
24258c2ecf20Sopenharmony_ci		.filter = filter,
24268c2ecf20Sopenharmony_ci	};
24278c2ecf20Sopenharmony_ci	long ret;
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
24308c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
24318c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
24328c2ecf20Sopenharmony_ci	}
24338c2ecf20Sopenharmony_ci
24348c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
24358c2ecf20Sopenharmony_ci		      &prog);
24368c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
24378c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
24388c2ecf20Sopenharmony_ci	}
24398c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret) {
24408c2ecf20Sopenharmony_ci		TH_LOG("Could not install initial filter with TSYNC!");
24418c2ecf20Sopenharmony_ci	}
24428c2ecf20Sopenharmony_ci}
24438c2ecf20Sopenharmony_ci
24448c2ecf20Sopenharmony_ci#define TSYNC_SIBLINGS 2
24458c2ecf20Sopenharmony_cistruct tsync_sibling {
24468c2ecf20Sopenharmony_ci	pthread_t tid;
24478c2ecf20Sopenharmony_ci	pid_t system_tid;
24488c2ecf20Sopenharmony_ci	sem_t *started;
24498c2ecf20Sopenharmony_ci	pthread_cond_t *cond;
24508c2ecf20Sopenharmony_ci	pthread_mutex_t *mutex;
24518c2ecf20Sopenharmony_ci	int diverge;
24528c2ecf20Sopenharmony_ci	int num_waits;
24538c2ecf20Sopenharmony_ci	struct sock_fprog *prog;
24548c2ecf20Sopenharmony_ci	struct __test_metadata *metadata;
24558c2ecf20Sopenharmony_ci};
24568c2ecf20Sopenharmony_ci
24578c2ecf20Sopenharmony_ci/*
24588c2ecf20Sopenharmony_ci * To avoid joining joined threads (which is not allowed by Bionic),
24598c2ecf20Sopenharmony_ci * make sure we both successfully join and clear the tid to skip a
24608c2ecf20Sopenharmony_ci * later join attempt during fixture teardown. Any remaining threads
24618c2ecf20Sopenharmony_ci * will be directly killed during teardown.
24628c2ecf20Sopenharmony_ci */
24638c2ecf20Sopenharmony_ci#define PTHREAD_JOIN(tid, status)					\
24648c2ecf20Sopenharmony_ci	do {								\
24658c2ecf20Sopenharmony_ci		int _rc = pthread_join(tid, status);			\
24668c2ecf20Sopenharmony_ci		if (_rc) {						\
24678c2ecf20Sopenharmony_ci			TH_LOG("pthread_join of tid %u failed: %d\n",	\
24688c2ecf20Sopenharmony_ci				(unsigned int)tid, _rc);		\
24698c2ecf20Sopenharmony_ci		} else {						\
24708c2ecf20Sopenharmony_ci			tid = 0;					\
24718c2ecf20Sopenharmony_ci		}							\
24728c2ecf20Sopenharmony_ci	} while (0)
24738c2ecf20Sopenharmony_ci
24748c2ecf20Sopenharmony_ciFIXTURE(TSYNC) {
24758c2ecf20Sopenharmony_ci	struct sock_fprog root_prog, apply_prog;
24768c2ecf20Sopenharmony_ci	struct tsync_sibling sibling[TSYNC_SIBLINGS];
24778c2ecf20Sopenharmony_ci	sem_t started;
24788c2ecf20Sopenharmony_ci	pthread_cond_t cond;
24798c2ecf20Sopenharmony_ci	pthread_mutex_t mutex;
24808c2ecf20Sopenharmony_ci	int sibling_count;
24818c2ecf20Sopenharmony_ci};
24828c2ecf20Sopenharmony_ci
24838c2ecf20Sopenharmony_ciFIXTURE_SETUP(TSYNC)
24848c2ecf20Sopenharmony_ci{
24858c2ecf20Sopenharmony_ci	struct sock_filter root_filter[] = {
24868c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
24878c2ecf20Sopenharmony_ci	};
24888c2ecf20Sopenharmony_ci	struct sock_filter apply_filter[] = {
24898c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
24908c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
24918c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
24928c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
24938c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
24948c2ecf20Sopenharmony_ci	};
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	memset(&self->root_prog, 0, sizeof(self->root_prog));
24978c2ecf20Sopenharmony_ci	memset(&self->apply_prog, 0, sizeof(self->apply_prog));
24988c2ecf20Sopenharmony_ci	memset(&self->sibling, 0, sizeof(self->sibling));
24998c2ecf20Sopenharmony_ci	self->root_prog.filter = malloc(sizeof(root_filter));
25008c2ecf20Sopenharmony_ci	ASSERT_NE(NULL, self->root_prog.filter);
25018c2ecf20Sopenharmony_ci	memcpy(self->root_prog.filter, &root_filter, sizeof(root_filter));
25028c2ecf20Sopenharmony_ci	self->root_prog.len = (unsigned short)ARRAY_SIZE(root_filter);
25038c2ecf20Sopenharmony_ci
25048c2ecf20Sopenharmony_ci	self->apply_prog.filter = malloc(sizeof(apply_filter));
25058c2ecf20Sopenharmony_ci	ASSERT_NE(NULL, self->apply_prog.filter);
25068c2ecf20Sopenharmony_ci	memcpy(self->apply_prog.filter, &apply_filter, sizeof(apply_filter));
25078c2ecf20Sopenharmony_ci	self->apply_prog.len = (unsigned short)ARRAY_SIZE(apply_filter);
25088c2ecf20Sopenharmony_ci
25098c2ecf20Sopenharmony_ci	self->sibling_count = 0;
25108c2ecf20Sopenharmony_ci	pthread_mutex_init(&self->mutex, NULL);
25118c2ecf20Sopenharmony_ci	pthread_cond_init(&self->cond, NULL);
25128c2ecf20Sopenharmony_ci	sem_init(&self->started, 0, 0);
25138c2ecf20Sopenharmony_ci	self->sibling[0].tid = 0;
25148c2ecf20Sopenharmony_ci	self->sibling[0].cond = &self->cond;
25158c2ecf20Sopenharmony_ci	self->sibling[0].started = &self->started;
25168c2ecf20Sopenharmony_ci	self->sibling[0].mutex = &self->mutex;
25178c2ecf20Sopenharmony_ci	self->sibling[0].diverge = 0;
25188c2ecf20Sopenharmony_ci	self->sibling[0].num_waits = 1;
25198c2ecf20Sopenharmony_ci	self->sibling[0].prog = &self->root_prog;
25208c2ecf20Sopenharmony_ci	self->sibling[0].metadata = _metadata;
25218c2ecf20Sopenharmony_ci	self->sibling[1].tid = 0;
25228c2ecf20Sopenharmony_ci	self->sibling[1].cond = &self->cond;
25238c2ecf20Sopenharmony_ci	self->sibling[1].started = &self->started;
25248c2ecf20Sopenharmony_ci	self->sibling[1].mutex = &self->mutex;
25258c2ecf20Sopenharmony_ci	self->sibling[1].diverge = 0;
25268c2ecf20Sopenharmony_ci	self->sibling[1].prog = &self->root_prog;
25278c2ecf20Sopenharmony_ci	self->sibling[1].num_waits = 1;
25288c2ecf20Sopenharmony_ci	self->sibling[1].metadata = _metadata;
25298c2ecf20Sopenharmony_ci}
25308c2ecf20Sopenharmony_ci
25318c2ecf20Sopenharmony_ciFIXTURE_TEARDOWN(TSYNC)
25328c2ecf20Sopenharmony_ci{
25338c2ecf20Sopenharmony_ci	int sib = 0;
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_ci	if (self->root_prog.filter)
25368c2ecf20Sopenharmony_ci		free(self->root_prog.filter);
25378c2ecf20Sopenharmony_ci	if (self->apply_prog.filter)
25388c2ecf20Sopenharmony_ci		free(self->apply_prog.filter);
25398c2ecf20Sopenharmony_ci
25408c2ecf20Sopenharmony_ci	for ( ; sib < self->sibling_count; ++sib) {
25418c2ecf20Sopenharmony_ci		struct tsync_sibling *s = &self->sibling[sib];
25428c2ecf20Sopenharmony_ci
25438c2ecf20Sopenharmony_ci		if (!s->tid)
25448c2ecf20Sopenharmony_ci			continue;
25458c2ecf20Sopenharmony_ci		/*
25468c2ecf20Sopenharmony_ci		 * If a thread is still running, it may be stuck, so hit
25478c2ecf20Sopenharmony_ci		 * it over the head really hard.
25488c2ecf20Sopenharmony_ci		 */
25498c2ecf20Sopenharmony_ci		pthread_kill(s->tid, 9);
25508c2ecf20Sopenharmony_ci	}
25518c2ecf20Sopenharmony_ci	pthread_mutex_destroy(&self->mutex);
25528c2ecf20Sopenharmony_ci	pthread_cond_destroy(&self->cond);
25538c2ecf20Sopenharmony_ci	sem_destroy(&self->started);
25548c2ecf20Sopenharmony_ci}
25558c2ecf20Sopenharmony_ci
25568c2ecf20Sopenharmony_civoid *tsync_sibling(void *data)
25578c2ecf20Sopenharmony_ci{
25588c2ecf20Sopenharmony_ci	long ret = 0;
25598c2ecf20Sopenharmony_ci	struct tsync_sibling *me = data;
25608c2ecf20Sopenharmony_ci
25618c2ecf20Sopenharmony_ci	me->system_tid = syscall(__NR_gettid);
25628c2ecf20Sopenharmony_ci
25638c2ecf20Sopenharmony_ci	pthread_mutex_lock(me->mutex);
25648c2ecf20Sopenharmony_ci	if (me->diverge) {
25658c2ecf20Sopenharmony_ci		/* Just re-apply the root prog to fork the tree */
25668c2ecf20Sopenharmony_ci		ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER,
25678c2ecf20Sopenharmony_ci				me->prog, 0, 0);
25688c2ecf20Sopenharmony_ci	}
25698c2ecf20Sopenharmony_ci	sem_post(me->started);
25708c2ecf20Sopenharmony_ci	/* Return outside of started so parent notices failures. */
25718c2ecf20Sopenharmony_ci	if (ret) {
25728c2ecf20Sopenharmony_ci		pthread_mutex_unlock(me->mutex);
25738c2ecf20Sopenharmony_ci		return (void *)SIBLING_EXIT_FAILURE;
25748c2ecf20Sopenharmony_ci	}
25758c2ecf20Sopenharmony_ci	do {
25768c2ecf20Sopenharmony_ci		pthread_cond_wait(me->cond, me->mutex);
25778c2ecf20Sopenharmony_ci		me->num_waits = me->num_waits - 1;
25788c2ecf20Sopenharmony_ci	} while (me->num_waits);
25798c2ecf20Sopenharmony_ci	pthread_mutex_unlock(me->mutex);
25808c2ecf20Sopenharmony_ci
25818c2ecf20Sopenharmony_ci	ret = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
25828c2ecf20Sopenharmony_ci	if (!ret)
25838c2ecf20Sopenharmony_ci		return (void *)SIBLING_EXIT_NEWPRIVS;
25848c2ecf20Sopenharmony_ci	read(-1, NULL, 0);
25858c2ecf20Sopenharmony_ci	return (void *)SIBLING_EXIT_UNKILLED;
25868c2ecf20Sopenharmony_ci}
25878c2ecf20Sopenharmony_ci
25888c2ecf20Sopenharmony_civoid tsync_start_sibling(struct tsync_sibling *sibling)
25898c2ecf20Sopenharmony_ci{
25908c2ecf20Sopenharmony_ci	pthread_create(&sibling->tid, NULL, tsync_sibling, (void *)sibling);
25918c2ecf20Sopenharmony_ci}
25928c2ecf20Sopenharmony_ci
25938c2ecf20Sopenharmony_ciTEST_F(TSYNC, siblings_fail_prctl)
25948c2ecf20Sopenharmony_ci{
25958c2ecf20Sopenharmony_ci	long ret;
25968c2ecf20Sopenharmony_ci	void *status;
25978c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
25988c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
25998c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
26008c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
26018c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EINVAL),
26028c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
26038c2ecf20Sopenharmony_ci	};
26048c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
26058c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
26068c2ecf20Sopenharmony_ci		.filter = filter,
26078c2ecf20Sopenharmony_ci	};
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
26108c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
26118c2ecf20Sopenharmony_ci	}
26128c2ecf20Sopenharmony_ci
26138c2ecf20Sopenharmony_ci	/* Check prctl failure detection by requesting sib 0 diverge. */
26148c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
26158c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
26168c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
26178c2ecf20Sopenharmony_ci	}
26188c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
26198c2ecf20Sopenharmony_ci		TH_LOG("setting filter failed");
26208c2ecf20Sopenharmony_ci	}
26218c2ecf20Sopenharmony_ci
26228c2ecf20Sopenharmony_ci	self->sibling[0].diverge = 1;
26238c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[0]);
26248c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[1]);
26258c2ecf20Sopenharmony_ci
26268c2ecf20Sopenharmony_ci	while (self->sibling_count < TSYNC_SIBLINGS) {
26278c2ecf20Sopenharmony_ci		sem_wait(&self->started);
26288c2ecf20Sopenharmony_ci		self->sibling_count++;
26298c2ecf20Sopenharmony_ci	}
26308c2ecf20Sopenharmony_ci
26318c2ecf20Sopenharmony_ci	/* Signal the threads to clean up*/
26328c2ecf20Sopenharmony_ci	pthread_mutex_lock(&self->mutex);
26338c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
26348c2ecf20Sopenharmony_ci		TH_LOG("cond broadcast non-zero");
26358c2ecf20Sopenharmony_ci	}
26368c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&self->mutex);
26378c2ecf20Sopenharmony_ci
26388c2ecf20Sopenharmony_ci	/* Ensure diverging sibling failed to call prctl. */
26398c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[0].tid, &status);
26408c2ecf20Sopenharmony_ci	EXPECT_EQ(SIBLING_EXIT_FAILURE, (long)status);
26418c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[1].tid, &status);
26428c2ecf20Sopenharmony_ci	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
26438c2ecf20Sopenharmony_ci}
26448c2ecf20Sopenharmony_ci
26458c2ecf20Sopenharmony_ciTEST_F(TSYNC, two_siblings_with_ancestor)
26468c2ecf20Sopenharmony_ci{
26478c2ecf20Sopenharmony_ci	long ret;
26488c2ecf20Sopenharmony_ci	void *status;
26498c2ecf20Sopenharmony_ci
26508c2ecf20Sopenharmony_ci	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
26518c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
26528c2ecf20Sopenharmony_ci	}
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
26558c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
26568c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
26578c2ecf20Sopenharmony_ci	}
26588c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
26598c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
26608c2ecf20Sopenharmony_ci	}
26618c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[0]);
26628c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[1]);
26638c2ecf20Sopenharmony_ci
26648c2ecf20Sopenharmony_ci	while (self->sibling_count < TSYNC_SIBLINGS) {
26658c2ecf20Sopenharmony_ci		sem_wait(&self->started);
26668c2ecf20Sopenharmony_ci		self->sibling_count++;
26678c2ecf20Sopenharmony_ci	}
26688c2ecf20Sopenharmony_ci
26698c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
26708c2ecf20Sopenharmony_ci		      &self->apply_prog);
26718c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
26728c2ecf20Sopenharmony_ci		TH_LOG("Could install filter on all threads!");
26738c2ecf20Sopenharmony_ci	}
26748c2ecf20Sopenharmony_ci	/* Tell the siblings to test the policy */
26758c2ecf20Sopenharmony_ci	pthread_mutex_lock(&self->mutex);
26768c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
26778c2ecf20Sopenharmony_ci		TH_LOG("cond broadcast non-zero");
26788c2ecf20Sopenharmony_ci	}
26798c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&self->mutex);
26808c2ecf20Sopenharmony_ci	/* Ensure they are both killed and don't exit cleanly. */
26818c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[0].tid, &status);
26828c2ecf20Sopenharmony_ci	EXPECT_EQ(0x0, (long)status);
26838c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[1].tid, &status);
26848c2ecf20Sopenharmony_ci	EXPECT_EQ(0x0, (long)status);
26858c2ecf20Sopenharmony_ci}
26868c2ecf20Sopenharmony_ci
26878c2ecf20Sopenharmony_ciTEST_F(TSYNC, two_sibling_want_nnp)
26888c2ecf20Sopenharmony_ci{
26898c2ecf20Sopenharmony_ci	void *status;
26908c2ecf20Sopenharmony_ci
26918c2ecf20Sopenharmony_ci	/* start siblings before any prctl() operations */
26928c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[0]);
26938c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[1]);
26948c2ecf20Sopenharmony_ci	while (self->sibling_count < TSYNC_SIBLINGS) {
26958c2ecf20Sopenharmony_ci		sem_wait(&self->started);
26968c2ecf20Sopenharmony_ci		self->sibling_count++;
26978c2ecf20Sopenharmony_ci	}
26988c2ecf20Sopenharmony_ci
26998c2ecf20Sopenharmony_ci	/* Tell the siblings to test no policy */
27008c2ecf20Sopenharmony_ci	pthread_mutex_lock(&self->mutex);
27018c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
27028c2ecf20Sopenharmony_ci		TH_LOG("cond broadcast non-zero");
27038c2ecf20Sopenharmony_ci	}
27048c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&self->mutex);
27058c2ecf20Sopenharmony_ci
27068c2ecf20Sopenharmony_ci	/* Ensure they are both upset about lacking nnp. */
27078c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[0].tid, &status);
27088c2ecf20Sopenharmony_ci	EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
27098c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[1].tid, &status);
27108c2ecf20Sopenharmony_ci	EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
27118c2ecf20Sopenharmony_ci}
27128c2ecf20Sopenharmony_ci
27138c2ecf20Sopenharmony_ciTEST_F(TSYNC, two_siblings_with_no_filter)
27148c2ecf20Sopenharmony_ci{
27158c2ecf20Sopenharmony_ci	long ret;
27168c2ecf20Sopenharmony_ci	void *status;
27178c2ecf20Sopenharmony_ci
27188c2ecf20Sopenharmony_ci	/* start siblings before any prctl() operations */
27198c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[0]);
27208c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[1]);
27218c2ecf20Sopenharmony_ci	while (self->sibling_count < TSYNC_SIBLINGS) {
27228c2ecf20Sopenharmony_ci		sem_wait(&self->started);
27238c2ecf20Sopenharmony_ci		self->sibling_count++;
27248c2ecf20Sopenharmony_ci	}
27258c2ecf20Sopenharmony_ci
27268c2ecf20Sopenharmony_ci	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
27278c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
27288c2ecf20Sopenharmony_ci	}
27298c2ecf20Sopenharmony_ci
27308c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
27318c2ecf20Sopenharmony_ci		      &self->apply_prog);
27328c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
27338c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
27348c2ecf20Sopenharmony_ci	}
27358c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
27368c2ecf20Sopenharmony_ci		TH_LOG("Could install filter on all threads!");
27378c2ecf20Sopenharmony_ci	}
27388c2ecf20Sopenharmony_ci
27398c2ecf20Sopenharmony_ci	/* Tell the siblings to test the policy */
27408c2ecf20Sopenharmony_ci	pthread_mutex_lock(&self->mutex);
27418c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
27428c2ecf20Sopenharmony_ci		TH_LOG("cond broadcast non-zero");
27438c2ecf20Sopenharmony_ci	}
27448c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&self->mutex);
27458c2ecf20Sopenharmony_ci
27468c2ecf20Sopenharmony_ci	/* Ensure they are both killed and don't exit cleanly. */
27478c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[0].tid, &status);
27488c2ecf20Sopenharmony_ci	EXPECT_EQ(0x0, (long)status);
27498c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[1].tid, &status);
27508c2ecf20Sopenharmony_ci	EXPECT_EQ(0x0, (long)status);
27518c2ecf20Sopenharmony_ci}
27528c2ecf20Sopenharmony_ci
27538c2ecf20Sopenharmony_ciTEST_F(TSYNC, two_siblings_with_one_divergence)
27548c2ecf20Sopenharmony_ci{
27558c2ecf20Sopenharmony_ci	long ret;
27568c2ecf20Sopenharmony_ci	void *status;
27578c2ecf20Sopenharmony_ci
27588c2ecf20Sopenharmony_ci	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
27598c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
27608c2ecf20Sopenharmony_ci	}
27618c2ecf20Sopenharmony_ci
27628c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
27638c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
27648c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
27658c2ecf20Sopenharmony_ci	}
27668c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
27678c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
27688c2ecf20Sopenharmony_ci	}
27698c2ecf20Sopenharmony_ci	self->sibling[0].diverge = 1;
27708c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[0]);
27718c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[1]);
27728c2ecf20Sopenharmony_ci
27738c2ecf20Sopenharmony_ci	while (self->sibling_count < TSYNC_SIBLINGS) {
27748c2ecf20Sopenharmony_ci		sem_wait(&self->started);
27758c2ecf20Sopenharmony_ci		self->sibling_count++;
27768c2ecf20Sopenharmony_ci	}
27778c2ecf20Sopenharmony_ci
27788c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
27798c2ecf20Sopenharmony_ci		      &self->apply_prog);
27808c2ecf20Sopenharmony_ci	ASSERT_EQ(self->sibling[0].system_tid, ret) {
27818c2ecf20Sopenharmony_ci		TH_LOG("Did not fail on diverged sibling.");
27828c2ecf20Sopenharmony_ci	}
27838c2ecf20Sopenharmony_ci
27848c2ecf20Sopenharmony_ci	/* Wake the threads */
27858c2ecf20Sopenharmony_ci	pthread_mutex_lock(&self->mutex);
27868c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
27878c2ecf20Sopenharmony_ci		TH_LOG("cond broadcast non-zero");
27888c2ecf20Sopenharmony_ci	}
27898c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&self->mutex);
27908c2ecf20Sopenharmony_ci
27918c2ecf20Sopenharmony_ci	/* Ensure they are both unkilled. */
27928c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[0].tid, &status);
27938c2ecf20Sopenharmony_ci	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
27948c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[1].tid, &status);
27958c2ecf20Sopenharmony_ci	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
27968c2ecf20Sopenharmony_ci}
27978c2ecf20Sopenharmony_ci
27988c2ecf20Sopenharmony_ciTEST_F(TSYNC, two_siblings_with_one_divergence_no_tid_in_err)
27998c2ecf20Sopenharmony_ci{
28008c2ecf20Sopenharmony_ci	long ret, flags;
28018c2ecf20Sopenharmony_ci	void *status;
28028c2ecf20Sopenharmony_ci
28038c2ecf20Sopenharmony_ci	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
28048c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
28058c2ecf20Sopenharmony_ci	}
28068c2ecf20Sopenharmony_ci
28078c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
28088c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
28098c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
28108c2ecf20Sopenharmony_ci	}
28118c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
28128c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
28138c2ecf20Sopenharmony_ci	}
28148c2ecf20Sopenharmony_ci	self->sibling[0].diverge = 1;
28158c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[0]);
28168c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[1]);
28178c2ecf20Sopenharmony_ci
28188c2ecf20Sopenharmony_ci	while (self->sibling_count < TSYNC_SIBLINGS) {
28198c2ecf20Sopenharmony_ci		sem_wait(&self->started);
28208c2ecf20Sopenharmony_ci		self->sibling_count++;
28218c2ecf20Sopenharmony_ci	}
28228c2ecf20Sopenharmony_ci
28238c2ecf20Sopenharmony_ci	flags = SECCOMP_FILTER_FLAG_TSYNC | \
28248c2ecf20Sopenharmony_ci		SECCOMP_FILTER_FLAG_TSYNC_ESRCH;
28258c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, flags, &self->apply_prog);
28268c2ecf20Sopenharmony_ci	ASSERT_EQ(ESRCH, errno) {
28278c2ecf20Sopenharmony_ci		TH_LOG("Did not return ESRCH for diverged sibling.");
28288c2ecf20Sopenharmony_ci	}
28298c2ecf20Sopenharmony_ci	ASSERT_EQ(-1, ret) {
28308c2ecf20Sopenharmony_ci		TH_LOG("Did not fail on diverged sibling.");
28318c2ecf20Sopenharmony_ci	}
28328c2ecf20Sopenharmony_ci
28338c2ecf20Sopenharmony_ci	/* Wake the threads */
28348c2ecf20Sopenharmony_ci	pthread_mutex_lock(&self->mutex);
28358c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
28368c2ecf20Sopenharmony_ci		TH_LOG("cond broadcast non-zero");
28378c2ecf20Sopenharmony_ci	}
28388c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&self->mutex);
28398c2ecf20Sopenharmony_ci
28408c2ecf20Sopenharmony_ci	/* Ensure they are both unkilled. */
28418c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[0].tid, &status);
28428c2ecf20Sopenharmony_ci	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
28438c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[1].tid, &status);
28448c2ecf20Sopenharmony_ci	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
28458c2ecf20Sopenharmony_ci}
28468c2ecf20Sopenharmony_ci
28478c2ecf20Sopenharmony_ciTEST_F(TSYNC, two_siblings_not_under_filter)
28488c2ecf20Sopenharmony_ci{
28498c2ecf20Sopenharmony_ci	long ret, sib;
28508c2ecf20Sopenharmony_ci	void *status;
28518c2ecf20Sopenharmony_ci	struct timespec delay = { .tv_nsec = 100000000 };
28528c2ecf20Sopenharmony_ci
28538c2ecf20Sopenharmony_ci	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
28548c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
28558c2ecf20Sopenharmony_ci	}
28568c2ecf20Sopenharmony_ci
28578c2ecf20Sopenharmony_ci	/*
28588c2ecf20Sopenharmony_ci	 * Sibling 0 will have its own seccomp policy
28598c2ecf20Sopenharmony_ci	 * and Sibling 1 will not be under seccomp at
28608c2ecf20Sopenharmony_ci	 * all. Sibling 1 will enter seccomp and 0
28618c2ecf20Sopenharmony_ci	 * will cause failure.
28628c2ecf20Sopenharmony_ci	 */
28638c2ecf20Sopenharmony_ci	self->sibling[0].diverge = 1;
28648c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[0]);
28658c2ecf20Sopenharmony_ci	tsync_start_sibling(&self->sibling[1]);
28668c2ecf20Sopenharmony_ci
28678c2ecf20Sopenharmony_ci	while (self->sibling_count < TSYNC_SIBLINGS) {
28688c2ecf20Sopenharmony_ci		sem_wait(&self->started);
28698c2ecf20Sopenharmony_ci		self->sibling_count++;
28708c2ecf20Sopenharmony_ci	}
28718c2ecf20Sopenharmony_ci
28728c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
28738c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
28748c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
28758c2ecf20Sopenharmony_ci	}
28768c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
28778c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
28788c2ecf20Sopenharmony_ci	}
28798c2ecf20Sopenharmony_ci
28808c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
28818c2ecf20Sopenharmony_ci		      &self->apply_prog);
28828c2ecf20Sopenharmony_ci	ASSERT_EQ(ret, self->sibling[0].system_tid) {
28838c2ecf20Sopenharmony_ci		TH_LOG("Did not fail on diverged sibling.");
28848c2ecf20Sopenharmony_ci	}
28858c2ecf20Sopenharmony_ci	sib = 1;
28868c2ecf20Sopenharmony_ci	if (ret == self->sibling[0].system_tid)
28878c2ecf20Sopenharmony_ci		sib = 0;
28888c2ecf20Sopenharmony_ci
28898c2ecf20Sopenharmony_ci	pthread_mutex_lock(&self->mutex);
28908c2ecf20Sopenharmony_ci
28918c2ecf20Sopenharmony_ci	/* Increment the other siblings num_waits so we can clean up
28928c2ecf20Sopenharmony_ci	 * the one we just saw.
28938c2ecf20Sopenharmony_ci	 */
28948c2ecf20Sopenharmony_ci	self->sibling[!sib].num_waits += 1;
28958c2ecf20Sopenharmony_ci
28968c2ecf20Sopenharmony_ci	/* Signal the thread to clean up*/
28978c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
28988c2ecf20Sopenharmony_ci		TH_LOG("cond broadcast non-zero");
28998c2ecf20Sopenharmony_ci	}
29008c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&self->mutex);
29018c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[sib].tid, &status);
29028c2ecf20Sopenharmony_ci	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
29038c2ecf20Sopenharmony_ci	/* Poll for actual task death. pthread_join doesn't guarantee it. */
29048c2ecf20Sopenharmony_ci	while (!kill(self->sibling[sib].system_tid, 0))
29058c2ecf20Sopenharmony_ci		nanosleep(&delay, NULL);
29068c2ecf20Sopenharmony_ci	/* Switch to the remaining sibling */
29078c2ecf20Sopenharmony_ci	sib = !sib;
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
29108c2ecf20Sopenharmony_ci		      &self->apply_prog);
29118c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
29128c2ecf20Sopenharmony_ci		TH_LOG("Expected the remaining sibling to sync");
29138c2ecf20Sopenharmony_ci	};
29148c2ecf20Sopenharmony_ci
29158c2ecf20Sopenharmony_ci	pthread_mutex_lock(&self->mutex);
29168c2ecf20Sopenharmony_ci
29178c2ecf20Sopenharmony_ci	/* If remaining sibling didn't have a chance to wake up during
29188c2ecf20Sopenharmony_ci	 * the first broadcast, manually reduce the num_waits now.
29198c2ecf20Sopenharmony_ci	 */
29208c2ecf20Sopenharmony_ci	if (self->sibling[sib].num_waits > 1)
29218c2ecf20Sopenharmony_ci		self->sibling[sib].num_waits = 1;
29228c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
29238c2ecf20Sopenharmony_ci		TH_LOG("cond broadcast non-zero");
29248c2ecf20Sopenharmony_ci	}
29258c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&self->mutex);
29268c2ecf20Sopenharmony_ci	PTHREAD_JOIN(self->sibling[sib].tid, &status);
29278c2ecf20Sopenharmony_ci	EXPECT_EQ(0, (long)status);
29288c2ecf20Sopenharmony_ci	/* Poll for actual task death. pthread_join doesn't guarantee it. */
29298c2ecf20Sopenharmony_ci	while (!kill(self->sibling[sib].system_tid, 0))
29308c2ecf20Sopenharmony_ci		nanosleep(&delay, NULL);
29318c2ecf20Sopenharmony_ci
29328c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,
29338c2ecf20Sopenharmony_ci		      &self->apply_prog);
29348c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);  /* just us chickens */
29358c2ecf20Sopenharmony_ci}
29368c2ecf20Sopenharmony_ci
29378c2ecf20Sopenharmony_ci/* Make sure restarted syscalls are seen directly as "restart_syscall". */
29388c2ecf20Sopenharmony_ciTEST(syscall_restart)
29398c2ecf20Sopenharmony_ci{
29408c2ecf20Sopenharmony_ci	long ret;
29418c2ecf20Sopenharmony_ci	unsigned long msg;
29428c2ecf20Sopenharmony_ci	pid_t child_pid;
29438c2ecf20Sopenharmony_ci	int pipefd[2];
29448c2ecf20Sopenharmony_ci	int status;
29458c2ecf20Sopenharmony_ci	siginfo_t info = { };
29468c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
29478c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
29488c2ecf20Sopenharmony_ci			 offsetof(struct seccomp_data, nr)),
29498c2ecf20Sopenharmony_ci
29508c2ecf20Sopenharmony_ci#ifdef __NR_sigreturn
29518c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_sigreturn, 7, 0),
29528c2ecf20Sopenharmony_ci#endif
29538c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 6, 0),
29548c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_exit, 5, 0),
29558c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_rt_sigreturn, 4, 0),
29568c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_nanosleep, 5, 0),
29578c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_clock_nanosleep, 4, 0),
29588c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_restart_syscall, 4, 0),
29598c2ecf20Sopenharmony_ci
29608c2ecf20Sopenharmony_ci		/* Allow __NR_write for easy logging. */
29618c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_write, 0, 1),
29628c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
29638c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
29648c2ecf20Sopenharmony_ci		/* The nanosleep jump target. */
29658c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x100),
29668c2ecf20Sopenharmony_ci		/* The restart_syscall jump target. */
29678c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x200),
29688c2ecf20Sopenharmony_ci	};
29698c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
29708c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
29718c2ecf20Sopenharmony_ci		.filter = filter,
29728c2ecf20Sopenharmony_ci	};
29738c2ecf20Sopenharmony_ci#if defined(__arm__)
29748c2ecf20Sopenharmony_ci	struct utsname utsbuf;
29758c2ecf20Sopenharmony_ci#endif
29768c2ecf20Sopenharmony_ci
29778c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pipe(pipefd));
29788c2ecf20Sopenharmony_ci
29798c2ecf20Sopenharmony_ci	child_pid = fork();
29808c2ecf20Sopenharmony_ci	ASSERT_LE(0, child_pid);
29818c2ecf20Sopenharmony_ci	if (child_pid == 0) {
29828c2ecf20Sopenharmony_ci		/* Child uses EXPECT not ASSERT to deliver status correctly. */
29838c2ecf20Sopenharmony_ci		char buf = ' ';
29848c2ecf20Sopenharmony_ci		struct timespec timeout = { };
29858c2ecf20Sopenharmony_ci
29868c2ecf20Sopenharmony_ci		/* Attach parent as tracer and stop. */
29878c2ecf20Sopenharmony_ci		EXPECT_EQ(0, ptrace(PTRACE_TRACEME));
29888c2ecf20Sopenharmony_ci		EXPECT_EQ(0, raise(SIGSTOP));
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci		EXPECT_EQ(0, close(pipefd[1]));
29918c2ecf20Sopenharmony_ci
29928c2ecf20Sopenharmony_ci		EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
29938c2ecf20Sopenharmony_ci			TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
29948c2ecf20Sopenharmony_ci		}
29958c2ecf20Sopenharmony_ci
29968c2ecf20Sopenharmony_ci		ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
29978c2ecf20Sopenharmony_ci		EXPECT_EQ(0, ret) {
29988c2ecf20Sopenharmony_ci			TH_LOG("Failed to install filter!");
29998c2ecf20Sopenharmony_ci		}
30008c2ecf20Sopenharmony_ci
30018c2ecf20Sopenharmony_ci		EXPECT_EQ(1, read(pipefd[0], &buf, 1)) {
30028c2ecf20Sopenharmony_ci			TH_LOG("Failed to read() sync from parent");
30038c2ecf20Sopenharmony_ci		}
30048c2ecf20Sopenharmony_ci		EXPECT_EQ('.', buf) {
30058c2ecf20Sopenharmony_ci			TH_LOG("Failed to get sync data from read()");
30068c2ecf20Sopenharmony_ci		}
30078c2ecf20Sopenharmony_ci
30088c2ecf20Sopenharmony_ci		/* Start nanosleep to be interrupted. */
30098c2ecf20Sopenharmony_ci		timeout.tv_sec = 1;
30108c2ecf20Sopenharmony_ci		errno = 0;
30118c2ecf20Sopenharmony_ci		EXPECT_EQ(0, nanosleep(&timeout, NULL)) {
30128c2ecf20Sopenharmony_ci			TH_LOG("Call to nanosleep() failed (errno %d)", errno);
30138c2ecf20Sopenharmony_ci		}
30148c2ecf20Sopenharmony_ci
30158c2ecf20Sopenharmony_ci		/* Read final sync from parent. */
30168c2ecf20Sopenharmony_ci		EXPECT_EQ(1, read(pipefd[0], &buf, 1)) {
30178c2ecf20Sopenharmony_ci			TH_LOG("Failed final read() from parent");
30188c2ecf20Sopenharmony_ci		}
30198c2ecf20Sopenharmony_ci		EXPECT_EQ('!', buf) {
30208c2ecf20Sopenharmony_ci			TH_LOG("Failed to get final data from read()");
30218c2ecf20Sopenharmony_ci		}
30228c2ecf20Sopenharmony_ci
30238c2ecf20Sopenharmony_ci		/* Directly report the status of our test harness results. */
30248c2ecf20Sopenharmony_ci		syscall(__NR_exit, _metadata->passed ? EXIT_SUCCESS
30258c2ecf20Sopenharmony_ci						     : EXIT_FAILURE);
30268c2ecf20Sopenharmony_ci	}
30278c2ecf20Sopenharmony_ci	EXPECT_EQ(0, close(pipefd[0]));
30288c2ecf20Sopenharmony_ci
30298c2ecf20Sopenharmony_ci	/* Attach to child, setup options, and release. */
30308c2ecf20Sopenharmony_ci	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
30318c2ecf20Sopenharmony_ci	ASSERT_EQ(true, WIFSTOPPED(status));
30328c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_SETOPTIONS, child_pid, NULL,
30338c2ecf20Sopenharmony_ci			    PTRACE_O_TRACESECCOMP));
30348c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
30358c2ecf20Sopenharmony_ci	ASSERT_EQ(1, write(pipefd[1], ".", 1));
30368c2ecf20Sopenharmony_ci
30378c2ecf20Sopenharmony_ci	/* Wait for nanosleep() to start. */
30388c2ecf20Sopenharmony_ci	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
30398c2ecf20Sopenharmony_ci	ASSERT_EQ(true, WIFSTOPPED(status));
30408c2ecf20Sopenharmony_ci	ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
30418c2ecf20Sopenharmony_ci	ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
30428c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
30438c2ecf20Sopenharmony_ci	ASSERT_EQ(0x100, msg);
30448c2ecf20Sopenharmony_ci	ret = get_syscall(_metadata, child_pid);
30458c2ecf20Sopenharmony_ci	EXPECT_TRUE(ret == __NR_nanosleep || ret == __NR_clock_nanosleep);
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_ci	/* Might as well check siginfo for sanity while we're here. */
30488c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
30498c2ecf20Sopenharmony_ci	ASSERT_EQ(SIGTRAP, info.si_signo);
30508c2ecf20Sopenharmony_ci	ASSERT_EQ(SIGTRAP | (PTRACE_EVENT_SECCOMP << 8), info.si_code);
30518c2ecf20Sopenharmony_ci	EXPECT_EQ(0, info.si_errno);
30528c2ecf20Sopenharmony_ci	EXPECT_EQ(getuid(), info.si_uid);
30538c2ecf20Sopenharmony_ci	/* Verify signal delivery came from child (seccomp-triggered). */
30548c2ecf20Sopenharmony_ci	EXPECT_EQ(child_pid, info.si_pid);
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_ci	/* Interrupt nanosleep with SIGSTOP (which we'll need to handle). */
30578c2ecf20Sopenharmony_ci	ASSERT_EQ(0, kill(child_pid, SIGSTOP));
30588c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
30598c2ecf20Sopenharmony_ci	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
30608c2ecf20Sopenharmony_ci	ASSERT_EQ(true, WIFSTOPPED(status));
30618c2ecf20Sopenharmony_ci	ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
30628c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
30638c2ecf20Sopenharmony_ci	/*
30648c2ecf20Sopenharmony_ci	 * There is no siginfo on SIGSTOP any more, so we can't verify
30658c2ecf20Sopenharmony_ci	 * signal delivery came from parent now (getpid() == info.si_pid).
30668c2ecf20Sopenharmony_ci	 * https://lkml.kernel.org/r/CAGXu5jJaZAOzP1qFz66tYrtbuywqb+UN2SOA1VLHpCCOiYvYeg@mail.gmail.com
30678c2ecf20Sopenharmony_ci	 * At least verify the SIGSTOP via PTRACE_GETSIGINFO.
30688c2ecf20Sopenharmony_ci	 */
30698c2ecf20Sopenharmony_ci	EXPECT_EQ(SIGSTOP, info.si_signo);
30708c2ecf20Sopenharmony_ci
30718c2ecf20Sopenharmony_ci	/* Restart nanosleep with SIGCONT, which triggers restart_syscall. */
30728c2ecf20Sopenharmony_ci	ASSERT_EQ(0, kill(child_pid, SIGCONT));
30738c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
30748c2ecf20Sopenharmony_ci	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
30758c2ecf20Sopenharmony_ci	ASSERT_EQ(true, WIFSTOPPED(status));
30768c2ecf20Sopenharmony_ci	ASSERT_EQ(SIGCONT, WSTOPSIG(status));
30778c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
30788c2ecf20Sopenharmony_ci
30798c2ecf20Sopenharmony_ci	/* Wait for restart_syscall() to start. */
30808c2ecf20Sopenharmony_ci	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
30818c2ecf20Sopenharmony_ci	ASSERT_EQ(true, WIFSTOPPED(status));
30828c2ecf20Sopenharmony_ci	ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
30838c2ecf20Sopenharmony_ci	ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
30848c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_ci	ASSERT_EQ(0x200, msg);
30878c2ecf20Sopenharmony_ci	ret = get_syscall(_metadata, child_pid);
30888c2ecf20Sopenharmony_ci#if defined(__arm__)
30898c2ecf20Sopenharmony_ci	/*
30908c2ecf20Sopenharmony_ci	 * FIXME:
30918c2ecf20Sopenharmony_ci	 * - native ARM registers do NOT expose true syscall.
30928c2ecf20Sopenharmony_ci	 * - compat ARM registers on ARM64 DO expose true syscall.
30938c2ecf20Sopenharmony_ci	 */
30948c2ecf20Sopenharmony_ci	ASSERT_EQ(0, uname(&utsbuf));
30958c2ecf20Sopenharmony_ci	if (strncmp(utsbuf.machine, "arm", 3) == 0) {
30968c2ecf20Sopenharmony_ci		EXPECT_EQ(__NR_nanosleep, ret);
30978c2ecf20Sopenharmony_ci	} else
30988c2ecf20Sopenharmony_ci#endif
30998c2ecf20Sopenharmony_ci	{
31008c2ecf20Sopenharmony_ci		EXPECT_EQ(__NR_restart_syscall, ret);
31018c2ecf20Sopenharmony_ci	}
31028c2ecf20Sopenharmony_ci
31038c2ecf20Sopenharmony_ci	/* Write again to end test. */
31048c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
31058c2ecf20Sopenharmony_ci	ASSERT_EQ(1, write(pipefd[1], "!", 1));
31068c2ecf20Sopenharmony_ci	EXPECT_EQ(0, close(pipefd[1]));
31078c2ecf20Sopenharmony_ci
31088c2ecf20Sopenharmony_ci	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
31098c2ecf20Sopenharmony_ci	if (WIFSIGNALED(status) || WEXITSTATUS(status))
31108c2ecf20Sopenharmony_ci		_metadata->passed = 0;
31118c2ecf20Sopenharmony_ci}
31128c2ecf20Sopenharmony_ci
31138c2ecf20Sopenharmony_ciTEST_SIGNAL(filter_flag_log, SIGSYS)
31148c2ecf20Sopenharmony_ci{
31158c2ecf20Sopenharmony_ci	struct sock_filter allow_filter[] = {
31168c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
31178c2ecf20Sopenharmony_ci	};
31188c2ecf20Sopenharmony_ci	struct sock_filter kill_filter[] = {
31198c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
31208c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
31218c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
31228c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
31238c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
31248c2ecf20Sopenharmony_ci	};
31258c2ecf20Sopenharmony_ci	struct sock_fprog allow_prog = {
31268c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(allow_filter),
31278c2ecf20Sopenharmony_ci		.filter = allow_filter,
31288c2ecf20Sopenharmony_ci	};
31298c2ecf20Sopenharmony_ci	struct sock_fprog kill_prog = {
31308c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(kill_filter),
31318c2ecf20Sopenharmony_ci		.filter = kill_filter,
31328c2ecf20Sopenharmony_ci	};
31338c2ecf20Sopenharmony_ci	long ret;
31348c2ecf20Sopenharmony_ci	pid_t parent = getppid();
31358c2ecf20Sopenharmony_ci
31368c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
31378c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret);
31388c2ecf20Sopenharmony_ci
31398c2ecf20Sopenharmony_ci	/* Verify that the FILTER_FLAG_LOG flag isn't accepted in strict mode */
31408c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_STRICT, SECCOMP_FILTER_FLAG_LOG,
31418c2ecf20Sopenharmony_ci		      &allow_prog);
31428c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
31438c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
31448c2ecf20Sopenharmony_ci	}
31458c2ecf20Sopenharmony_ci	EXPECT_NE(0, ret) {
31468c2ecf20Sopenharmony_ci		TH_LOG("Kernel accepted FILTER_FLAG_LOG flag in strict mode!");
31478c2ecf20Sopenharmony_ci	}
31488c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno) {
31498c2ecf20Sopenharmony_ci		TH_LOG("Kernel returned unexpected errno for FILTER_FLAG_LOG flag in strict mode!");
31508c2ecf20Sopenharmony_ci	}
31518c2ecf20Sopenharmony_ci
31528c2ecf20Sopenharmony_ci	/* Verify that a simple, permissive filter can be added with no flags */
31538c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &allow_prog);
31548c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret);
31558c2ecf20Sopenharmony_ci
31568c2ecf20Sopenharmony_ci	/* See if the same filter can be added with the FILTER_FLAG_LOG flag */
31578c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
31588c2ecf20Sopenharmony_ci		      &allow_prog);
31598c2ecf20Sopenharmony_ci	ASSERT_NE(EINVAL, errno) {
31608c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support the FILTER_FLAG_LOG flag!");
31618c2ecf20Sopenharmony_ci	}
31628c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret);
31638c2ecf20Sopenharmony_ci
31648c2ecf20Sopenharmony_ci	/* Ensure that the kill filter works with the FILTER_FLAG_LOG flag */
31658c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
31668c2ecf20Sopenharmony_ci		      &kill_prog);
31678c2ecf20Sopenharmony_ci	EXPECT_EQ(0, ret);
31688c2ecf20Sopenharmony_ci
31698c2ecf20Sopenharmony_ci	EXPECT_EQ(parent, syscall(__NR_getppid));
31708c2ecf20Sopenharmony_ci	/* getpid() should never return. */
31718c2ecf20Sopenharmony_ci	EXPECT_EQ(0, syscall(__NR_getpid));
31728c2ecf20Sopenharmony_ci}
31738c2ecf20Sopenharmony_ci
31748c2ecf20Sopenharmony_ciTEST(get_action_avail)
31758c2ecf20Sopenharmony_ci{
31768c2ecf20Sopenharmony_ci	__u32 actions[] = { SECCOMP_RET_KILL_THREAD, SECCOMP_RET_TRAP,
31778c2ecf20Sopenharmony_ci			    SECCOMP_RET_ERRNO, SECCOMP_RET_TRACE,
31788c2ecf20Sopenharmony_ci			    SECCOMP_RET_LOG,   SECCOMP_RET_ALLOW };
31798c2ecf20Sopenharmony_ci	__u32 unknown_action = 0x10000000U;
31808c2ecf20Sopenharmony_ci	int i;
31818c2ecf20Sopenharmony_ci	long ret;
31828c2ecf20Sopenharmony_ci
31838c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[0]);
31848c2ecf20Sopenharmony_ci	ASSERT_NE(ENOSYS, errno) {
31858c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support seccomp syscall!");
31868c2ecf20Sopenharmony_ci	}
31878c2ecf20Sopenharmony_ci	ASSERT_NE(EINVAL, errno) {
31888c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support SECCOMP_GET_ACTION_AVAIL operation!");
31898c2ecf20Sopenharmony_ci	}
31908c2ecf20Sopenharmony_ci	EXPECT_EQ(ret, 0);
31918c2ecf20Sopenharmony_ci
31928c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(actions); i++) {
31938c2ecf20Sopenharmony_ci		ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[i]);
31948c2ecf20Sopenharmony_ci		EXPECT_EQ(ret, 0) {
31958c2ecf20Sopenharmony_ci			TH_LOG("Expected action (0x%X) not available!",
31968c2ecf20Sopenharmony_ci			       actions[i]);
31978c2ecf20Sopenharmony_ci		}
31988c2ecf20Sopenharmony_ci	}
31998c2ecf20Sopenharmony_ci
32008c2ecf20Sopenharmony_ci	/* Check that an unknown action is handled properly (EOPNOTSUPP) */
32018c2ecf20Sopenharmony_ci	ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &unknown_action);
32028c2ecf20Sopenharmony_ci	EXPECT_EQ(ret, -1);
32038c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EOPNOTSUPP);
32048c2ecf20Sopenharmony_ci}
32058c2ecf20Sopenharmony_ci
32068c2ecf20Sopenharmony_ciTEST(get_metadata)
32078c2ecf20Sopenharmony_ci{
32088c2ecf20Sopenharmony_ci	pid_t pid;
32098c2ecf20Sopenharmony_ci	int pipefd[2];
32108c2ecf20Sopenharmony_ci	char buf;
32118c2ecf20Sopenharmony_ci	struct seccomp_metadata md;
32128c2ecf20Sopenharmony_ci	long ret;
32138c2ecf20Sopenharmony_ci
32148c2ecf20Sopenharmony_ci	/* Only real root can get metadata. */
32158c2ecf20Sopenharmony_ci	if (geteuid()) {
32168c2ecf20Sopenharmony_ci		SKIP(return, "get_metadata requires real root");
32178c2ecf20Sopenharmony_ci		return;
32188c2ecf20Sopenharmony_ci	}
32198c2ecf20Sopenharmony_ci
32208c2ecf20Sopenharmony_ci	ASSERT_EQ(0, pipe(pipefd));
32218c2ecf20Sopenharmony_ci
32228c2ecf20Sopenharmony_ci	pid = fork();
32238c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
32248c2ecf20Sopenharmony_ci	if (pid == 0) {
32258c2ecf20Sopenharmony_ci		struct sock_filter filter[] = {
32268c2ecf20Sopenharmony_ci			BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
32278c2ecf20Sopenharmony_ci		};
32288c2ecf20Sopenharmony_ci		struct sock_fprog prog = {
32298c2ecf20Sopenharmony_ci			.len = (unsigned short)ARRAY_SIZE(filter),
32308c2ecf20Sopenharmony_ci			.filter = filter,
32318c2ecf20Sopenharmony_ci		};
32328c2ecf20Sopenharmony_ci
32338c2ecf20Sopenharmony_ci		/* one with log, one without */
32348c2ecf20Sopenharmony_ci		EXPECT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER,
32358c2ecf20Sopenharmony_ci				     SECCOMP_FILTER_FLAG_LOG, &prog));
32368c2ecf20Sopenharmony_ci		EXPECT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog));
32378c2ecf20Sopenharmony_ci
32388c2ecf20Sopenharmony_ci		EXPECT_EQ(0, close(pipefd[0]));
32398c2ecf20Sopenharmony_ci		ASSERT_EQ(1, write(pipefd[1], "1", 1));
32408c2ecf20Sopenharmony_ci		ASSERT_EQ(0, close(pipefd[1]));
32418c2ecf20Sopenharmony_ci
32428c2ecf20Sopenharmony_ci		while (1)
32438c2ecf20Sopenharmony_ci			sleep(100);
32448c2ecf20Sopenharmony_ci	}
32458c2ecf20Sopenharmony_ci
32468c2ecf20Sopenharmony_ci	ASSERT_EQ(0, close(pipefd[1]));
32478c2ecf20Sopenharmony_ci	ASSERT_EQ(1, read(pipefd[0], &buf, 1));
32488c2ecf20Sopenharmony_ci
32498c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid));
32508c2ecf20Sopenharmony_ci	ASSERT_EQ(pid, waitpid(pid, NULL, 0));
32518c2ecf20Sopenharmony_ci
32528c2ecf20Sopenharmony_ci	/* Past here must not use ASSERT or child process is never killed. */
32538c2ecf20Sopenharmony_ci
32548c2ecf20Sopenharmony_ci	md.filter_off = 0;
32558c2ecf20Sopenharmony_ci	errno = 0;
32568c2ecf20Sopenharmony_ci	ret = ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md);
32578c2ecf20Sopenharmony_ci	EXPECT_EQ(sizeof(md), ret) {
32588c2ecf20Sopenharmony_ci		if (errno == EINVAL)
32598c2ecf20Sopenharmony_ci			SKIP(goto skip, "Kernel does not support PTRACE_SECCOMP_GET_METADATA (missing CONFIG_CHECKPOINT_RESTORE?)");
32608c2ecf20Sopenharmony_ci	}
32618c2ecf20Sopenharmony_ci
32628c2ecf20Sopenharmony_ci	EXPECT_EQ(md.flags, SECCOMP_FILTER_FLAG_LOG);
32638c2ecf20Sopenharmony_ci	EXPECT_EQ(md.filter_off, 0);
32648c2ecf20Sopenharmony_ci
32658c2ecf20Sopenharmony_ci	md.filter_off = 1;
32668c2ecf20Sopenharmony_ci	ret = ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md);
32678c2ecf20Sopenharmony_ci	EXPECT_EQ(sizeof(md), ret);
32688c2ecf20Sopenharmony_ci	EXPECT_EQ(md.flags, 0);
32698c2ecf20Sopenharmony_ci	EXPECT_EQ(md.filter_off, 1);
32708c2ecf20Sopenharmony_ci
32718c2ecf20Sopenharmony_ciskip:
32728c2ecf20Sopenharmony_ci	ASSERT_EQ(0, kill(pid, SIGKILL));
32738c2ecf20Sopenharmony_ci}
32748c2ecf20Sopenharmony_ci
32758c2ecf20Sopenharmony_cistatic int user_notif_syscall(int nr, unsigned int flags)
32768c2ecf20Sopenharmony_ci{
32778c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
32788c2ecf20Sopenharmony_ci		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
32798c2ecf20Sopenharmony_ci			offsetof(struct seccomp_data, nr)),
32808c2ecf20Sopenharmony_ci		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, nr, 0, 1),
32818c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_USER_NOTIF),
32828c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
32838c2ecf20Sopenharmony_ci	};
32848c2ecf20Sopenharmony_ci
32858c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
32868c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
32878c2ecf20Sopenharmony_ci		.filter = filter,
32888c2ecf20Sopenharmony_ci	};
32898c2ecf20Sopenharmony_ci
32908c2ecf20Sopenharmony_ci	return seccomp(SECCOMP_SET_MODE_FILTER, flags, &prog);
32918c2ecf20Sopenharmony_ci}
32928c2ecf20Sopenharmony_ci
32938c2ecf20Sopenharmony_ci#define USER_NOTIF_MAGIC INT_MAX
32948c2ecf20Sopenharmony_ciTEST(user_notification_basic)
32958c2ecf20Sopenharmony_ci{
32968c2ecf20Sopenharmony_ci	pid_t pid;
32978c2ecf20Sopenharmony_ci	long ret;
32988c2ecf20Sopenharmony_ci	int status, listener;
32998c2ecf20Sopenharmony_ci	struct seccomp_notif req = {};
33008c2ecf20Sopenharmony_ci	struct seccomp_notif_resp resp = {};
33018c2ecf20Sopenharmony_ci	struct pollfd pollfd;
33028c2ecf20Sopenharmony_ci
33038c2ecf20Sopenharmony_ci	struct sock_filter filter[] = {
33048c2ecf20Sopenharmony_ci		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
33058c2ecf20Sopenharmony_ci	};
33068c2ecf20Sopenharmony_ci	struct sock_fprog prog = {
33078c2ecf20Sopenharmony_ci		.len = (unsigned short)ARRAY_SIZE(filter),
33088c2ecf20Sopenharmony_ci		.filter = filter,
33098c2ecf20Sopenharmony_ci	};
33108c2ecf20Sopenharmony_ci
33118c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
33128c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
33138c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
33148c2ecf20Sopenharmony_ci	}
33158c2ecf20Sopenharmony_ci
33168c2ecf20Sopenharmony_ci	pid = fork();
33178c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
33188c2ecf20Sopenharmony_ci
33198c2ecf20Sopenharmony_ci	/* Check that we get -ENOSYS with no listener attached */
33208c2ecf20Sopenharmony_ci	if (pid == 0) {
33218c2ecf20Sopenharmony_ci		if (user_notif_syscall(__NR_getppid, 0) < 0)
33228c2ecf20Sopenharmony_ci			exit(1);
33238c2ecf20Sopenharmony_ci		ret = syscall(__NR_getppid);
33248c2ecf20Sopenharmony_ci		exit(ret >= 0 || errno != ENOSYS);
33258c2ecf20Sopenharmony_ci	}
33268c2ecf20Sopenharmony_ci
33278c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
33288c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
33298c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
33308c2ecf20Sopenharmony_ci
33318c2ecf20Sopenharmony_ci	/* Add some no-op filters for grins. */
33328c2ecf20Sopenharmony_ci	EXPECT_EQ(seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog), 0);
33338c2ecf20Sopenharmony_ci	EXPECT_EQ(seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog), 0);
33348c2ecf20Sopenharmony_ci	EXPECT_EQ(seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog), 0);
33358c2ecf20Sopenharmony_ci	EXPECT_EQ(seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog), 0);
33368c2ecf20Sopenharmony_ci
33378c2ecf20Sopenharmony_ci	/* Check that the basic notification machinery works */
33388c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_getppid,
33398c2ecf20Sopenharmony_ci				      SECCOMP_FILTER_FLAG_NEW_LISTENER);
33408c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
33418c2ecf20Sopenharmony_ci
33428c2ecf20Sopenharmony_ci	/* Installing a second listener in the chain should EBUSY */
33438c2ecf20Sopenharmony_ci	EXPECT_EQ(user_notif_syscall(__NR_getppid,
33448c2ecf20Sopenharmony_ci				     SECCOMP_FILTER_FLAG_NEW_LISTENER),
33458c2ecf20Sopenharmony_ci		  -1);
33468c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EBUSY);
33478c2ecf20Sopenharmony_ci
33488c2ecf20Sopenharmony_ci	pid = fork();
33498c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
33508c2ecf20Sopenharmony_ci
33518c2ecf20Sopenharmony_ci	if (pid == 0) {
33528c2ecf20Sopenharmony_ci		ret = syscall(__NR_getppid);
33538c2ecf20Sopenharmony_ci		exit(ret != USER_NOTIF_MAGIC);
33548c2ecf20Sopenharmony_ci	}
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci	pollfd.fd = listener;
33578c2ecf20Sopenharmony_ci	pollfd.events = POLLIN | POLLOUT;
33588c2ecf20Sopenharmony_ci
33598c2ecf20Sopenharmony_ci	EXPECT_GT(poll(&pollfd, 1, -1), 0);
33608c2ecf20Sopenharmony_ci	EXPECT_EQ(pollfd.revents, POLLIN);
33618c2ecf20Sopenharmony_ci
33628c2ecf20Sopenharmony_ci	/* Test that we can't pass garbage to the kernel. */
33638c2ecf20Sopenharmony_ci	memset(&req, 0, sizeof(req));
33648c2ecf20Sopenharmony_ci	req.pid = -1;
33658c2ecf20Sopenharmony_ci	errno = 0;
33668c2ecf20Sopenharmony_ci	ret = ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req);
33678c2ecf20Sopenharmony_ci	EXPECT_EQ(-1, ret);
33688c2ecf20Sopenharmony_ci	EXPECT_EQ(EINVAL, errno);
33698c2ecf20Sopenharmony_ci
33708c2ecf20Sopenharmony_ci	if (ret) {
33718c2ecf20Sopenharmony_ci		req.pid = 0;
33728c2ecf20Sopenharmony_ci		EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
33738c2ecf20Sopenharmony_ci	}
33748c2ecf20Sopenharmony_ci
33758c2ecf20Sopenharmony_ci	pollfd.fd = listener;
33768c2ecf20Sopenharmony_ci	pollfd.events = POLLIN | POLLOUT;
33778c2ecf20Sopenharmony_ci
33788c2ecf20Sopenharmony_ci	EXPECT_GT(poll(&pollfd, 1, -1), 0);
33798c2ecf20Sopenharmony_ci	EXPECT_EQ(pollfd.revents, POLLOUT);
33808c2ecf20Sopenharmony_ci
33818c2ecf20Sopenharmony_ci	EXPECT_EQ(req.data.nr,  __NR_getppid);
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_ci	resp.id = req.id;
33848c2ecf20Sopenharmony_ci	resp.error = 0;
33858c2ecf20Sopenharmony_ci	resp.val = USER_NOTIF_MAGIC;
33868c2ecf20Sopenharmony_ci
33878c2ecf20Sopenharmony_ci	/* check that we make sure flags == 0 */
33888c2ecf20Sopenharmony_ci	resp.flags = 1;
33898c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1);
33908c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EINVAL);
33918c2ecf20Sopenharmony_ci
33928c2ecf20Sopenharmony_ci	resp.flags = 0;
33938c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
33948c2ecf20Sopenharmony_ci
33958c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
33968c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
33978c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
33988c2ecf20Sopenharmony_ci}
33998c2ecf20Sopenharmony_ci
34008c2ecf20Sopenharmony_ciTEST(user_notification_with_tsync)
34018c2ecf20Sopenharmony_ci{
34028c2ecf20Sopenharmony_ci	int ret;
34038c2ecf20Sopenharmony_ci	unsigned int flags;
34048c2ecf20Sopenharmony_ci
34058c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
34068c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
34078c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
34088c2ecf20Sopenharmony_ci	}
34098c2ecf20Sopenharmony_ci
34108c2ecf20Sopenharmony_ci	/* these were exclusive */
34118c2ecf20Sopenharmony_ci	flags = SECCOMP_FILTER_FLAG_NEW_LISTENER |
34128c2ecf20Sopenharmony_ci		SECCOMP_FILTER_FLAG_TSYNC;
34138c2ecf20Sopenharmony_ci	ASSERT_EQ(-1, user_notif_syscall(__NR_getppid, flags));
34148c2ecf20Sopenharmony_ci	ASSERT_EQ(EINVAL, errno);
34158c2ecf20Sopenharmony_ci
34168c2ecf20Sopenharmony_ci	/* but now they're not */
34178c2ecf20Sopenharmony_ci	flags |= SECCOMP_FILTER_FLAG_TSYNC_ESRCH;
34188c2ecf20Sopenharmony_ci	ret = user_notif_syscall(__NR_getppid, flags);
34198c2ecf20Sopenharmony_ci	close(ret);
34208c2ecf20Sopenharmony_ci	ASSERT_LE(0, ret);
34218c2ecf20Sopenharmony_ci}
34228c2ecf20Sopenharmony_ci
34238c2ecf20Sopenharmony_ciTEST(user_notification_kill_in_middle)
34248c2ecf20Sopenharmony_ci{
34258c2ecf20Sopenharmony_ci	pid_t pid;
34268c2ecf20Sopenharmony_ci	long ret;
34278c2ecf20Sopenharmony_ci	int listener;
34288c2ecf20Sopenharmony_ci	struct seccomp_notif req = {};
34298c2ecf20Sopenharmony_ci	struct seccomp_notif_resp resp = {};
34308c2ecf20Sopenharmony_ci
34318c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
34328c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
34338c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
34348c2ecf20Sopenharmony_ci	}
34358c2ecf20Sopenharmony_ci
34368c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_getppid,
34378c2ecf20Sopenharmony_ci				      SECCOMP_FILTER_FLAG_NEW_LISTENER);
34388c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
34398c2ecf20Sopenharmony_ci
34408c2ecf20Sopenharmony_ci	/*
34418c2ecf20Sopenharmony_ci	 * Check that nothing bad happens when we kill the task in the middle
34428c2ecf20Sopenharmony_ci	 * of a syscall.
34438c2ecf20Sopenharmony_ci	 */
34448c2ecf20Sopenharmony_ci	pid = fork();
34458c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
34468c2ecf20Sopenharmony_ci
34478c2ecf20Sopenharmony_ci	if (pid == 0) {
34488c2ecf20Sopenharmony_ci		ret = syscall(__NR_getppid);
34498c2ecf20Sopenharmony_ci		exit(ret != USER_NOTIF_MAGIC);
34508c2ecf20Sopenharmony_ci	}
34518c2ecf20Sopenharmony_ci
34528c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
34538c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ID_VALID, &req.id), 0);
34548c2ecf20Sopenharmony_ci
34558c2ecf20Sopenharmony_ci	EXPECT_EQ(kill(pid, SIGKILL), 0);
34568c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, NULL, 0), pid);
34578c2ecf20Sopenharmony_ci
34588c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ID_VALID, &req.id), -1);
34598c2ecf20Sopenharmony_ci
34608c2ecf20Sopenharmony_ci	resp.id = req.id;
34618c2ecf20Sopenharmony_ci	ret = ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp);
34628c2ecf20Sopenharmony_ci	EXPECT_EQ(ret, -1);
34638c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, ENOENT);
34648c2ecf20Sopenharmony_ci}
34658c2ecf20Sopenharmony_ci
34668c2ecf20Sopenharmony_cistatic int handled = -1;
34678c2ecf20Sopenharmony_ci
34688c2ecf20Sopenharmony_cistatic void signal_handler(int signal)
34698c2ecf20Sopenharmony_ci{
34708c2ecf20Sopenharmony_ci	if (write(handled, "c", 1) != 1)
34718c2ecf20Sopenharmony_ci		perror("write from signal");
34728c2ecf20Sopenharmony_ci}
34738c2ecf20Sopenharmony_ci
34748c2ecf20Sopenharmony_ciTEST(user_notification_signal)
34758c2ecf20Sopenharmony_ci{
34768c2ecf20Sopenharmony_ci	pid_t pid;
34778c2ecf20Sopenharmony_ci	long ret;
34788c2ecf20Sopenharmony_ci	int status, listener, sk_pair[2];
34798c2ecf20Sopenharmony_ci	struct seccomp_notif req = {};
34808c2ecf20Sopenharmony_ci	struct seccomp_notif_resp resp = {};
34818c2ecf20Sopenharmony_ci	char c;
34828c2ecf20Sopenharmony_ci
34838c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
34848c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
34858c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
34868c2ecf20Sopenharmony_ci	}
34878c2ecf20Sopenharmony_ci
34888c2ecf20Sopenharmony_ci	ASSERT_EQ(socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sk_pair), 0);
34898c2ecf20Sopenharmony_ci
34908c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_gettid,
34918c2ecf20Sopenharmony_ci				      SECCOMP_FILTER_FLAG_NEW_LISTENER);
34928c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
34938c2ecf20Sopenharmony_ci
34948c2ecf20Sopenharmony_ci	pid = fork();
34958c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
34968c2ecf20Sopenharmony_ci
34978c2ecf20Sopenharmony_ci	if (pid == 0) {
34988c2ecf20Sopenharmony_ci		close(sk_pair[0]);
34998c2ecf20Sopenharmony_ci		handled = sk_pair[1];
35008c2ecf20Sopenharmony_ci		if (signal(SIGUSR1, signal_handler) == SIG_ERR) {
35018c2ecf20Sopenharmony_ci			perror("signal");
35028c2ecf20Sopenharmony_ci			exit(1);
35038c2ecf20Sopenharmony_ci		}
35048c2ecf20Sopenharmony_ci		/*
35058c2ecf20Sopenharmony_ci		 * ERESTARTSYS behavior is a bit hard to test, because we need
35068c2ecf20Sopenharmony_ci		 * to rely on a signal that has not yet been handled. Let's at
35078c2ecf20Sopenharmony_ci		 * least check that the error code gets propagated through, and
35088c2ecf20Sopenharmony_ci		 * hope that it doesn't break when there is actually a signal :)
35098c2ecf20Sopenharmony_ci		 */
35108c2ecf20Sopenharmony_ci		ret = syscall(__NR_gettid);
35118c2ecf20Sopenharmony_ci		exit(!(ret == -1 && errno == 512));
35128c2ecf20Sopenharmony_ci	}
35138c2ecf20Sopenharmony_ci
35148c2ecf20Sopenharmony_ci	close(sk_pair[1]);
35158c2ecf20Sopenharmony_ci
35168c2ecf20Sopenharmony_ci	memset(&req, 0, sizeof(req));
35178c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
35188c2ecf20Sopenharmony_ci
35198c2ecf20Sopenharmony_ci	EXPECT_EQ(kill(pid, SIGUSR1), 0);
35208c2ecf20Sopenharmony_ci
35218c2ecf20Sopenharmony_ci	/*
35228c2ecf20Sopenharmony_ci	 * Make sure the signal really is delivered, which means we're not
35238c2ecf20Sopenharmony_ci	 * stuck in the user notification code any more and the notification
35248c2ecf20Sopenharmony_ci	 * should be dead.
35258c2ecf20Sopenharmony_ci	 */
35268c2ecf20Sopenharmony_ci	EXPECT_EQ(read(sk_pair[0], &c, 1), 1);
35278c2ecf20Sopenharmony_ci
35288c2ecf20Sopenharmony_ci	resp.id = req.id;
35298c2ecf20Sopenharmony_ci	resp.error = -EPERM;
35308c2ecf20Sopenharmony_ci	resp.val = 0;
35318c2ecf20Sopenharmony_ci
35328c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1);
35338c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, ENOENT);
35348c2ecf20Sopenharmony_ci
35358c2ecf20Sopenharmony_ci	memset(&req, 0, sizeof(req));
35368c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
35378c2ecf20Sopenharmony_ci
35388c2ecf20Sopenharmony_ci	resp.id = req.id;
35398c2ecf20Sopenharmony_ci	resp.error = -512; /* -ERESTARTSYS */
35408c2ecf20Sopenharmony_ci	resp.val = 0;
35418c2ecf20Sopenharmony_ci
35428c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
35438c2ecf20Sopenharmony_ci
35448c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
35458c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
35468c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
35478c2ecf20Sopenharmony_ci}
35488c2ecf20Sopenharmony_ci
35498c2ecf20Sopenharmony_ciTEST(user_notification_closed_listener)
35508c2ecf20Sopenharmony_ci{
35518c2ecf20Sopenharmony_ci	pid_t pid;
35528c2ecf20Sopenharmony_ci	long ret;
35538c2ecf20Sopenharmony_ci	int status, listener;
35548c2ecf20Sopenharmony_ci
35558c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
35568c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
35578c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
35588c2ecf20Sopenharmony_ci	}
35598c2ecf20Sopenharmony_ci
35608c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_getppid,
35618c2ecf20Sopenharmony_ci				      SECCOMP_FILTER_FLAG_NEW_LISTENER);
35628c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
35638c2ecf20Sopenharmony_ci
35648c2ecf20Sopenharmony_ci	/*
35658c2ecf20Sopenharmony_ci	 * Check that we get an ENOSYS when the listener is closed.
35668c2ecf20Sopenharmony_ci	 */
35678c2ecf20Sopenharmony_ci	pid = fork();
35688c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
35698c2ecf20Sopenharmony_ci	if (pid == 0) {
35708c2ecf20Sopenharmony_ci		close(listener);
35718c2ecf20Sopenharmony_ci		ret = syscall(__NR_getppid);
35728c2ecf20Sopenharmony_ci		exit(ret != -1 && errno != ENOSYS);
35738c2ecf20Sopenharmony_ci	}
35748c2ecf20Sopenharmony_ci
35758c2ecf20Sopenharmony_ci	close(listener);
35768c2ecf20Sopenharmony_ci
35778c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
35788c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
35798c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
35808c2ecf20Sopenharmony_ci}
35818c2ecf20Sopenharmony_ci
35828c2ecf20Sopenharmony_ci/*
35838c2ecf20Sopenharmony_ci * Check that a pid in a child namespace still shows up as valid in ours.
35848c2ecf20Sopenharmony_ci */
35858c2ecf20Sopenharmony_ciTEST(user_notification_child_pid_ns)
35868c2ecf20Sopenharmony_ci{
35878c2ecf20Sopenharmony_ci	pid_t pid;
35888c2ecf20Sopenharmony_ci	int status, listener;
35898c2ecf20Sopenharmony_ci	struct seccomp_notif req = {};
35908c2ecf20Sopenharmony_ci	struct seccomp_notif_resp resp = {};
35918c2ecf20Sopenharmony_ci
35928c2ecf20Sopenharmony_ci	ASSERT_EQ(unshare(CLONE_NEWUSER | CLONE_NEWPID), 0) {
35938c2ecf20Sopenharmony_ci		if (errno == EINVAL)
35948c2ecf20Sopenharmony_ci			SKIP(return, "kernel missing CLONE_NEWUSER support");
35958c2ecf20Sopenharmony_ci	};
35968c2ecf20Sopenharmony_ci
35978c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_getppid,
35988c2ecf20Sopenharmony_ci				      SECCOMP_FILTER_FLAG_NEW_LISTENER);
35998c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
36008c2ecf20Sopenharmony_ci
36018c2ecf20Sopenharmony_ci	pid = fork();
36028c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
36038c2ecf20Sopenharmony_ci
36048c2ecf20Sopenharmony_ci	if (pid == 0)
36058c2ecf20Sopenharmony_ci		exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC);
36068c2ecf20Sopenharmony_ci
36078c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
36088c2ecf20Sopenharmony_ci	EXPECT_EQ(req.pid, pid);
36098c2ecf20Sopenharmony_ci
36108c2ecf20Sopenharmony_ci	resp.id = req.id;
36118c2ecf20Sopenharmony_ci	resp.error = 0;
36128c2ecf20Sopenharmony_ci	resp.val = USER_NOTIF_MAGIC;
36138c2ecf20Sopenharmony_ci
36148c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
36158c2ecf20Sopenharmony_ci
36168c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
36178c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
36188c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
36198c2ecf20Sopenharmony_ci	close(listener);
36208c2ecf20Sopenharmony_ci}
36218c2ecf20Sopenharmony_ci
36228c2ecf20Sopenharmony_ci/*
36238c2ecf20Sopenharmony_ci * Check that a pid in a sibling (i.e. unrelated) namespace shows up as 0, i.e.
36248c2ecf20Sopenharmony_ci * invalid.
36258c2ecf20Sopenharmony_ci */
36268c2ecf20Sopenharmony_ciTEST(user_notification_sibling_pid_ns)
36278c2ecf20Sopenharmony_ci{
36288c2ecf20Sopenharmony_ci	pid_t pid, pid2;
36298c2ecf20Sopenharmony_ci	int status, listener;
36308c2ecf20Sopenharmony_ci	struct seccomp_notif req = {};
36318c2ecf20Sopenharmony_ci	struct seccomp_notif_resp resp = {};
36328c2ecf20Sopenharmony_ci
36338c2ecf20Sopenharmony_ci	ASSERT_EQ(prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0), 0) {
36348c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
36358c2ecf20Sopenharmony_ci	}
36368c2ecf20Sopenharmony_ci
36378c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_getppid,
36388c2ecf20Sopenharmony_ci				      SECCOMP_FILTER_FLAG_NEW_LISTENER);
36398c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
36408c2ecf20Sopenharmony_ci
36418c2ecf20Sopenharmony_ci	pid = fork();
36428c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
36438c2ecf20Sopenharmony_ci
36448c2ecf20Sopenharmony_ci	if (pid == 0) {
36458c2ecf20Sopenharmony_ci		ASSERT_EQ(unshare(CLONE_NEWPID), 0);
36468c2ecf20Sopenharmony_ci
36478c2ecf20Sopenharmony_ci		pid2 = fork();
36488c2ecf20Sopenharmony_ci		ASSERT_GE(pid2, 0);
36498c2ecf20Sopenharmony_ci
36508c2ecf20Sopenharmony_ci		if (pid2 == 0)
36518c2ecf20Sopenharmony_ci			exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC);
36528c2ecf20Sopenharmony_ci
36538c2ecf20Sopenharmony_ci		EXPECT_EQ(waitpid(pid2, &status, 0), pid2);
36548c2ecf20Sopenharmony_ci		EXPECT_EQ(true, WIFEXITED(status));
36558c2ecf20Sopenharmony_ci		EXPECT_EQ(0, WEXITSTATUS(status));
36568c2ecf20Sopenharmony_ci		exit(WEXITSTATUS(status));
36578c2ecf20Sopenharmony_ci	}
36588c2ecf20Sopenharmony_ci
36598c2ecf20Sopenharmony_ci	/* Create the sibling ns, and sibling in it. */
36608c2ecf20Sopenharmony_ci	ASSERT_EQ(unshare(CLONE_NEWPID), 0) {
36618c2ecf20Sopenharmony_ci		if (errno == EPERM)
36628c2ecf20Sopenharmony_ci			SKIP(return, "CLONE_NEWPID requires CAP_SYS_ADMIN");
36638c2ecf20Sopenharmony_ci	}
36648c2ecf20Sopenharmony_ci	ASSERT_EQ(errno, 0);
36658c2ecf20Sopenharmony_ci
36668c2ecf20Sopenharmony_ci	pid2 = fork();
36678c2ecf20Sopenharmony_ci	ASSERT_GE(pid2, 0);
36688c2ecf20Sopenharmony_ci
36698c2ecf20Sopenharmony_ci	if (pid2 == 0) {
36708c2ecf20Sopenharmony_ci		ASSERT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
36718c2ecf20Sopenharmony_ci		/*
36728c2ecf20Sopenharmony_ci		 * The pid should be 0, i.e. the task is in some namespace that
36738c2ecf20Sopenharmony_ci		 * we can't "see".
36748c2ecf20Sopenharmony_ci		 */
36758c2ecf20Sopenharmony_ci		EXPECT_EQ(req.pid, 0);
36768c2ecf20Sopenharmony_ci
36778c2ecf20Sopenharmony_ci		resp.id = req.id;
36788c2ecf20Sopenharmony_ci		resp.error = 0;
36798c2ecf20Sopenharmony_ci		resp.val = USER_NOTIF_MAGIC;
36808c2ecf20Sopenharmony_ci
36818c2ecf20Sopenharmony_ci		ASSERT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
36828c2ecf20Sopenharmony_ci		exit(0);
36838c2ecf20Sopenharmony_ci	}
36848c2ecf20Sopenharmony_ci
36858c2ecf20Sopenharmony_ci	close(listener);
36868c2ecf20Sopenharmony_ci
36878c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
36888c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
36898c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
36908c2ecf20Sopenharmony_ci
36918c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid2, &status, 0), pid2);
36928c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
36938c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
36948c2ecf20Sopenharmony_ci}
36958c2ecf20Sopenharmony_ci
36968c2ecf20Sopenharmony_ciTEST(user_notification_fault_recv)
36978c2ecf20Sopenharmony_ci{
36988c2ecf20Sopenharmony_ci	pid_t pid;
36998c2ecf20Sopenharmony_ci	int status, listener;
37008c2ecf20Sopenharmony_ci	struct seccomp_notif req = {};
37018c2ecf20Sopenharmony_ci	struct seccomp_notif_resp resp = {};
37028c2ecf20Sopenharmony_ci
37038c2ecf20Sopenharmony_ci	ASSERT_EQ(unshare(CLONE_NEWUSER), 0);
37048c2ecf20Sopenharmony_ci
37058c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_getppid,
37068c2ecf20Sopenharmony_ci				      SECCOMP_FILTER_FLAG_NEW_LISTENER);
37078c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
37088c2ecf20Sopenharmony_ci
37098c2ecf20Sopenharmony_ci	pid = fork();
37108c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
37118c2ecf20Sopenharmony_ci
37128c2ecf20Sopenharmony_ci	if (pid == 0)
37138c2ecf20Sopenharmony_ci		exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC);
37148c2ecf20Sopenharmony_ci
37158c2ecf20Sopenharmony_ci	/* Do a bad recv() */
37168c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, NULL), -1);
37178c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EFAULT);
37188c2ecf20Sopenharmony_ci
37198c2ecf20Sopenharmony_ci	/* We should still be able to receive this notification, though. */
37208c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
37218c2ecf20Sopenharmony_ci	EXPECT_EQ(req.pid, pid);
37228c2ecf20Sopenharmony_ci
37238c2ecf20Sopenharmony_ci	resp.id = req.id;
37248c2ecf20Sopenharmony_ci	resp.error = 0;
37258c2ecf20Sopenharmony_ci	resp.val = USER_NOTIF_MAGIC;
37268c2ecf20Sopenharmony_ci
37278c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
37288c2ecf20Sopenharmony_ci
37298c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
37308c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
37318c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
37328c2ecf20Sopenharmony_ci}
37338c2ecf20Sopenharmony_ci
37348c2ecf20Sopenharmony_ciTEST(seccomp_get_notif_sizes)
37358c2ecf20Sopenharmony_ci{
37368c2ecf20Sopenharmony_ci	struct seccomp_notif_sizes sizes;
37378c2ecf20Sopenharmony_ci
37388c2ecf20Sopenharmony_ci	ASSERT_EQ(seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes), 0);
37398c2ecf20Sopenharmony_ci	EXPECT_EQ(sizes.seccomp_notif, sizeof(struct seccomp_notif));
37408c2ecf20Sopenharmony_ci	EXPECT_EQ(sizes.seccomp_notif_resp, sizeof(struct seccomp_notif_resp));
37418c2ecf20Sopenharmony_ci}
37428c2ecf20Sopenharmony_ci
37438c2ecf20Sopenharmony_ciTEST(user_notification_continue)
37448c2ecf20Sopenharmony_ci{
37458c2ecf20Sopenharmony_ci	pid_t pid;
37468c2ecf20Sopenharmony_ci	long ret;
37478c2ecf20Sopenharmony_ci	int status, listener;
37488c2ecf20Sopenharmony_ci	struct seccomp_notif req = {};
37498c2ecf20Sopenharmony_ci	struct seccomp_notif_resp resp = {};
37508c2ecf20Sopenharmony_ci	struct pollfd pollfd;
37518c2ecf20Sopenharmony_ci
37528c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
37538c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
37548c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
37558c2ecf20Sopenharmony_ci	}
37568c2ecf20Sopenharmony_ci
37578c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_dup, SECCOMP_FILTER_FLAG_NEW_LISTENER);
37588c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
37598c2ecf20Sopenharmony_ci
37608c2ecf20Sopenharmony_ci	pid = fork();
37618c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
37628c2ecf20Sopenharmony_ci
37638c2ecf20Sopenharmony_ci	if (pid == 0) {
37648c2ecf20Sopenharmony_ci		int dup_fd, pipe_fds[2];
37658c2ecf20Sopenharmony_ci		pid_t self;
37668c2ecf20Sopenharmony_ci
37678c2ecf20Sopenharmony_ci		ASSERT_GE(pipe(pipe_fds), 0);
37688c2ecf20Sopenharmony_ci
37698c2ecf20Sopenharmony_ci		dup_fd = dup(pipe_fds[0]);
37708c2ecf20Sopenharmony_ci		ASSERT_GE(dup_fd, 0);
37718c2ecf20Sopenharmony_ci		EXPECT_NE(pipe_fds[0], dup_fd);
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci		self = getpid();
37748c2ecf20Sopenharmony_ci		ASSERT_EQ(filecmp(self, self, pipe_fds[0], dup_fd), 0);
37758c2ecf20Sopenharmony_ci		exit(0);
37768c2ecf20Sopenharmony_ci	}
37778c2ecf20Sopenharmony_ci
37788c2ecf20Sopenharmony_ci	pollfd.fd = listener;
37798c2ecf20Sopenharmony_ci	pollfd.events = POLLIN | POLLOUT;
37808c2ecf20Sopenharmony_ci
37818c2ecf20Sopenharmony_ci	EXPECT_GT(poll(&pollfd, 1, -1), 0);
37828c2ecf20Sopenharmony_ci	EXPECT_EQ(pollfd.revents, POLLIN);
37838c2ecf20Sopenharmony_ci
37848c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
37858c2ecf20Sopenharmony_ci
37868c2ecf20Sopenharmony_ci	pollfd.fd = listener;
37878c2ecf20Sopenharmony_ci	pollfd.events = POLLIN | POLLOUT;
37888c2ecf20Sopenharmony_ci
37898c2ecf20Sopenharmony_ci	EXPECT_GT(poll(&pollfd, 1, -1), 0);
37908c2ecf20Sopenharmony_ci	EXPECT_EQ(pollfd.revents, POLLOUT);
37918c2ecf20Sopenharmony_ci
37928c2ecf20Sopenharmony_ci	EXPECT_EQ(req.data.nr, __NR_dup);
37938c2ecf20Sopenharmony_ci
37948c2ecf20Sopenharmony_ci	resp.id = req.id;
37958c2ecf20Sopenharmony_ci	resp.flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
37968c2ecf20Sopenharmony_ci
37978c2ecf20Sopenharmony_ci	/*
37988c2ecf20Sopenharmony_ci	 * Verify that setting SECCOMP_USER_NOTIF_FLAG_CONTINUE enforces other
37998c2ecf20Sopenharmony_ci	 * args be set to 0.
38008c2ecf20Sopenharmony_ci	 */
38018c2ecf20Sopenharmony_ci	resp.error = 0;
38028c2ecf20Sopenharmony_ci	resp.val = USER_NOTIF_MAGIC;
38038c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1);
38048c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EINVAL);
38058c2ecf20Sopenharmony_ci
38068c2ecf20Sopenharmony_ci	resp.error = USER_NOTIF_MAGIC;
38078c2ecf20Sopenharmony_ci	resp.val = 0;
38088c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1);
38098c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EINVAL);
38108c2ecf20Sopenharmony_ci
38118c2ecf20Sopenharmony_ci	resp.error = 0;
38128c2ecf20Sopenharmony_ci	resp.val = 0;
38138c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0) {
38148c2ecf20Sopenharmony_ci		if (errno == EINVAL)
38158c2ecf20Sopenharmony_ci			SKIP(goto skip, "Kernel does not support SECCOMP_USER_NOTIF_FLAG_CONTINUE");
38168c2ecf20Sopenharmony_ci	}
38178c2ecf20Sopenharmony_ci
38188c2ecf20Sopenharmony_ciskip:
38198c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
38208c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
38218c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status)) {
38228c2ecf20Sopenharmony_ci		if (WEXITSTATUS(status) == 2) {
38238c2ecf20Sopenharmony_ci			SKIP(return, "Kernel does not support kcmp() syscall");
38248c2ecf20Sopenharmony_ci			return;
38258c2ecf20Sopenharmony_ci		}
38268c2ecf20Sopenharmony_ci	}
38278c2ecf20Sopenharmony_ci}
38288c2ecf20Sopenharmony_ci
38298c2ecf20Sopenharmony_ciTEST(user_notification_filter_empty)
38308c2ecf20Sopenharmony_ci{
38318c2ecf20Sopenharmony_ci	pid_t pid;
38328c2ecf20Sopenharmony_ci	long ret;
38338c2ecf20Sopenharmony_ci	int status;
38348c2ecf20Sopenharmony_ci	struct pollfd pollfd;
38358c2ecf20Sopenharmony_ci	struct __clone_args args = {
38368c2ecf20Sopenharmony_ci		.flags = CLONE_FILES,
38378c2ecf20Sopenharmony_ci		.exit_signal = SIGCHLD,
38388c2ecf20Sopenharmony_ci	};
38398c2ecf20Sopenharmony_ci
38408c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
38418c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
38428c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
38438c2ecf20Sopenharmony_ci	}
38448c2ecf20Sopenharmony_ci
38458c2ecf20Sopenharmony_ci	pid = sys_clone3(&args, sizeof(args));
38468c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
38478c2ecf20Sopenharmony_ci
38488c2ecf20Sopenharmony_ci	if (pid == 0) {
38498c2ecf20Sopenharmony_ci		int listener;
38508c2ecf20Sopenharmony_ci
38518c2ecf20Sopenharmony_ci		listener = user_notif_syscall(__NR_mknodat, SECCOMP_FILTER_FLAG_NEW_LISTENER);
38528c2ecf20Sopenharmony_ci		if (listener < 0)
38538c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
38548c2ecf20Sopenharmony_ci
38558c2ecf20Sopenharmony_ci		if (dup2(listener, 200) != 200)
38568c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
38578c2ecf20Sopenharmony_ci
38588c2ecf20Sopenharmony_ci		close(listener);
38598c2ecf20Sopenharmony_ci
38608c2ecf20Sopenharmony_ci		_exit(EXIT_SUCCESS);
38618c2ecf20Sopenharmony_ci	}
38628c2ecf20Sopenharmony_ci
38638c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
38648c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
38658c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
38668c2ecf20Sopenharmony_ci
38678c2ecf20Sopenharmony_ci	/*
38688c2ecf20Sopenharmony_ci	 * The seccomp filter has become unused so we should be notified once
38698c2ecf20Sopenharmony_ci	 * the kernel gets around to cleaning up task struct.
38708c2ecf20Sopenharmony_ci	 */
38718c2ecf20Sopenharmony_ci	pollfd.fd = 200;
38728c2ecf20Sopenharmony_ci	pollfd.events = POLLHUP;
38738c2ecf20Sopenharmony_ci
38748c2ecf20Sopenharmony_ci	EXPECT_GT(poll(&pollfd, 1, 2000), 0);
38758c2ecf20Sopenharmony_ci	EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0);
38768c2ecf20Sopenharmony_ci}
38778c2ecf20Sopenharmony_ci
38788c2ecf20Sopenharmony_cistatic void *do_thread(void *data)
38798c2ecf20Sopenharmony_ci{
38808c2ecf20Sopenharmony_ci	return NULL;
38818c2ecf20Sopenharmony_ci}
38828c2ecf20Sopenharmony_ci
38838c2ecf20Sopenharmony_ciTEST(user_notification_filter_empty_threaded)
38848c2ecf20Sopenharmony_ci{
38858c2ecf20Sopenharmony_ci	pid_t pid;
38868c2ecf20Sopenharmony_ci	long ret;
38878c2ecf20Sopenharmony_ci	int status;
38888c2ecf20Sopenharmony_ci	struct pollfd pollfd;
38898c2ecf20Sopenharmony_ci	struct __clone_args args = {
38908c2ecf20Sopenharmony_ci		.flags = CLONE_FILES,
38918c2ecf20Sopenharmony_ci		.exit_signal = SIGCHLD,
38928c2ecf20Sopenharmony_ci	};
38938c2ecf20Sopenharmony_ci
38948c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
38958c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
38968c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
38978c2ecf20Sopenharmony_ci	}
38988c2ecf20Sopenharmony_ci
38998c2ecf20Sopenharmony_ci	pid = sys_clone3(&args, sizeof(args));
39008c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
39018c2ecf20Sopenharmony_ci
39028c2ecf20Sopenharmony_ci	if (pid == 0) {
39038c2ecf20Sopenharmony_ci		pid_t pid1, pid2;
39048c2ecf20Sopenharmony_ci		int listener, status;
39058c2ecf20Sopenharmony_ci		pthread_t thread;
39068c2ecf20Sopenharmony_ci
39078c2ecf20Sopenharmony_ci		listener = user_notif_syscall(__NR_dup, SECCOMP_FILTER_FLAG_NEW_LISTENER);
39088c2ecf20Sopenharmony_ci		if (listener < 0)
39098c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
39108c2ecf20Sopenharmony_ci
39118c2ecf20Sopenharmony_ci		if (dup2(listener, 200) != 200)
39128c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
39138c2ecf20Sopenharmony_ci
39148c2ecf20Sopenharmony_ci		close(listener);
39158c2ecf20Sopenharmony_ci
39168c2ecf20Sopenharmony_ci		pid1 = fork();
39178c2ecf20Sopenharmony_ci		if (pid1 < 0)
39188c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
39198c2ecf20Sopenharmony_ci
39208c2ecf20Sopenharmony_ci		if (pid1 == 0)
39218c2ecf20Sopenharmony_ci			_exit(EXIT_SUCCESS);
39228c2ecf20Sopenharmony_ci
39238c2ecf20Sopenharmony_ci		pid2 = fork();
39248c2ecf20Sopenharmony_ci		if (pid2 < 0)
39258c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
39268c2ecf20Sopenharmony_ci
39278c2ecf20Sopenharmony_ci		if (pid2 == 0)
39288c2ecf20Sopenharmony_ci			_exit(EXIT_SUCCESS);
39298c2ecf20Sopenharmony_ci
39308c2ecf20Sopenharmony_ci		if (pthread_create(&thread, NULL, do_thread, NULL) ||
39318c2ecf20Sopenharmony_ci		    pthread_join(thread, NULL))
39328c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
39338c2ecf20Sopenharmony_ci
39348c2ecf20Sopenharmony_ci		if (pthread_create(&thread, NULL, do_thread, NULL) ||
39358c2ecf20Sopenharmony_ci		    pthread_join(thread, NULL))
39368c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
39378c2ecf20Sopenharmony_ci
39388c2ecf20Sopenharmony_ci		if (waitpid(pid1, &status, 0) != pid1 || !WIFEXITED(status) ||
39398c2ecf20Sopenharmony_ci		    WEXITSTATUS(status))
39408c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
39418c2ecf20Sopenharmony_ci
39428c2ecf20Sopenharmony_ci		if (waitpid(pid2, &status, 0) != pid2 || !WIFEXITED(status) ||
39438c2ecf20Sopenharmony_ci		    WEXITSTATUS(status))
39448c2ecf20Sopenharmony_ci			_exit(EXIT_FAILURE);
39458c2ecf20Sopenharmony_ci
39468c2ecf20Sopenharmony_ci		exit(EXIT_SUCCESS);
39478c2ecf20Sopenharmony_ci	}
39488c2ecf20Sopenharmony_ci
39498c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
39508c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
39518c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
39528c2ecf20Sopenharmony_ci
39538c2ecf20Sopenharmony_ci	/*
39548c2ecf20Sopenharmony_ci	 * The seccomp filter has become unused so we should be notified once
39558c2ecf20Sopenharmony_ci	 * the kernel gets around to cleaning up task struct.
39568c2ecf20Sopenharmony_ci	 */
39578c2ecf20Sopenharmony_ci	pollfd.fd = 200;
39588c2ecf20Sopenharmony_ci	pollfd.events = POLLHUP;
39598c2ecf20Sopenharmony_ci
39608c2ecf20Sopenharmony_ci	EXPECT_GT(poll(&pollfd, 1, 2000), 0);
39618c2ecf20Sopenharmony_ci	EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0);
39628c2ecf20Sopenharmony_ci}
39638c2ecf20Sopenharmony_ci
39648c2ecf20Sopenharmony_ciTEST(user_notification_addfd)
39658c2ecf20Sopenharmony_ci{
39668c2ecf20Sopenharmony_ci	pid_t pid;
39678c2ecf20Sopenharmony_ci	long ret;
39688c2ecf20Sopenharmony_ci	int status, listener, memfd, fd;
39698c2ecf20Sopenharmony_ci	struct seccomp_notif_addfd addfd = {};
39708c2ecf20Sopenharmony_ci	struct seccomp_notif_addfd_small small = {};
39718c2ecf20Sopenharmony_ci	struct seccomp_notif_addfd_big big = {};
39728c2ecf20Sopenharmony_ci	struct seccomp_notif req = {};
39738c2ecf20Sopenharmony_ci	struct seccomp_notif_resp resp = {};
39748c2ecf20Sopenharmony_ci	/* 100 ms */
39758c2ecf20Sopenharmony_ci	struct timespec delay = { .tv_nsec = 100000000 };
39768c2ecf20Sopenharmony_ci
39778c2ecf20Sopenharmony_ci	memfd = memfd_create("test", 0);
39788c2ecf20Sopenharmony_ci	ASSERT_GE(memfd, 0);
39798c2ecf20Sopenharmony_ci
39808c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
39818c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
39828c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
39838c2ecf20Sopenharmony_ci	}
39848c2ecf20Sopenharmony_ci
39858c2ecf20Sopenharmony_ci	/* Check that the basic notification machinery works */
39868c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_getppid,
39878c2ecf20Sopenharmony_ci				      SECCOMP_FILTER_FLAG_NEW_LISTENER);
39888c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
39898c2ecf20Sopenharmony_ci
39908c2ecf20Sopenharmony_ci	pid = fork();
39918c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
39928c2ecf20Sopenharmony_ci
39938c2ecf20Sopenharmony_ci	if (pid == 0) {
39948c2ecf20Sopenharmony_ci		if (syscall(__NR_getppid) != USER_NOTIF_MAGIC)
39958c2ecf20Sopenharmony_ci			exit(1);
39968c2ecf20Sopenharmony_ci		exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC);
39978c2ecf20Sopenharmony_ci	}
39988c2ecf20Sopenharmony_ci
39998c2ecf20Sopenharmony_ci	ASSERT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
40008c2ecf20Sopenharmony_ci
40018c2ecf20Sopenharmony_ci	addfd.srcfd = memfd;
40028c2ecf20Sopenharmony_ci	addfd.newfd = 0;
40038c2ecf20Sopenharmony_ci	addfd.id = req.id;
40048c2ecf20Sopenharmony_ci	addfd.flags = 0x0;
40058c2ecf20Sopenharmony_ci
40068c2ecf20Sopenharmony_ci	/* Verify bad newfd_flags cannot be set */
40078c2ecf20Sopenharmony_ci	addfd.newfd_flags = ~O_CLOEXEC;
40088c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd), -1);
40098c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EINVAL);
40108c2ecf20Sopenharmony_ci	addfd.newfd_flags = O_CLOEXEC;
40118c2ecf20Sopenharmony_ci
40128c2ecf20Sopenharmony_ci	/* Verify bad flags cannot be set */
40138c2ecf20Sopenharmony_ci	addfd.flags = 0xff;
40148c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd), -1);
40158c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EINVAL);
40168c2ecf20Sopenharmony_ci	addfd.flags = 0;
40178c2ecf20Sopenharmony_ci
40188c2ecf20Sopenharmony_ci	/* Verify that remote_fd cannot be set without setting flags */
40198c2ecf20Sopenharmony_ci	addfd.newfd = 1;
40208c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd), -1);
40218c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EINVAL);
40228c2ecf20Sopenharmony_ci	addfd.newfd = 0;
40238c2ecf20Sopenharmony_ci
40248c2ecf20Sopenharmony_ci	/* Verify small size cannot be set */
40258c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD_SMALL, &small), -1);
40268c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EINVAL);
40278c2ecf20Sopenharmony_ci
40288c2ecf20Sopenharmony_ci	/* Verify we can't send bits filled in unknown buffer area */
40298c2ecf20Sopenharmony_ci	memset(&big, 0xAA, sizeof(big));
40308c2ecf20Sopenharmony_ci	big.addfd = addfd;
40318c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD_BIG, &big), -1);
40328c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, E2BIG);
40338c2ecf20Sopenharmony_ci
40348c2ecf20Sopenharmony_ci
40358c2ecf20Sopenharmony_ci	/* Verify we can set an arbitrary remote fd */
40368c2ecf20Sopenharmony_ci	fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd);
40378c2ecf20Sopenharmony_ci	/*
40388c2ecf20Sopenharmony_ci	 * The child has fds 0(stdin), 1(stdout), 2(stderr), 3(memfd),
40398c2ecf20Sopenharmony_ci	 * 4(listener), so the newly allocated fd should be 5.
40408c2ecf20Sopenharmony_ci	 */
40418c2ecf20Sopenharmony_ci	EXPECT_EQ(fd, 5);
40428c2ecf20Sopenharmony_ci	EXPECT_EQ(filecmp(getpid(), pid, memfd, fd), 0);
40438c2ecf20Sopenharmony_ci
40448c2ecf20Sopenharmony_ci	/* Verify we can set an arbitrary remote fd with large size */
40458c2ecf20Sopenharmony_ci	memset(&big, 0x0, sizeof(big));
40468c2ecf20Sopenharmony_ci	big.addfd = addfd;
40478c2ecf20Sopenharmony_ci	fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD_BIG, &big);
40488c2ecf20Sopenharmony_ci	EXPECT_EQ(fd, 6);
40498c2ecf20Sopenharmony_ci
40508c2ecf20Sopenharmony_ci	/* Verify we can set a specific remote fd */
40518c2ecf20Sopenharmony_ci	addfd.newfd = 42;
40528c2ecf20Sopenharmony_ci	addfd.flags = SECCOMP_ADDFD_FLAG_SETFD;
40538c2ecf20Sopenharmony_ci	fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd);
40548c2ecf20Sopenharmony_ci	EXPECT_EQ(fd, 42);
40558c2ecf20Sopenharmony_ci	EXPECT_EQ(filecmp(getpid(), pid, memfd, fd), 0);
40568c2ecf20Sopenharmony_ci
40578c2ecf20Sopenharmony_ci	/* Resume syscall */
40588c2ecf20Sopenharmony_ci	resp.id = req.id;
40598c2ecf20Sopenharmony_ci	resp.error = 0;
40608c2ecf20Sopenharmony_ci	resp.val = USER_NOTIF_MAGIC;
40618c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
40628c2ecf20Sopenharmony_ci
40638c2ecf20Sopenharmony_ci	/*
40648c2ecf20Sopenharmony_ci	 * This sets the ID of the ADD FD to the last request plus 1. The
40658c2ecf20Sopenharmony_ci	 * notification ID increments 1 per notification.
40668c2ecf20Sopenharmony_ci	 */
40678c2ecf20Sopenharmony_ci	addfd.id = req.id + 1;
40688c2ecf20Sopenharmony_ci
40698c2ecf20Sopenharmony_ci	/* This spins until the underlying notification is generated */
40708c2ecf20Sopenharmony_ci	while (ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd) != -1 &&
40718c2ecf20Sopenharmony_ci	       errno != -EINPROGRESS)
40728c2ecf20Sopenharmony_ci		nanosleep(&delay, NULL);
40738c2ecf20Sopenharmony_ci
40748c2ecf20Sopenharmony_ci	memset(&req, 0, sizeof(req));
40758c2ecf20Sopenharmony_ci	ASSERT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
40768c2ecf20Sopenharmony_ci	ASSERT_EQ(addfd.id, req.id);
40778c2ecf20Sopenharmony_ci
40788c2ecf20Sopenharmony_ci	resp.id = req.id;
40798c2ecf20Sopenharmony_ci	resp.error = 0;
40808c2ecf20Sopenharmony_ci	resp.val = USER_NOTIF_MAGIC;
40818c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
40828c2ecf20Sopenharmony_ci
40838c2ecf20Sopenharmony_ci	/* Wait for child to finish. */
40848c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
40858c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
40868c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
40878c2ecf20Sopenharmony_ci
40888c2ecf20Sopenharmony_ci	close(memfd);
40898c2ecf20Sopenharmony_ci}
40908c2ecf20Sopenharmony_ci
40918c2ecf20Sopenharmony_ciTEST(user_notification_addfd_rlimit)
40928c2ecf20Sopenharmony_ci{
40938c2ecf20Sopenharmony_ci	pid_t pid;
40948c2ecf20Sopenharmony_ci	long ret;
40958c2ecf20Sopenharmony_ci	int status, listener, memfd;
40968c2ecf20Sopenharmony_ci	struct seccomp_notif_addfd addfd = {};
40978c2ecf20Sopenharmony_ci	struct seccomp_notif req = {};
40988c2ecf20Sopenharmony_ci	struct seccomp_notif_resp resp = {};
40998c2ecf20Sopenharmony_ci	const struct rlimit lim = {
41008c2ecf20Sopenharmony_ci		.rlim_cur	= 0,
41018c2ecf20Sopenharmony_ci		.rlim_max	= 0,
41028c2ecf20Sopenharmony_ci	};
41038c2ecf20Sopenharmony_ci
41048c2ecf20Sopenharmony_ci	memfd = memfd_create("test", 0);
41058c2ecf20Sopenharmony_ci	ASSERT_GE(memfd, 0);
41068c2ecf20Sopenharmony_ci
41078c2ecf20Sopenharmony_ci	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
41088c2ecf20Sopenharmony_ci	ASSERT_EQ(0, ret) {
41098c2ecf20Sopenharmony_ci		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
41108c2ecf20Sopenharmony_ci	}
41118c2ecf20Sopenharmony_ci
41128c2ecf20Sopenharmony_ci	/* Check that the basic notification machinery works */
41138c2ecf20Sopenharmony_ci	listener = user_notif_syscall(__NR_getppid,
41148c2ecf20Sopenharmony_ci				      SECCOMP_FILTER_FLAG_NEW_LISTENER);
41158c2ecf20Sopenharmony_ci	ASSERT_GE(listener, 0);
41168c2ecf20Sopenharmony_ci
41178c2ecf20Sopenharmony_ci	pid = fork();
41188c2ecf20Sopenharmony_ci	ASSERT_GE(pid, 0);
41198c2ecf20Sopenharmony_ci
41208c2ecf20Sopenharmony_ci	if (pid == 0)
41218c2ecf20Sopenharmony_ci		exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC);
41228c2ecf20Sopenharmony_ci
41238c2ecf20Sopenharmony_ci
41248c2ecf20Sopenharmony_ci	ASSERT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
41258c2ecf20Sopenharmony_ci
41268c2ecf20Sopenharmony_ci	ASSERT_EQ(prlimit(pid, RLIMIT_NOFILE, &lim, NULL), 0);
41278c2ecf20Sopenharmony_ci
41288c2ecf20Sopenharmony_ci	addfd.srcfd = memfd;
41298c2ecf20Sopenharmony_ci	addfd.newfd_flags = O_CLOEXEC;
41308c2ecf20Sopenharmony_ci	addfd.newfd = 0;
41318c2ecf20Sopenharmony_ci	addfd.id = req.id;
41328c2ecf20Sopenharmony_ci	addfd.flags = 0;
41338c2ecf20Sopenharmony_ci
41348c2ecf20Sopenharmony_ci	/* Should probably spot check /proc/sys/fs/file-nr */
41358c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd), -1);
41368c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EMFILE);
41378c2ecf20Sopenharmony_ci
41388c2ecf20Sopenharmony_ci	addfd.newfd = 100;
41398c2ecf20Sopenharmony_ci	addfd.flags = SECCOMP_ADDFD_FLAG_SETFD;
41408c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd), -1);
41418c2ecf20Sopenharmony_ci	EXPECT_EQ(errno, EBADF);
41428c2ecf20Sopenharmony_ci
41438c2ecf20Sopenharmony_ci	resp.id = req.id;
41448c2ecf20Sopenharmony_ci	resp.error = 0;
41458c2ecf20Sopenharmony_ci	resp.val = USER_NOTIF_MAGIC;
41468c2ecf20Sopenharmony_ci
41478c2ecf20Sopenharmony_ci	EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0);
41488c2ecf20Sopenharmony_ci
41498c2ecf20Sopenharmony_ci	/* Wait for child to finish. */
41508c2ecf20Sopenharmony_ci	EXPECT_EQ(waitpid(pid, &status, 0), pid);
41518c2ecf20Sopenharmony_ci	EXPECT_EQ(true, WIFEXITED(status));
41528c2ecf20Sopenharmony_ci	EXPECT_EQ(0, WEXITSTATUS(status));
41538c2ecf20Sopenharmony_ci
41548c2ecf20Sopenharmony_ci	close(memfd);
41558c2ecf20Sopenharmony_ci}
41568c2ecf20Sopenharmony_ci
41578c2ecf20Sopenharmony_ci/*
41588c2ecf20Sopenharmony_ci * TODO:
41598c2ecf20Sopenharmony_ci * - expand NNP testing
41608c2ecf20Sopenharmony_ci * - better arch-specific TRACE and TRAP handlers.
41618c2ecf20Sopenharmony_ci * - endianness checking when appropriate
41628c2ecf20Sopenharmony_ci * - 64-bit arg prodding
41638c2ecf20Sopenharmony_ci * - arch value testing (x86 modes especially)
41648c2ecf20Sopenharmony_ci * - verify that FILTER_FLAG_LOG filters generate log messages
41658c2ecf20Sopenharmony_ci * - verify that RET_LOG generates log messages
41668c2ecf20Sopenharmony_ci */
41678c2ecf20Sopenharmony_ci
41688c2ecf20Sopenharmony_ciTEST_HARNESS_MAIN
4169