Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  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}