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