1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun #define _GNU_SOURCE
4*4882a593Smuzhiyun #include <errno.h>
5*4882a593Smuzhiyun #include <fcntl.h>
6*4882a593Smuzhiyun #include <inttypes.h>
7*4882a593Smuzhiyun #include <limits.h>
8*4882a593Smuzhiyun #include <linux/types.h>
9*4882a593Smuzhiyun #include <sched.h>
10*4882a593Smuzhiyun #include <signal.h>
11*4882a593Smuzhiyun #include <stdbool.h>
12*4882a593Smuzhiyun #include <stdio.h>
13*4882a593Smuzhiyun #include <stdlib.h>
14*4882a593Smuzhiyun #include <string.h>
15*4882a593Smuzhiyun #include <syscall.h>
16*4882a593Smuzhiyun #include <sys/mount.h>
17*4882a593Smuzhiyun #include <sys/prctl.h>
18*4882a593Smuzhiyun #include <sys/wait.h>
19*4882a593Smuzhiyun #include <unistd.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #include "pidfd.h"
22*4882a593Smuzhiyun #include "../kselftest.h"
23*4882a593Smuzhiyun
safe_int(const char * numstr,int * converted)24*4882a593Smuzhiyun static int safe_int(const char *numstr, int *converted)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun char *err = NULL;
27*4882a593Smuzhiyun long sli;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun errno = 0;
30*4882a593Smuzhiyun sli = strtol(numstr, &err, 0);
31*4882a593Smuzhiyun if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
32*4882a593Smuzhiyun return -ERANGE;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun if (errno != 0 && sli == 0)
35*4882a593Smuzhiyun return -EINVAL;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun if (err == numstr || *err != '\0')
38*4882a593Smuzhiyun return -EINVAL;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun if (sli > INT_MAX || sli < INT_MIN)
41*4882a593Smuzhiyun return -ERANGE;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun *converted = (int)sli;
44*4882a593Smuzhiyun return 0;
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
char_left_gc(const char * buffer,size_t len)47*4882a593Smuzhiyun static int char_left_gc(const char *buffer, size_t len)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun size_t i;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun for (i = 0; i < len; i++) {
52*4882a593Smuzhiyun if (buffer[i] == ' ' ||
53*4882a593Smuzhiyun buffer[i] == '\t')
54*4882a593Smuzhiyun continue;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun return i;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun return 0;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
char_right_gc(const char * buffer,size_t len)62*4882a593Smuzhiyun static int char_right_gc(const char *buffer, size_t len)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun int i;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun for (i = len - 1; i >= 0; i--) {
67*4882a593Smuzhiyun if (buffer[i] == ' ' ||
68*4882a593Smuzhiyun buffer[i] == '\t' ||
69*4882a593Smuzhiyun buffer[i] == '\n' ||
70*4882a593Smuzhiyun buffer[i] == '\0')
71*4882a593Smuzhiyun continue;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun return i + 1;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun return 0;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
trim_whitespace_in_place(char * buffer)79*4882a593Smuzhiyun static char *trim_whitespace_in_place(char *buffer)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun buffer += char_left_gc(buffer, strlen(buffer));
82*4882a593Smuzhiyun buffer[char_right_gc(buffer, strlen(buffer))] = '\0';
83*4882a593Smuzhiyun return buffer;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
get_pid_from_fdinfo_file(int pidfd,const char * key,size_t keylen)86*4882a593Smuzhiyun static pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun int ret;
89*4882a593Smuzhiyun char path[512];
90*4882a593Smuzhiyun FILE *f;
91*4882a593Smuzhiyun size_t n = 0;
92*4882a593Smuzhiyun pid_t result = -1;
93*4882a593Smuzhiyun char *line = NULL;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun f = fopen(path, "re");
98*4882a593Smuzhiyun if (!f)
99*4882a593Smuzhiyun return -1;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun while (getline(&line, &n, f) != -1) {
102*4882a593Smuzhiyun char *numstr;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun if (strncmp(line, key, keylen))
105*4882a593Smuzhiyun continue;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun numstr = trim_whitespace_in_place(line + 4);
108*4882a593Smuzhiyun ret = safe_int(numstr, &result);
109*4882a593Smuzhiyun if (ret < 0)
110*4882a593Smuzhiyun goto out;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun break;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun out:
116*4882a593Smuzhiyun free(line);
117*4882a593Smuzhiyun fclose(f);
118*4882a593Smuzhiyun return result;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
main(int argc,char ** argv)121*4882a593Smuzhiyun int main(int argc, char **argv)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun int pidfd = -1, ret = 1;
124*4882a593Smuzhiyun pid_t pid;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun ksft_set_plan(3);
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun pidfd = sys_pidfd_open(-1, 0);
129*4882a593Smuzhiyun if (pidfd >= 0) {
130*4882a593Smuzhiyun ksft_print_msg(
131*4882a593Smuzhiyun "%s - succeeded to open pidfd for invalid pid -1\n",
132*4882a593Smuzhiyun strerror(errno));
133*4882a593Smuzhiyun goto on_error;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun ksft_test_result_pass("do not allow invalid pid test: passed\n");
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun pidfd = sys_pidfd_open(getpid(), 1);
138*4882a593Smuzhiyun if (pidfd >= 0) {
139*4882a593Smuzhiyun ksft_print_msg(
140*4882a593Smuzhiyun "%s - succeeded to open pidfd with invalid flag value specified\n",
141*4882a593Smuzhiyun strerror(errno));
142*4882a593Smuzhiyun goto on_error;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun ksft_test_result_pass("do not allow invalid flag test: passed\n");
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun pidfd = sys_pidfd_open(getpid(), 0);
147*4882a593Smuzhiyun if (pidfd < 0) {
148*4882a593Smuzhiyun ksft_print_msg("%s - failed to open pidfd\n", strerror(errno));
149*4882a593Smuzhiyun goto on_error;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun ksft_test_result_pass("open a new pidfd test: passed\n");
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun pid = get_pid_from_fdinfo_file(pidfd, "Pid:", sizeof("Pid:") - 1);
154*4882a593Smuzhiyun ksft_print_msg("pidfd %d refers to process with pid %d\n", pidfd, pid);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun ret = 0;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun on_error:
159*4882a593Smuzhiyun if (pidfd >= 0)
160*4882a593Smuzhiyun close(pidfd);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun return !ret ? ksft_exit_pass() : ksft_exit_fail();
163*4882a593Smuzhiyun }
164