File Index
Files and directories
Sign in
FILE

pidfd_open_test.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/pidfd/pidfd_open_test.c 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 <sched.h>
 10#include <signal.h>
 11#include <stdbool.h>
 12#include <stdio.h>
 13#include <stdlib.h>
 14#include <string.h>
 15#include <syscall.h>
 16#include <sys/ioctl.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
 25static int safe_int(const char *numstr, int *converted)
 26{
 27	char *err = NULL;
 28	long sli;
 29
 30	errno = 0;
 31	sli = strtol(numstr, &err, 0);
 32	if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
 33		return -ERANGE;
 34
 35	if (errno != 0 && sli == 0)
 36		return -EINVAL;
 37
 38	if (err == numstr || *err != '\0')
 39		return -EINVAL;
 40
 41	if (sli > INT_MAX || sli < INT_MIN)
 42		return -ERANGE;
 43
 44	*converted = (int)sli;
 45	return 0;
 46}
 47
 48static int char_left_gc(const char *buffer, size_t len)
 49{
 50	size_t i;
 51
 52	for (i = 0; i < len; i++) {
 53		if (buffer[i] == ' ' ||
 54		    buffer[i] == '\t')
 55			continue;
 56
 57		return i;
 58	}
 59
 60	return 0;
 61}
 62
 63static int char_right_gc(const char *buffer, size_t len)
 64{
 65	int i;
 66
 67	for (i = len - 1; i >= 0; i--) {
 68		if (buffer[i] == ' '  ||
 69		    buffer[i] == '\t' ||
 70		    buffer[i] == '\n' ||
 71		    buffer[i] == '\0')
 72			continue;
 73
 74		return i + 1;
 75	}
 76
 77	return 0;
 78}
 79
 80static char *trim_whitespace_in_place(char *buffer)
 81{
 82	buffer += char_left_gc(buffer, strlen(buffer));
 83	buffer[char_right_gc(buffer, strlen(buffer))] = '\0';
 84	return buffer;
 85}
 86
 87static pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen)
 88{
 89	int ret;
 90	char path[512];
 91	FILE *f;
 92	size_t n = 0;
 93	pid_t result = -1;
 94	char *line = NULL;
 95
 96	snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd);
 97
 98	f = fopen(path, "re");
 99	if (!f)
100		return -1;
101
102	while (getline(&line, &n, f) != -1) {
103		char *numstr;
104
105		if (strncmp(line, key, keylen))
106			continue;
107
108		numstr = trim_whitespace_in_place(line + 4);
109		ret = safe_int(numstr, &result);
110		if (ret < 0)
111			goto out;
112
113		break;
114	}
115
116out:
117	free(line);
118	fclose(f);
119	return result;
120}
121
122int main(int argc, char **argv)
123{
124	struct pidfd_info info = {
125		.mask = PIDFD_INFO_CGROUPID,
126	};
127	int pidfd = -1, ret = 1;
128	pid_t pid;
129
130	ksft_set_plan(4);
131
132	pidfd = sys_pidfd_open(-1, 0);
133	if (pidfd >= 0) {
134		ksft_print_msg(
135			"%s - succeeded to open pidfd for invalid pid -1\n",
136			strerror(errno));
137		goto on_error;
138	}
139	ksft_test_result_pass("do not allow invalid pid test: passed\n");
140
141	pidfd = sys_pidfd_open(getpid(), 1);
142	if (pidfd >= 0) {
143		ksft_print_msg(
144			"%s - succeeded to open pidfd with invalid flag value specified\n",
145			strerror(errno));
146		goto on_error;
147	}
148	ksft_test_result_pass("do not allow invalid flag test: passed\n");
149
150	pidfd = sys_pidfd_open(getpid(), 0);
151	if (pidfd < 0) {
152		ksft_print_msg("%s - failed to open pidfd\n", strerror(errno));
153		goto on_error;
154	}
155	ksft_test_result_pass("open a new pidfd test: passed\n");
156
157	pid = get_pid_from_fdinfo_file(pidfd, "Pid:", sizeof("Pid:") - 1);
158	ksft_print_msg("pidfd %d refers to process with pid %d\n", pidfd, pid);
159
160	if (ioctl(pidfd, PIDFD_GET_INFO, &info) < 0) {
161		ksft_print_msg("%s - failed to get info from pidfd\n", strerror(errno));
162		goto on_error;
163	}
164	if (info.pid != pid) {
165		ksft_print_msg("pid from fdinfo file %d does not match pid from ioctl %d\n",
166			       pid, info.pid);
167		goto on_error;
168	}
169	if (info.ppid != getppid()) {
170		ksft_print_msg("ppid %d does not match ppid from ioctl %d\n",
171			       pid, info.pid);
172		goto on_error;
173	}
174	if (info.ruid != getuid()) {
175		ksft_print_msg("uid %d does not match uid from ioctl %d\n",
176			       getuid(), info.ruid);
177		goto on_error;
178	}
179	if (info.rgid != getgid()) {
180		ksft_print_msg("gid %d does not match gid from ioctl %d\n",
181			       getgid(), info.rgid);
182		goto on_error;
183	}
184	if (info.euid != geteuid()) {
185		ksft_print_msg("euid %d does not match euid from ioctl %d\n",
186			       geteuid(), info.euid);
187		goto on_error;
188	}
189	if (info.egid != getegid()) {
190		ksft_print_msg("egid %d does not match egid from ioctl %d\n",
191			       getegid(), info.egid);
192		goto on_error;
193	}
194	if (info.suid != geteuid()) {
195		ksft_print_msg("suid %d does not match suid from ioctl %d\n",
196			       geteuid(), info.suid);
197		goto on_error;
198	}
199	if (info.sgid != getegid()) {
200		ksft_print_msg("sgid %d does not match sgid from ioctl %d\n",
201			       getegid(), info.sgid);
202		goto on_error;
203	}
204	if ((info.mask & PIDFD_INFO_CGROUPID) && info.cgroupid == 0) {
205		ksft_print_msg("cgroupid should not be 0 when PIDFD_INFO_CGROUPID is set\n");
206		goto on_error;
207	}
208	ksft_test_result_pass("get info from pidfd test: passed\n");
209
210	ret = 0;
211
212on_error:
213	if (pidfd >= 0)
214		close(pidfd);
215
216	if (ret)
217		ksft_exit_fail();
218	ksft_exit_pass();
219}
~/ Read-only file preview.