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