pidfd_setns_test.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <errno.h>
  4. #include <fcntl.h>
  5. #include <limits.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/prctl.h>
  14. #include <sys/wait.h>
  15. #include <unistd.h>
  16. #include <sys/socket.h>
  17. #include <sys/stat.h>
  18. #include "pidfd.h"
  19. #include "kselftest_harness.h"
  20. enum {
  21. PIDFD_NS_USER,
  22. PIDFD_NS_MNT,
  23. PIDFD_NS_PID,
  24. PIDFD_NS_UTS,
  25. PIDFD_NS_IPC,
  26. PIDFD_NS_NET,
  27. PIDFD_NS_CGROUP,
  28. PIDFD_NS_PIDCLD,
  29. PIDFD_NS_TIME,
  30. PIDFD_NS_TIMECLD,
  31. PIDFD_NS_MAX
  32. };
  33. const struct ns_info {
  34. const char *name;
  35. int flag;
  36. unsigned int pidfd_ioctl;
  37. } ns_info[] = {
  38. [PIDFD_NS_USER] = { "user", CLONE_NEWUSER, PIDFD_GET_USER_NAMESPACE, },
  39. [PIDFD_NS_MNT] = { "mnt", CLONE_NEWNS, PIDFD_GET_MNT_NAMESPACE, },
  40. [PIDFD_NS_PID] = { "pid", CLONE_NEWPID, PIDFD_GET_PID_NAMESPACE, },
  41. [PIDFD_NS_UTS] = { "uts", CLONE_NEWUTS, PIDFD_GET_UTS_NAMESPACE, },
  42. [PIDFD_NS_IPC] = { "ipc", CLONE_NEWIPC, PIDFD_GET_IPC_NAMESPACE, },
  43. [PIDFD_NS_NET] = { "net", CLONE_NEWNET, PIDFD_GET_NET_NAMESPACE, },
  44. [PIDFD_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, PIDFD_GET_CGROUP_NAMESPACE, },
  45. [PIDFD_NS_TIME] = { "time", CLONE_NEWTIME, PIDFD_GET_TIME_NAMESPACE, },
  46. [PIDFD_NS_PIDCLD] = { "pid_for_children", 0, PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE, },
  47. [PIDFD_NS_TIMECLD] = { "time_for_children", 0, PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE, },
  48. };
  49. FIXTURE(current_nsset)
  50. {
  51. pid_t pid;
  52. int pidfd;
  53. int nsfds[PIDFD_NS_MAX];
  54. int child_pidfd_derived_nsfds[PIDFD_NS_MAX];
  55. pid_t child_pid_exited;
  56. int child_pidfd_exited;
  57. pid_t child_pid1;
  58. int child_pidfd1;
  59. int child_nsfds1[PIDFD_NS_MAX];
  60. int child_pidfd_derived_nsfds1[PIDFD_NS_MAX];
  61. pid_t child_pid2;
  62. int child_pidfd2;
  63. int child_nsfds2[PIDFD_NS_MAX];
  64. int child_pidfd_derived_nsfds2[PIDFD_NS_MAX];
  65. };
  66. static bool switch_timens(void)
  67. {
  68. int fd, ret;
  69. if (unshare(CLONE_NEWTIME))
  70. return false;
  71. fd = open("/proc/self/ns/time_for_children", O_RDONLY | O_CLOEXEC);
  72. if (fd < 0)
  73. return false;
  74. ret = setns(fd, CLONE_NEWTIME);
  75. close(fd);
  76. return ret == 0;
  77. }
  78. FIXTURE_SETUP(current_nsset)
  79. {
  80. int i, proc_fd, ret;
  81. int ipc_sockets[2];
  82. char c;
  83. for (i = 0; i < PIDFD_NS_MAX; i++) {
  84. self->nsfds[i] = -EBADF;
  85. self->child_nsfds1[i] = -EBADF;
  86. self->child_nsfds2[i] = -EBADF;
  87. self->child_pidfd_derived_nsfds[i] = -EBADF;
  88. self->child_pidfd_derived_nsfds1[i] = -EBADF;
  89. self->child_pidfd_derived_nsfds2[i] = -EBADF;
  90. }
  91. proc_fd = open("/proc/self/ns", O_DIRECTORY | O_CLOEXEC);
  92. ASSERT_GE(proc_fd, 0) {
  93. TH_LOG("%m - Failed to open /proc/self/ns");
  94. }
  95. self->pid = getpid();
  96. self->pidfd = sys_pidfd_open(self->pid, 0);
  97. EXPECT_GT(self->pidfd, 0) {
  98. TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
  99. }
  100. for (i = 0; i < PIDFD_NS_MAX; i++) {
  101. const struct ns_info *info = &ns_info[i];
  102. self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
  103. if (self->nsfds[i] < 0) {
  104. EXPECT_EQ(errno, ENOENT) {
  105. TH_LOG("%m - Failed to open %s namespace for process %d",
  106. info->name, self->pid);
  107. }
  108. }
  109. self->child_pidfd_derived_nsfds[i] = ioctl(self->pidfd, info->pidfd_ioctl, 0);
  110. if (self->child_pidfd_derived_nsfds[i] < 0) {
  111. EXPECT_EQ(errno, EOPNOTSUPP) {
  112. TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
  113. info->name, self->pid);
  114. }
  115. }
  116. }
  117. /* Create task that exits right away. */
  118. self->child_pid_exited = create_child(&self->child_pidfd_exited, 0);
  119. EXPECT_GE(self->child_pid_exited, 0);
  120. if (self->child_pid_exited == 0) {
  121. if (self->nsfds[PIDFD_NS_USER] >= 0 && unshare(CLONE_NEWUSER) < 0)
  122. _exit(EXIT_FAILURE);
  123. if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0)
  124. _exit(EXIT_FAILURE);
  125. _exit(EXIT_SUCCESS);
  126. }
  127. ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED | WNOWAIT), 0);
  128. self->pidfd = sys_pidfd_open(self->pid, 0);
  129. EXPECT_GE(self->pidfd, 0) {
  130. TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
  131. }
  132. ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
  133. EXPECT_EQ(ret, 0);
  134. /* Create tasks that will be stopped. */
  135. if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
  136. self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER | CLONE_NEWPID);
  137. else if (self->nsfds[PIDFD_NS_PID] >= 0)
  138. self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWPID);
  139. else if (self->nsfds[PIDFD_NS_USER] >= 0)
  140. self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER);
  141. else
  142. self->child_pid1 = create_child(&self->child_pidfd1, 0);
  143. EXPECT_GE(self->child_pid1, 0);
  144. if (self->child_pid1 == 0) {
  145. close(ipc_sockets[0]);
  146. if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
  147. TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
  148. _exit(EXIT_FAILURE);
  149. }
  150. if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
  151. TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
  152. _exit(EXIT_FAILURE);
  153. }
  154. if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
  155. TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
  156. _exit(EXIT_FAILURE);
  157. }
  158. if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
  159. TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
  160. _exit(EXIT_FAILURE);
  161. }
  162. if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
  163. TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
  164. _exit(EXIT_FAILURE);
  165. }
  166. if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
  167. TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
  168. _exit(EXIT_FAILURE);
  169. }
  170. if (write_nointr(ipc_sockets[1], "1", 1) < 0)
  171. _exit(EXIT_FAILURE);
  172. close(ipc_sockets[1]);
  173. pause();
  174. _exit(EXIT_SUCCESS);
  175. }
  176. close(ipc_sockets[1]);
  177. ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
  178. close(ipc_sockets[0]);
  179. ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
  180. EXPECT_EQ(ret, 0);
  181. if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
  182. self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER | CLONE_NEWPID);
  183. else if (self->nsfds[PIDFD_NS_PID] >= 0)
  184. self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWPID);
  185. else if (self->nsfds[PIDFD_NS_USER] >= 0)
  186. self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER);
  187. else
  188. self->child_pid2 = create_child(&self->child_pidfd2, 0);
  189. EXPECT_GE(self->child_pid2, 0);
  190. if (self->child_pid2 == 0) {
  191. close(ipc_sockets[0]);
  192. if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
  193. TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
  194. _exit(EXIT_FAILURE);
  195. }
  196. if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
  197. TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
  198. _exit(EXIT_FAILURE);
  199. }
  200. if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
  201. TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
  202. _exit(EXIT_FAILURE);
  203. }
  204. if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
  205. TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
  206. _exit(EXIT_FAILURE);
  207. }
  208. if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
  209. TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
  210. _exit(EXIT_FAILURE);
  211. }
  212. if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
  213. TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
  214. _exit(EXIT_FAILURE);
  215. }
  216. if (write_nointr(ipc_sockets[1], "1", 1) < 0)
  217. _exit(EXIT_FAILURE);
  218. close(ipc_sockets[1]);
  219. pause();
  220. _exit(EXIT_SUCCESS);
  221. }
  222. close(ipc_sockets[1]);
  223. ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
  224. close(ipc_sockets[0]);
  225. for (i = 0; i < PIDFD_NS_MAX; i++) {
  226. char p[100];
  227. const struct ns_info *info = &ns_info[i];
  228. self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
  229. if (self->nsfds[i] < 0) {
  230. EXPECT_EQ(errno, ENOENT) {
  231. TH_LOG("%m - Failed to open %s namespace for process %d",
  232. info->name, self->pid);
  233. }
  234. }
  235. ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
  236. self->child_pid1, info->name);
  237. EXPECT_GT(ret, 0);
  238. EXPECT_LT(ret, sizeof(p));
  239. self->child_nsfds1[i] = open(p, O_RDONLY | O_CLOEXEC);
  240. if (self->child_nsfds1[i] < 0) {
  241. EXPECT_EQ(errno, ENOENT) {
  242. TH_LOG("%m - Failed to open %s namespace for process %d",
  243. info->name, self->child_pid1);
  244. }
  245. }
  246. ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
  247. self->child_pid2, info->name);
  248. EXPECT_GT(ret, 0);
  249. EXPECT_LT(ret, sizeof(p));
  250. self->child_nsfds2[i] = open(p, O_RDONLY | O_CLOEXEC);
  251. if (self->child_nsfds2[i] < 0) {
  252. EXPECT_EQ(errno, ENOENT) {
  253. TH_LOG("%m - Failed to open %s namespace for process %d",
  254. info->name, self->child_pid1);
  255. }
  256. }
  257. self->child_pidfd_derived_nsfds1[i] = ioctl(self->child_pidfd1, info->pidfd_ioctl, 0);
  258. if (self->child_pidfd_derived_nsfds1[i] < 0) {
  259. EXPECT_EQ(errno, EOPNOTSUPP) {
  260. TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
  261. info->name, self->child_pid1);
  262. }
  263. }
  264. self->child_pidfd_derived_nsfds2[i] = ioctl(self->child_pidfd2, info->pidfd_ioctl, 0);
  265. if (self->child_pidfd_derived_nsfds2[i] < 0) {
  266. EXPECT_EQ(errno, EOPNOTSUPP) {
  267. TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
  268. info->name, self->child_pid2);
  269. }
  270. }
  271. }
  272. close(proc_fd);
  273. }
  274. FIXTURE_TEARDOWN(current_nsset)
  275. {
  276. int i;
  277. ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd1,
  278. SIGKILL, NULL, 0), 0);
  279. ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd2,
  280. SIGKILL, NULL, 0), 0);
  281. for (i = 0; i < PIDFD_NS_MAX; i++) {
  282. if (self->nsfds[i] >= 0)
  283. close(self->nsfds[i]);
  284. if (self->child_nsfds1[i] >= 0)
  285. close(self->child_nsfds1[i]);
  286. if (self->child_nsfds2[i] >= 0)
  287. close(self->child_nsfds2[i]);
  288. if (self->child_pidfd_derived_nsfds[i] >= 0)
  289. close(self->child_pidfd_derived_nsfds[i]);
  290. if (self->child_pidfd_derived_nsfds1[i] >= 0)
  291. close(self->child_pidfd_derived_nsfds1[i]);
  292. if (self->child_pidfd_derived_nsfds2[i] >= 0)
  293. close(self->child_pidfd_derived_nsfds2[i]);
  294. }
  295. if (self->child_pidfd1 >= 0)
  296. EXPECT_EQ(0, close(self->child_pidfd1));
  297. if (self->child_pidfd2 >= 0)
  298. EXPECT_EQ(0, close(self->child_pidfd2));
  299. ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED), 0);
  300. ASSERT_EQ(sys_waitid(P_PID, self->child_pid1, NULL, WEXITED), 0);
  301. ASSERT_EQ(sys_waitid(P_PID, self->child_pid2, NULL, WEXITED), 0);
  302. }
  303. static int preserve_ns(const int pid, const char *ns)
  304. {
  305. int ret;
  306. char path[50];
  307. ret = snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns);
  308. if (ret < 0 || (size_t)ret >= sizeof(path))
  309. return -EIO;
  310. return open(path, O_RDONLY | O_CLOEXEC);
  311. }
  312. static int in_same_namespace(int ns_fd1, pid_t pid2, const char *ns)
  313. {
  314. int ns_fd2 = -EBADF;
  315. int ret = -1;
  316. struct stat ns_st1, ns_st2;
  317. ret = fstat(ns_fd1, &ns_st1);
  318. if (ret < 0)
  319. return -1;
  320. ns_fd2 = preserve_ns(pid2, ns);
  321. if (ns_fd2 < 0)
  322. return -1;
  323. ret = fstat(ns_fd2, &ns_st2);
  324. close(ns_fd2);
  325. if (ret < 0)
  326. return -1;
  327. /* processes are in the same namespace */
  328. if ((ns_st1.st_dev == ns_st2.st_dev) &&
  329. (ns_st1.st_ino == ns_st2.st_ino))
  330. return 1;
  331. /* processes are in different namespaces */
  332. return 0;
  333. }
  334. /* Test that we can't pass garbage to the kernel. */
  335. TEST_F(current_nsset, invalid_flags)
  336. {
  337. ASSERT_NE(setns(self->pidfd, 0), 0);
  338. EXPECT_EQ(errno, EINVAL);
  339. ASSERT_NE(setns(self->pidfd, -1), 0);
  340. EXPECT_EQ(errno, EINVAL);
  341. ASSERT_NE(setns(self->pidfd, CLONE_VM), 0);
  342. EXPECT_EQ(errno, EINVAL);
  343. ASSERT_NE(setns(self->pidfd, CLONE_NEWUSER | CLONE_VM), 0);
  344. EXPECT_EQ(errno, EINVAL);
  345. }
  346. /* Test that we can't attach to a task that has already exited. */
  347. TEST_F(current_nsset, pidfd_exited_child)
  348. {
  349. int i;
  350. pid_t pid;
  351. ASSERT_NE(setns(self->child_pidfd_exited, CLONE_NEWUSER | CLONE_NEWNET),
  352. 0);
  353. EXPECT_EQ(errno, ESRCH);
  354. pid = getpid();
  355. for (i = 0; i < PIDFD_NS_MAX; i++) {
  356. const struct ns_info *info = &ns_info[i];
  357. /* Verify that we haven't changed any namespaces. */
  358. if (self->nsfds[i] >= 0)
  359. ASSERT_EQ(in_same_namespace(self->nsfds[i], pid, info->name), 1);
  360. }
  361. }
  362. TEST_F(current_nsset, pidfd_incremental_setns)
  363. {
  364. int i;
  365. pid_t pid;
  366. pid = getpid();
  367. for (i = 0; i < PIDFD_NS_MAX; i++) {
  368. const struct ns_info *info = &ns_info[i];
  369. int nsfd;
  370. if (self->child_nsfds1[i] < 0)
  371. continue;
  372. if (info->flag) {
  373. ASSERT_EQ(setns(self->child_pidfd1, info->flag), 0) {
  374. TH_LOG("%m - Failed to setns to %s namespace of %d via pidfd %d",
  375. info->name, self->child_pid1,
  376. self->child_pidfd1);
  377. }
  378. }
  379. /* Verify that we have changed to the correct namespaces. */
  380. if (info->flag == CLONE_NEWPID)
  381. nsfd = self->nsfds[i];
  382. else
  383. nsfd = self->child_nsfds1[i];
  384. ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
  385. TH_LOG("setns failed to place us correctly into %s namespace of %d via pidfd %d",
  386. info->name, self->child_pid1,
  387. self->child_pidfd1);
  388. }
  389. TH_LOG("Managed to correctly setns to %s namespace of %d via pidfd %d",
  390. info->name, self->child_pid1, self->child_pidfd1);
  391. }
  392. }
  393. TEST_F(current_nsset, nsfd_incremental_setns)
  394. {
  395. int i;
  396. pid_t pid;
  397. pid = getpid();
  398. for (i = 0; i < PIDFD_NS_MAX; i++) {
  399. const struct ns_info *info = &ns_info[i];
  400. int nsfd;
  401. if (self->child_nsfds1[i] < 0)
  402. continue;
  403. if (info->flag) {
  404. ASSERT_EQ(setns(self->child_nsfds1[i], info->flag), 0) {
  405. TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
  406. info->name, self->child_pid1,
  407. self->child_nsfds1[i]);
  408. }
  409. }
  410. /* Verify that we have changed to the correct namespaces. */
  411. if (info->flag == CLONE_NEWPID)
  412. nsfd = self->nsfds[i];
  413. else
  414. nsfd = self->child_nsfds1[i];
  415. ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
  416. TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
  417. info->name, self->child_pid1,
  418. self->child_nsfds1[i]);
  419. }
  420. TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
  421. info->name, self->child_pid1, self->child_nsfds1[i]);
  422. }
  423. }
  424. TEST_F(current_nsset, pidfd_derived_nsfd_incremental_setns)
  425. {
  426. int i;
  427. pid_t pid;
  428. pid = getpid();
  429. for (i = 0; i < PIDFD_NS_MAX; i++) {
  430. const struct ns_info *info = &ns_info[i];
  431. int nsfd;
  432. if (self->child_pidfd_derived_nsfds1[i] < 0)
  433. continue;
  434. if (info->flag) {
  435. ASSERT_EQ(setns(self->child_pidfd_derived_nsfds1[i], info->flag), 0) {
  436. TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
  437. info->name, self->child_pid1,
  438. self->child_pidfd_derived_nsfds1[i]);
  439. }
  440. }
  441. /* Verify that we have changed to the correct namespaces. */
  442. if (info->flag == CLONE_NEWPID)
  443. nsfd = self->child_pidfd_derived_nsfds[i];
  444. else
  445. nsfd = self->child_pidfd_derived_nsfds1[i];
  446. ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
  447. TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
  448. info->name, self->child_pid1,
  449. self->child_pidfd_derived_nsfds1[i]);
  450. }
  451. TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
  452. info->name, self->child_pid1, self->child_pidfd_derived_nsfds1[i]);
  453. }
  454. }
  455. TEST_F(current_nsset, pidfd_one_shot_setns)
  456. {
  457. unsigned flags = 0;
  458. int i;
  459. pid_t pid;
  460. for (i = 0; i < PIDFD_NS_MAX; i++) {
  461. const struct ns_info *info = &ns_info[i];
  462. if (self->child_nsfds1[i] < 0)
  463. continue;
  464. flags |= info->flag;
  465. TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
  466. info->name, self->child_pid1);
  467. }
  468. ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
  469. TH_LOG("%m - Failed to setns to namespaces of %d",
  470. self->child_pid1);
  471. }
  472. pid = getpid();
  473. for (i = 0; i < PIDFD_NS_MAX; i++) {
  474. const struct ns_info *info = &ns_info[i];
  475. int nsfd;
  476. if (self->child_nsfds1[i] < 0)
  477. continue;
  478. /* Verify that we have changed to the correct namespaces. */
  479. if (info->flag == CLONE_NEWPID)
  480. nsfd = self->nsfds[i];
  481. else
  482. nsfd = self->child_nsfds1[i];
  483. ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
  484. TH_LOG("setns failed to place us correctly into %s namespace of %d",
  485. info->name, self->child_pid1);
  486. }
  487. TH_LOG("Managed to correctly setns to %s namespace of %d",
  488. info->name, self->child_pid1);
  489. }
  490. }
  491. TEST_F(current_nsset, no_foul_play)
  492. {
  493. unsigned flags = 0;
  494. int i;
  495. for (i = 0; i < PIDFD_NS_MAX; i++) {
  496. const struct ns_info *info = &ns_info[i];
  497. if (self->child_nsfds1[i] < 0)
  498. continue;
  499. flags |= info->flag;
  500. if (info->flag) /* No use logging pid_for_children. */
  501. TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
  502. info->name, self->child_pid1);
  503. }
  504. ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
  505. TH_LOG("%m - Failed to setns to namespaces of %d vid pidfd %d",
  506. self->child_pid1, self->child_pidfd1);
  507. }
  508. /*
  509. * Can't setns to a user namespace outside of our hierarchy since we
  510. * don't have caps in there and didn't create it. That means that under
  511. * no circumstances should we be able to setns to any of the other
  512. * ones since they aren't owned by our user namespace.
  513. */
  514. for (i = 0; i < PIDFD_NS_MAX; i++) {
  515. const struct ns_info *info = &ns_info[i];
  516. if (self->child_nsfds2[i] < 0 || !info->flag)
  517. continue;
  518. ASSERT_NE(setns(self->child_pidfd2, info->flag), 0) {
  519. TH_LOG("Managed to setns to %s namespace of %d via pidfd %d",
  520. info->name, self->child_pid2,
  521. self->child_pidfd2);
  522. }
  523. TH_LOG("%m - Correctly failed to setns to %s namespace of %d via pidfd %d",
  524. info->name, self->child_pid2,
  525. self->child_pidfd2);
  526. ASSERT_NE(setns(self->child_nsfds2[i], info->flag), 0) {
  527. TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
  528. info->name, self->child_pid2,
  529. self->child_nsfds2[i]);
  530. }
  531. TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
  532. info->name, self->child_pid2,
  533. self->child_nsfds2[i]);
  534. }
  535. /*
  536. * Can't setns to a user namespace outside of our hierarchy since we
  537. * don't have caps in there and didn't create it. That means that under
  538. * no circumstances should we be able to setns to any of the other
  539. * ones since they aren't owned by our user namespace.
  540. */
  541. for (i = 0; i < PIDFD_NS_MAX; i++) {
  542. const struct ns_info *info = &ns_info[i];
  543. if (self->child_pidfd_derived_nsfds2[i] < 0 || !info->flag)
  544. continue;
  545. ASSERT_NE(setns(self->child_pidfd_derived_nsfds2[i], info->flag), 0) {
  546. TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
  547. info->name, self->child_pid2,
  548. self->child_pidfd_derived_nsfds2[i]);
  549. }
  550. TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
  551. info->name, self->child_pid2,
  552. self->child_pidfd_derived_nsfds2[i]);
  553. }
  554. }
  555. TEST(setns_einval)
  556. {
  557. int fd;
  558. fd = sys_memfd_create("rostock", 0);
  559. EXPECT_GT(fd, 0);
  560. ASSERT_NE(setns(fd, 0), 0);
  561. EXPECT_EQ(errno, EINVAL);
  562. close(fd);
  563. }
  564. TEST_HARNESS_MAIN