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, ®s, 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