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 | #ifndef PIDFD_NONBLOCK |
50 | #define PIDFD_NONBLOCK O_NONBLOCK |
51 | #endif |
52 | |
53 | /* |
54 | * The kernel reserves 300 pids via RESERVED_PIDS in kernel/pid.c |
55 | * That means, when it wraps around any pid < 300 will be skipped. |
56 | * So we need to use a pid > 300 in order to test recycling. |
57 | */ |
58 | #define PID_RECYCLE 1000 |
59 | |
60 | /* |
61 | * Define a few custom error codes for the child process to clearly indicate |
62 | * what is happening. This way we can tell the difference between a system |
63 | * error, a test error, etc. |
64 | */ |
65 | #define PIDFD_PASS 0 |
66 | #define PIDFD_FAIL 1 |
67 | #define PIDFD_ERROR 2 |
68 | #define PIDFD_SKIP 3 |
69 | #define PIDFD_XFAIL 4 |
70 | |
71 | static inline int wait_for_pid(pid_t pid) |
72 | { |
73 | int status, ret; |
74 | |
75 | again: |
76 | ret = waitpid(pid, &status, 0); |
77 | if (ret == -1) { |
78 | if (errno == EINTR) |
79 | goto again; |
80 | |
81 | ksft_print_msg(msg: "waitpid returned -1, errno=%d\n" , errno); |
82 | return -1; |
83 | } |
84 | |
85 | if (!WIFEXITED(status)) { |
86 | ksft_print_msg( |
87 | msg: "waitpid !WIFEXITED, WIFSIGNALED=%d, WTERMSIG=%d\n" , |
88 | WIFSIGNALED(status), WTERMSIG(status)); |
89 | return -1; |
90 | } |
91 | |
92 | ret = WEXITSTATUS(status); |
93 | return ret; |
94 | } |
95 | |
96 | static inline int sys_pidfd_open(pid_t pid, unsigned int flags) |
97 | { |
98 | return syscall(__NR_pidfd_open, pid, flags); |
99 | } |
100 | |
101 | static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, |
102 | unsigned int flags) |
103 | { |
104 | return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags); |
105 | } |
106 | |
107 | static inline int sys_pidfd_getfd(int pidfd, int fd, int flags) |
108 | { |
109 | return syscall(__NR_pidfd_getfd, pidfd, fd, flags); |
110 | } |
111 | |
112 | static inline int sys_memfd_create(const char *name, unsigned int flags) |
113 | { |
114 | return syscall(__NR_memfd_create, name, flags); |
115 | } |
116 | |
117 | #endif /* __PIDFD_H */ |
118 | |