pidfd_open_test.c 4.6 KB

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