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/mount.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 
19 #include "../kselftest.h"
20 
21 #ifndef P_PIDFD
22 #define P_PIDFD 3
23 #endif
24 
25 #ifndef CLONE_NEWTIME
26 #define CLONE_NEWTIME 0x00000080
27 #endif
28 
29 #ifndef CLONE_PIDFD
30 #define CLONE_PIDFD 0x00001000
31 #endif
32 
33 #ifndef __NR_pidfd_open
34 #define __NR_pidfd_open -1
35 #endif
36 
37 #ifndef __NR_pidfd_send_signal
38 #define __NR_pidfd_send_signal -1
39 #endif
40 
41 #ifndef __NR_clone3
42 #define __NR_clone3 -1
43 #endif
44 
45 #ifndef __NR_pidfd_getfd
46 #define __NR_pidfd_getfd -1
47 #endif
48 
49 /*
50  * The kernel reserves 300 pids via RESERVED_PIDS in kernel/pid.c
51  * That means, when it wraps around any pid < 300 will be skipped.
52  * So we need to use a pid > 300 in order to test recycling.
53  */
54 #define PID_RECYCLE 1000
55 
56 /*
57  * Define a few custom error codes for the child process to clearly indicate
58  * what is happening. This way we can tell the difference between a system
59  * error, a test error, etc.
60  */
61 #define PIDFD_PASS 0
62 #define PIDFD_FAIL 1
63 #define PIDFD_ERROR 2
64 #define PIDFD_SKIP 3
65 #define PIDFD_XFAIL 4
66 
67 int wait_for_pid(pid_t pid)
68 {
69 	int status, ret;
70 
71 again:
72 	ret = waitpid(pid, &status, 0);
73 	if (ret == -1) {
74 		if (errno == EINTR)
75 			goto again;
76 
77 		return -1;
78 	}
79 
80 	if (!WIFEXITED(status))
81 		return -1;
82 
83 	return WEXITSTATUS(status);
84 }
85 
86 static inline int sys_pidfd_open(pid_t pid, unsigned int flags)
87 {
88 	return syscall(__NR_pidfd_open, pid, flags);
89 }
90 
91 static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
92 					unsigned int flags)
93 {
94 	return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
95 }
96 
97 static inline int sys_pidfd_getfd(int pidfd, int fd, int flags)
98 {
99 	return syscall(__NR_pidfd_getfd, pidfd, fd, flags);
100 }
101 
102 static inline int sys_memfd_create(const char *name, unsigned int flags)
103 {
104 	return syscall(__NR_memfd_create, name, flags);
105 }
106 
107 #endif /* __PIDFD_H */
108