pidfd_fdinfo_test.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <assert.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <linux/types.h>
  7. #include <sched.h>
  8. #include <signal.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <syscall.h>
  13. #include <sys/wait.h>
  14. #include <sys/mman.h>
  15. #include "pidfd.h"
  16. #include "../kselftest.h"
  17. struct error {
  18. int code;
  19. char msg[512];
  20. };
  21. static int error_set(struct error *err, int code, const char *fmt, ...)
  22. {
  23. va_list args;
  24. int r;
  25. if (code == PIDFD_PASS || !err || err->code != PIDFD_PASS)
  26. return code;
  27. err->code = code;
  28. va_start(args, fmt);
  29. r = vsnprintf(err->msg, sizeof(err->msg), fmt, args);
  30. assert((size_t)r < sizeof(err->msg));
  31. va_end(args);
  32. return code;
  33. }
  34. static void error_report(struct error *err, const char *test_name)
  35. {
  36. switch (err->code) {
  37. case PIDFD_ERROR:
  38. ksft_exit_fail_msg("%s test: Fatal: %s\n", test_name, err->msg);
  39. break;
  40. case PIDFD_FAIL:
  41. /* will be: not ok %d # error %s test: %s */
  42. ksft_test_result_error("%s test: %s\n", test_name, err->msg);
  43. break;
  44. case PIDFD_SKIP:
  45. /* will be: not ok %d # SKIP %s test: %s */
  46. ksft_test_result_skip("%s test: %s\n", test_name, err->msg);
  47. break;
  48. case PIDFD_XFAIL:
  49. ksft_test_result_pass("%s test: Expected failure: %s\n",
  50. test_name, err->msg);
  51. break;
  52. case PIDFD_PASS:
  53. ksft_test_result_pass("%s test: Passed\n", test_name);
  54. break;
  55. default:
  56. ksft_exit_fail_msg("%s test: Unknown code: %d %s\n",
  57. test_name, err->code, err->msg);
  58. break;
  59. }
  60. }
  61. static inline int error_check(struct error *err, const char *test_name)
  62. {
  63. /* In case of error we bail out and terminate the test program */
  64. if (err->code == PIDFD_ERROR)
  65. error_report(err, test_name);
  66. return err->code;
  67. }
  68. #define CHILD_STACK_SIZE 8192
  69. struct child {
  70. char *stack;
  71. pid_t pid;
  72. int fd;
  73. };
  74. static struct child clone_newns(int (*fn)(void *), void *args,
  75. struct error *err)
  76. {
  77. static int flags = CLONE_PIDFD | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD;
  78. struct child ret;
  79. if (!(flags & CLONE_NEWUSER) && geteuid() != 0)
  80. flags |= CLONE_NEWUSER;
  81. ret.stack = mmap(NULL, CHILD_STACK_SIZE, PROT_READ | PROT_WRITE,
  82. MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
  83. if (ret.stack == MAP_FAILED) {
  84. error_set(err, -1, "mmap of stack failed (errno %d)", errno);
  85. return ret;
  86. }
  87. #ifdef __ia64__
  88. ret.pid = __clone2(fn, ret.stack, CHILD_STACK_SIZE, flags, args, &ret.fd);
  89. #else
  90. ret.pid = clone(fn, ret.stack + CHILD_STACK_SIZE, flags, args, &ret.fd);
  91. #endif
  92. if (ret.pid < 0) {
  93. error_set(err, PIDFD_ERROR, "clone failed (ret %d, errno %d)",
  94. ret.fd, errno);
  95. return ret;
  96. }
  97. ksft_print_msg("New child: %d, fd: %d\n", ret.pid, ret.fd);
  98. return ret;
  99. }
  100. static inline void child_close(struct child *child)
  101. {
  102. close(child->fd);
  103. }
  104. static inline int child_join(struct child *child, struct error *err)
  105. {
  106. int r;
  107. r = wait_for_pid(child->pid);
  108. if (r < 0)
  109. error_set(err, PIDFD_ERROR, "waitpid failed (ret %d, errno %d)",
  110. r, errno);
  111. else if (r > 0)
  112. error_set(err, r, "child %d reported: %d", child->pid, r);
  113. if (munmap(child->stack, CHILD_STACK_SIZE)) {
  114. error_set(err, -1, "munmap of child stack failed (errno %d)", errno);
  115. r = -1;
  116. }
  117. ksft_print_msg("waitpid WEXITSTATUS=%d\n", r);
  118. return r;
  119. }
  120. static inline int child_join_close(struct child *child, struct error *err)
  121. {
  122. child_close(child);
  123. return child_join(child, err);
  124. }
  125. static inline void trim_newline(char *str)
  126. {
  127. char *pos = strrchr(str, '\n');
  128. if (pos)
  129. *pos = '\0';
  130. }
  131. static int verify_fdinfo(int pidfd, struct error *err, const char *prefix,
  132. size_t prefix_len, const char *expect, ...)
  133. {
  134. char buffer[512] = {0, };
  135. char path[512] = {0, };
  136. va_list args;
  137. FILE *f;
  138. char *line = NULL;
  139. size_t n = 0;
  140. int found = 0;
  141. int r;
  142. va_start(args, expect);
  143. r = vsnprintf(buffer, sizeof(buffer), expect, args);
  144. assert((size_t)r < sizeof(buffer));
  145. va_end(args);
  146. snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd);
  147. f = fopen(path, "re");
  148. if (!f)
  149. return error_set(err, PIDFD_ERROR, "fdinfo open failed for %d",
  150. pidfd);
  151. while (getline(&line, &n, f) != -1) {
  152. char *val;
  153. if (strncmp(line, prefix, prefix_len))
  154. continue;
  155. found = 1;
  156. val = line + prefix_len;
  157. r = strcmp(val, buffer);
  158. if (r != 0) {
  159. trim_newline(line);
  160. trim_newline(buffer);
  161. error_set(err, PIDFD_FAIL, "%s '%s' != '%s'",
  162. prefix, val, buffer);
  163. }
  164. break;
  165. }
  166. free(line);
  167. fclose(f);
  168. if (found == 0)
  169. return error_set(err, PIDFD_FAIL, "%s not found for fd %d",
  170. prefix, pidfd);
  171. return PIDFD_PASS;
  172. }
  173. static int child_fdinfo_nspid_test(void *args)
  174. {
  175. struct error err;
  176. int pidfd;
  177. int r;
  178. /* if we got no fd for the sibling, we are done */
  179. if (!args)
  180. return PIDFD_PASS;
  181. /* verify that we can not resolve the pidfd for a process
  182. * in a sibling pid namespace, i.e. a pid namespace it is
  183. * not in our or a descended namespace
  184. */
  185. r = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0);
  186. if (r < 0) {
  187. ksft_print_msg("Failed to remount / private\n");
  188. return PIDFD_ERROR;
  189. }
  190. (void)umount2("/proc", MNT_DETACH);
  191. r = mount("proc", "/proc", "proc", 0, NULL);
  192. if (r < 0) {
  193. ksft_print_msg("Failed to remount /proc\n");
  194. return PIDFD_ERROR;
  195. }
  196. pidfd = *(int *)args;
  197. r = verify_fdinfo(pidfd, &err, "NSpid:", 6, "\t0\n");
  198. if (r != PIDFD_PASS)
  199. ksft_print_msg("NSpid fdinfo check failed: %s\n", err.msg);
  200. return r;
  201. }
  202. static void test_pidfd_fdinfo_nspid(void)
  203. {
  204. struct child a, b;
  205. struct error err = {0, };
  206. const char *test_name = "pidfd check for NSpid in fdinfo";
  207. /* Create a new child in a new pid and mount namespace */
  208. a = clone_newns(child_fdinfo_nspid_test, NULL, &err);
  209. error_check(&err, test_name);
  210. /* Pass the pidfd representing the first child to the
  211. * second child, which will be in a sibling pid namespace,
  212. * which means that the fdinfo NSpid entry for the pidfd
  213. * should only contain '0'.
  214. */
  215. b = clone_newns(child_fdinfo_nspid_test, &a.fd, &err);
  216. error_check(&err, test_name);
  217. /* The children will have pid 1 in the new pid namespace,
  218. * so the line must be 'NSPid:\t<pid>\t1'.
  219. */
  220. verify_fdinfo(a.fd, &err, "NSpid:", 6, "\t%d\t%d\n", a.pid, 1);
  221. verify_fdinfo(b.fd, &err, "NSpid:", 6, "\t%d\t%d\n", b.pid, 1);
  222. /* wait for the process, check the exit status and set
  223. * 'err' accordingly, if it is not already set.
  224. */
  225. child_join_close(&a, &err);
  226. child_join_close(&b, &err);
  227. error_report(&err, test_name);
  228. }
  229. static void test_pidfd_dead_fdinfo(void)
  230. {
  231. struct child a;
  232. struct error err = {0, };
  233. const char *test_name = "pidfd check fdinfo for dead process";
  234. /* Create a new child in a new pid and mount namespace */
  235. a = clone_newns(child_fdinfo_nspid_test, NULL, &err);
  236. error_check(&err, test_name);
  237. child_join(&a, &err);
  238. verify_fdinfo(a.fd, &err, "Pid:", 4, "\t-1\n");
  239. verify_fdinfo(a.fd, &err, "NSpid:", 6, "\t-1\n");
  240. child_close(&a);
  241. error_report(&err, test_name);
  242. }
  243. int main(int argc, char **argv)
  244. {
  245. ksft_print_header();
  246. ksft_set_plan(2);
  247. test_pidfd_fdinfo_nspid();
  248. test_pidfd_dead_fdinfo();
  249. ksft_exit_pass();
  250. }