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_THREAD 135 #define PIDFD_THREAD O_EXCL 136 #endif 137 138 struct pidfd_info { 139 __u64 mask; 140 __u64 cgroupid; 141 __u32 pid; 142 __u32 tgid; 143 __u32 ppid; 144 __u32 ruid; 145 __u32 rgid; 146 __u32 euid; 147 __u32 egid; 148 __u32 suid; 149 __u32 sgid; 150 __u32 fsuid; 151 __u32 fsgid; 152 __s32 exit_code; 153 }; 154 155 /* 156 * The kernel reserves 300 pids via RESERVED_PIDS in kernel/pid.c 157 * That means, when it wraps around any pid < 300 will be skipped. 158 * So we need to use a pid > 300 in order to test recycling. 159 */ 160 #define PID_RECYCLE 1000 161 162 /* 163 * Define a few custom error codes for the child process to clearly indicate 164 * what is happening. This way we can tell the difference between a system 165 * error, a test error, etc. 166 */ 167 #define PIDFD_PASS 0 168 #define PIDFD_FAIL 1 169 #define PIDFD_ERROR 2 170 #define PIDFD_SKIP 3 171 #define PIDFD_XFAIL 4 172 173 static inline int sys_waitid(int which, pid_t pid, siginfo_t *info, int options) 174 { 175 return syscall(__NR_waitid, which, pid, info, options, NULL); 176 } 177 178 static inline int wait_for_pid(pid_t pid) 179 { 180 int status, ret; 181 182 again: 183 ret = waitpid(pid, &status, 0); 184 if (ret == -1) { 185 if (errno == EINTR) 186 goto again; 187 188 ksft_print_msg("waitpid returned -1, errno=%d\n", errno); 189 return -1; 190 } 191 192 if (!WIFEXITED(status)) { 193 ksft_print_msg( 194 "waitpid !WIFEXITED, WIFSIGNALED=%d, WTERMSIG=%d\n", 195 WIFSIGNALED(status), WTERMSIG(status)); 196 return -1; 197 } 198 199 ret = WEXITSTATUS(status); 200 return ret; 201 } 202 203 static inline int sys_pidfd_open(pid_t pid, unsigned int flags) 204 { 205 return syscall(__NR_pidfd_open, pid, flags); 206 } 207 208 static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, 209 unsigned int flags) 210 { 211 return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags); 212 } 213 214 static inline int sys_pidfd_getfd(int pidfd, int fd, int flags) 215 { 216 return syscall(__NR_pidfd_getfd, pidfd, fd, flags); 217 } 218 219 static inline int sys_memfd_create(const char *name, unsigned int flags) 220 { 221 return syscall(__NR_memfd_create, name, flags); 222 } 223 224 static inline pid_t create_child(int *pidfd, unsigned flags) 225 { 226 struct __clone_args args = { 227 .flags = CLONE_PIDFD | flags, 228 .exit_signal = SIGCHLD, 229 .pidfd = ptr_to_u64(pidfd), 230 }; 231 232 return sys_clone3(&args, sizeof(struct __clone_args)); 233 } 234 235 static inline ssize_t read_nointr(int fd, void *buf, size_t count) 236 { 237 ssize_t ret; 238 239 do { 240 ret = read(fd, buf, count); 241 } while (ret < 0 && errno == EINTR); 242 243 return ret; 244 } 245 246 static inline ssize_t write_nointr(int fd, const void *buf, size_t count) 247 { 248 ssize_t ret; 249 250 do { 251 ret = write(fd, buf, count); 252 } while (ret < 0 && errno == EINTR); 253 254 return ret; 255 } 256 257 static inline int sys_execveat(int dirfd, const char *pathname, 258 char *const argv[], char *const envp[], 259 int flags) 260 { 261 return syscall(__NR_execveat, dirfd, pathname, argv, envp, flags); 262 } 263 264 #endif /* __PIDFD_H */ 265