at v6.16-rc4 286 lines 6.4 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2 3#ifndef __PIDFD_H 4#define __PIDFD_H 5 6#define _GNU_SOURCE 7#include <errno.h> 8#include <fcntl.h> 9#include <sched.h> 10#include <signal.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14#include <syscall.h> 15#include <sys/ioctl.h> 16#include <sys/types.h> 17#include <sys/wait.h> 18 19#include "../kselftest.h" 20#include "../clone3/clone3_selftests.h" 21 22#ifndef P_PIDFD 23#define P_PIDFD 3 24#endif 25 26#ifndef CLONE_NEWTIME 27#define CLONE_NEWTIME 0x00000080 28#endif 29 30#ifndef CLONE_PIDFD 31#define CLONE_PIDFD 0x00001000 32#endif 33 34#ifndef __NR_pidfd_open 35#define __NR_pidfd_open 434 36#endif 37 38#ifndef __NR_pidfd_send_signal 39#define __NR_pidfd_send_signal 424 40#endif 41 42#ifndef __NR_clone3 43#define __NR_clone3 435 44#endif 45 46#ifndef __NR_pidfd_getfd 47#define __NR_pidfd_getfd 438 48#endif 49 50#ifndef PIDFD_NONBLOCK 51#define PIDFD_NONBLOCK O_NONBLOCK 52#endif 53 54#ifndef PIDFD_SELF_THREAD 55#define PIDFD_SELF_THREAD -10000 /* Current thread. */ 56#endif 57 58#ifndef PIDFD_SELF_THREAD_GROUP 59#define PIDFD_SELF_THREAD_GROUP -20000 /* Current thread group leader. */ 60#endif 61 62#ifndef PIDFD_SELF 63#define PIDFD_SELF PIDFD_SELF_THREAD 64#endif 65 66#ifndef PIDFD_SELF_PROCESS 67#define PIDFD_SELF_PROCESS PIDFD_SELF_THREAD_GROUP 68#endif 69 70#ifndef PIDFS_IOCTL_MAGIC 71#define PIDFS_IOCTL_MAGIC 0xFF 72#endif 73 74#ifndef PIDFD_GET_CGROUP_NAMESPACE 75#define PIDFD_GET_CGROUP_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 1) 76#endif 77 78#ifndef PIDFD_GET_IPC_NAMESPACE 79#define PIDFD_GET_IPC_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 2) 80#endif 81 82#ifndef PIDFD_GET_MNT_NAMESPACE 83#define PIDFD_GET_MNT_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 3) 84#endif 85 86#ifndef PIDFD_GET_NET_NAMESPACE 87#define PIDFD_GET_NET_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 4) 88#endif 89 90#ifndef PIDFD_GET_PID_NAMESPACE 91#define PIDFD_GET_PID_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 5) 92#endif 93 94#ifndef PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE 95#define PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 6) 96#endif 97 98#ifndef PIDFD_GET_TIME_NAMESPACE 99#define PIDFD_GET_TIME_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 7) 100#endif 101 102#ifndef PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE 103#define PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 8) 104#endif 105 106#ifndef PIDFD_GET_USER_NAMESPACE 107#define PIDFD_GET_USER_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 9) 108#endif 109 110#ifndef PIDFD_GET_UTS_NAMESPACE 111#define PIDFD_GET_UTS_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 10) 112#endif 113 114#ifndef PIDFD_GET_INFO 115#define PIDFD_GET_INFO _IOWR(PIDFS_IOCTL_MAGIC, 11, struct pidfd_info) 116#endif 117 118#ifndef PIDFD_INFO_PID 119#define PIDFD_INFO_PID (1UL << 0) /* Always returned, even if not requested */ 120#endif 121 122#ifndef PIDFD_INFO_CREDS 123#define PIDFD_INFO_CREDS (1UL << 1) /* Always returned, even if not requested */ 124#endif 125 126#ifndef PIDFD_INFO_CGROUPID 127#define PIDFD_INFO_CGROUPID (1UL << 2) /* Always returned if available, even if not requested */ 128#endif 129 130#ifndef PIDFD_INFO_EXIT 131#define PIDFD_INFO_EXIT (1UL << 3) /* Always returned if available, even if not requested */ 132#endif 133 134#ifndef PIDFD_INFO_COREDUMP 135#define PIDFD_INFO_COREDUMP (1UL << 4) 136#endif 137 138#ifndef PIDFD_COREDUMPED 139#define PIDFD_COREDUMPED (1U << 0) /* Did crash and... */ 140#endif 141 142#ifndef PIDFD_COREDUMP_SKIP 143#define PIDFD_COREDUMP_SKIP (1U << 1) /* coredumping generation was skipped. */ 144#endif 145 146#ifndef PIDFD_COREDUMP_USER 147#define PIDFD_COREDUMP_USER (1U << 2) /* coredump was done as the user. */ 148#endif 149 150#ifndef PIDFD_COREDUMP_ROOT 151#define PIDFD_COREDUMP_ROOT (1U << 3) /* coredump was done as root. */ 152#endif 153 154#ifndef PIDFD_THREAD 155#define PIDFD_THREAD O_EXCL 156#endif 157 158struct pidfd_info { 159 __u64 mask; 160 __u64 cgroupid; 161 __u32 pid; 162 __u32 tgid; 163 __u32 ppid; 164 __u32 ruid; 165 __u32 rgid; 166 __u32 euid; 167 __u32 egid; 168 __u32 suid; 169 __u32 sgid; 170 __u32 fsuid; 171 __u32 fsgid; 172 __s32 exit_code; 173 __u32 coredump_mask; 174 __u32 __spare1; 175}; 176 177/* 178 * The kernel reserves 300 pids via RESERVED_PIDS in kernel/pid.c 179 * That means, when it wraps around any pid < 300 will be skipped. 180 * So we need to use a pid > 300 in order to test recycling. 181 */ 182#define PID_RECYCLE 1000 183 184/* 185 * Define a few custom error codes for the child process to clearly indicate 186 * what is happening. This way we can tell the difference between a system 187 * error, a test error, etc. 188 */ 189#define PIDFD_PASS 0 190#define PIDFD_FAIL 1 191#define PIDFD_ERROR 2 192#define PIDFD_SKIP 3 193#define PIDFD_XFAIL 4 194 195static inline int sys_waitid(int which, pid_t pid, siginfo_t *info, int options) 196{ 197 return syscall(__NR_waitid, which, pid, info, options, NULL); 198} 199 200static inline int wait_for_pid(pid_t pid) 201{ 202 int status, ret; 203 204again: 205 ret = waitpid(pid, &status, 0); 206 if (ret == -1) { 207 if (errno == EINTR) 208 goto again; 209 210 ksft_print_msg("waitpid returned -1, errno=%d\n", errno); 211 return -1; 212 } 213 214 if (!WIFEXITED(status)) { 215 ksft_print_msg( 216 "waitpid !WIFEXITED, WIFSIGNALED=%d, WTERMSIG=%d\n", 217 WIFSIGNALED(status), WTERMSIG(status)); 218 return -1; 219 } 220 221 ret = WEXITSTATUS(status); 222 return ret; 223} 224 225static inline int sys_pidfd_open(pid_t pid, unsigned int flags) 226{ 227 return syscall(__NR_pidfd_open, pid, flags); 228} 229 230static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, 231 unsigned int flags) 232{ 233 return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags); 234} 235 236static inline int sys_pidfd_getfd(int pidfd, int fd, int flags) 237{ 238 return syscall(__NR_pidfd_getfd, pidfd, fd, flags); 239} 240 241static inline int sys_memfd_create(const char *name, unsigned int flags) 242{ 243 return syscall(__NR_memfd_create, name, flags); 244} 245 246static inline pid_t create_child(int *pidfd, unsigned flags) 247{ 248 struct __clone_args args = { 249 .flags = CLONE_PIDFD | flags, 250 .exit_signal = SIGCHLD, 251 .pidfd = ptr_to_u64(pidfd), 252 }; 253 254 return sys_clone3(&args, sizeof(struct __clone_args)); 255} 256 257static inline ssize_t read_nointr(int fd, void *buf, size_t count) 258{ 259 ssize_t ret; 260 261 do { 262 ret = read(fd, buf, count); 263 } while (ret < 0 && errno == EINTR); 264 265 return ret; 266} 267 268static inline ssize_t write_nointr(int fd, const void *buf, size_t count) 269{ 270 ssize_t ret; 271 272 do { 273 ret = write(fd, buf, count); 274 } while (ret < 0 && errno == EINTR); 275 276 return ret; 277} 278 279static inline int sys_execveat(int dirfd, const char *pathname, 280 char *const argv[], char *const envp[], 281 int flags) 282{ 283 return syscall(__NR_execveat, dirfd, pathname, argv, envp, flags); 284} 285 286#endif /* __PIDFD_H */