1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/types.h>
16 #include <sys/ioctl.h>
17 #include <sys/mount.h>
18 #include <sys/prctl.h>
23 #include "../kselftest.h"
25 #ifndef PIDFS_IOCTL_MAGIC
26 #define PIDFS_IOCTL_MAGIC 0xFF
29 #ifndef PIDFD_GET_INFO
30 #define PIDFD_GET_INFO _IOWR(PIDFS_IOCTL_MAGIC, 11, struct pidfd_info)
31 #define PIDFD_INFO_CGROUPID (1UL << 0)
51 static int safe_int(const char *numstr
, int *converted
)
57 sli
= strtol(numstr
, &err
, 0);
58 if (errno
== ERANGE
&& (sli
== LONG_MAX
|| sli
== LONG_MIN
))
61 if (errno
!= 0 && sli
== 0)
64 if (err
== numstr
|| *err
!= '\0')
67 if (sli
> INT_MAX
|| sli
< INT_MIN
)
70 *converted
= (int)sli
;
74 static int char_left_gc(const char *buffer
, size_t len
)
78 for (i
= 0; i
< len
; i
++) {
79 if (buffer
[i
] == ' ' ||
89 static int char_right_gc(const char *buffer
, size_t len
)
93 for (i
= len
- 1; i
>= 0; i
--) {
94 if (buffer
[i
] == ' ' ||
106 static char *trim_whitespace_in_place(char *buffer
)
108 buffer
+= char_left_gc(buffer
, strlen(buffer
));
109 buffer
[char_right_gc(buffer
, strlen(buffer
))] = '\0';
113 static pid_t
get_pid_from_fdinfo_file(int pidfd
, const char *key
, size_t keylen
)
122 snprintf(path
, sizeof(path
), "/proc/self/fdinfo/%d", pidfd
);
124 f
= fopen(path
, "re");
128 while (getline(&line
, &n
, f
) != -1) {
131 if (strncmp(line
, key
, keylen
))
134 numstr
= trim_whitespace_in_place(line
+ 4);
135 ret
= safe_int(numstr
, &result
);
148 int main(int argc
, char **argv
)
150 struct pidfd_info info
= {
151 .request_mask
= PIDFD_INFO_CGROUPID
,
153 int pidfd
= -1, ret
= 1;
158 pidfd
= sys_pidfd_open(-1, 0);
161 "%s - succeeded to open pidfd for invalid pid -1\n",
165 ksft_test_result_pass("do not allow invalid pid test: passed\n");
167 pidfd
= sys_pidfd_open(getpid(), 1);
170 "%s - succeeded to open pidfd with invalid flag value specified\n",
174 ksft_test_result_pass("do not allow invalid flag test: passed\n");
176 pidfd
= sys_pidfd_open(getpid(), 0);
178 ksft_print_msg("%s - failed to open pidfd\n", strerror(errno
));
181 ksft_test_result_pass("open a new pidfd test: passed\n");
183 pid
= get_pid_from_fdinfo_file(pidfd
, "Pid:", sizeof("Pid:") - 1);
184 ksft_print_msg("pidfd %d refers to process with pid %d\n", pidfd
, pid
);
186 if (ioctl(pidfd
, PIDFD_GET_INFO
, &info
) < 0) {
187 ksft_print_msg("%s - failed to get info from pidfd\n", strerror(errno
));
190 if (info
.pid
!= pid
) {
191 ksft_print_msg("pid from fdinfo file %d does not match pid from ioctl %d\n",
195 if (info
.ppid
!= getppid()) {
196 ksft_print_msg("ppid %d does not match ppid from ioctl %d\n",
200 if (info
.ruid
!= getuid()) {
201 ksft_print_msg("uid %d does not match uid from ioctl %d\n",
202 getuid(), info
.ruid
);
205 if (info
.rgid
!= getgid()) {
206 ksft_print_msg("gid %d does not match gid from ioctl %d\n",
207 getgid(), info
.rgid
);
210 if (info
.euid
!= geteuid()) {
211 ksft_print_msg("euid %d does not match euid from ioctl %d\n",
212 geteuid(), info
.euid
);
215 if (info
.egid
!= getegid()) {
216 ksft_print_msg("egid %d does not match egid from ioctl %d\n",
217 getegid(), info
.egid
);
220 if (info
.suid
!= geteuid()) {
221 ksft_print_msg("suid %d does not match suid from ioctl %d\n",
222 geteuid(), info
.suid
);
225 if (info
.sgid
!= getegid()) {
226 ksft_print_msg("sgid %d does not match sgid from ioctl %d\n",
227 getegid(), info
.sgid
);
230 if ((info
.request_mask
& PIDFD_INFO_CGROUPID
) && info
.cgroupid
== 0) {
231 ksft_print_msg("cgroupid should not be 0 when PIDFD_INFO_CGROUPID is set\n");
234 ksft_test_result_pass("get info from pidfd test: passed\n");