0001
0002
0003 #define _GNU_SOURCE
0004 #include <errno.h>
0005 #include <fcntl.h>
0006 #include <inttypes.h>
0007 #include <limits.h>
0008 #include <linux/types.h>
0009 #include <sched.h>
0010 #include <signal.h>
0011 #include <stdbool.h>
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <string.h>
0015 #include <syscall.h>
0016 #include <sys/mount.h>
0017 #include <sys/prctl.h>
0018 #include <sys/wait.h>
0019 #include <unistd.h>
0020
0021 #include "pidfd.h"
0022 #include "../kselftest.h"
0023
0024 static int safe_int(const char *numstr, int *converted)
0025 {
0026 char *err = NULL;
0027 long sli;
0028
0029 errno = 0;
0030 sli = strtol(numstr, &err, 0);
0031 if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
0032 return -ERANGE;
0033
0034 if (errno != 0 && sli == 0)
0035 return -EINVAL;
0036
0037 if (err == numstr || *err != '\0')
0038 return -EINVAL;
0039
0040 if (sli > INT_MAX || sli < INT_MIN)
0041 return -ERANGE;
0042
0043 *converted = (int)sli;
0044 return 0;
0045 }
0046
0047 static int char_left_gc(const char *buffer, size_t len)
0048 {
0049 size_t i;
0050
0051 for (i = 0; i < len; i++) {
0052 if (buffer[i] == ' ' ||
0053 buffer[i] == '\t')
0054 continue;
0055
0056 return i;
0057 }
0058
0059 return 0;
0060 }
0061
0062 static int char_right_gc(const char *buffer, size_t len)
0063 {
0064 int i;
0065
0066 for (i = len - 1; i >= 0; i--) {
0067 if (buffer[i] == ' ' ||
0068 buffer[i] == '\t' ||
0069 buffer[i] == '\n' ||
0070 buffer[i] == '\0')
0071 continue;
0072
0073 return i + 1;
0074 }
0075
0076 return 0;
0077 }
0078
0079 static char *trim_whitespace_in_place(char *buffer)
0080 {
0081 buffer += char_left_gc(buffer, strlen(buffer));
0082 buffer[char_right_gc(buffer, strlen(buffer))] = '\0';
0083 return buffer;
0084 }
0085
0086 static pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen)
0087 {
0088 int ret;
0089 char path[512];
0090 FILE *f;
0091 size_t n = 0;
0092 pid_t result = -1;
0093 char *line = NULL;
0094
0095 snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd);
0096
0097 f = fopen(path, "re");
0098 if (!f)
0099 return -1;
0100
0101 while (getline(&line, &n, f) != -1) {
0102 char *numstr;
0103
0104 if (strncmp(line, key, keylen))
0105 continue;
0106
0107 numstr = trim_whitespace_in_place(line + 4);
0108 ret = safe_int(numstr, &result);
0109 if (ret < 0)
0110 goto out;
0111
0112 break;
0113 }
0114
0115 out:
0116 free(line);
0117 fclose(f);
0118 return result;
0119 }
0120
0121 int main(int argc, char **argv)
0122 {
0123 int pidfd = -1, ret = 1;
0124 pid_t pid;
0125
0126 ksft_set_plan(3);
0127
0128 pidfd = sys_pidfd_open(-1, 0);
0129 if (pidfd >= 0) {
0130 ksft_print_msg(
0131 "%s - succeeded to open pidfd for invalid pid -1\n",
0132 strerror(errno));
0133 goto on_error;
0134 }
0135 ksft_test_result_pass("do not allow invalid pid test: passed\n");
0136
0137 pidfd = sys_pidfd_open(getpid(), 1);
0138 if (pidfd >= 0) {
0139 ksft_print_msg(
0140 "%s - succeeded to open pidfd with invalid flag value specified\n",
0141 strerror(errno));
0142 goto on_error;
0143 }
0144 ksft_test_result_pass("do not allow invalid flag test: passed\n");
0145
0146 pidfd = sys_pidfd_open(getpid(), 0);
0147 if (pidfd < 0) {
0148 ksft_print_msg("%s - failed to open pidfd\n", strerror(errno));
0149 goto on_error;
0150 }
0151 ksft_test_result_pass("open a new pidfd test: passed\n");
0152
0153 pid = get_pid_from_fdinfo_file(pidfd, "Pid:", sizeof("Pid:") - 1);
0154 ksft_print_msg("pidfd %d refers to process with pid %d\n", pidfd, pid);
0155
0156 ret = 0;
0157
0158 on_error:
0159 if (pidfd >= 0)
0160 close(pidfd);
0161
0162 return !ret ? ksft_exit_pass() : ksft_exit_fail();
0163 }