Linux Audio

Check our new training course

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