nsid_test.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <assert.h>
  3. #include <fcntl.h>
  4. #include <inttypes.h>
  5. #include <libgen.h>
  6. #include <limits.h>
  7. #include <pthread.h>
  8. #include <signal.h>
  9. #include <string.h>
  10. #include <sys/mount.h>
  11. #include <poll.h>
  12. #include <sys/epoll.h>
  13. #include <sys/resource.h>
  14. #include <sys/stat.h>
  15. #include <sys/socket.h>
  16. #include <sys/un.h>
  17. #include <sys/wait.h>
  18. #include <unistd.h>
  19. #include <linux/fs.h>
  20. #include <linux/limits.h>
  21. #include <linux/nsfs.h>
  22. #include "kselftest_harness.h"
  23. /* Fixture for tests that create child processes */
  24. FIXTURE(nsid) {
  25. pid_t child_pid;
  26. };
  27. FIXTURE_SETUP(nsid) {
  28. self->child_pid = 0;
  29. }
  30. FIXTURE_TEARDOWN(nsid) {
  31. /* Clean up any child process that may still be running */
  32. if (self->child_pid > 0) {
  33. kill(self->child_pid, SIGKILL);
  34. waitpid(self->child_pid, NULL, 0);
  35. }
  36. }
  37. TEST(nsid_mntns_basic)
  38. {
  39. __u64 mnt_ns_id = 0;
  40. int fd_mntns;
  41. int ret;
  42. /* Open the current mount namespace */
  43. fd_mntns = open("/proc/self/ns/mnt", O_RDONLY);
  44. ASSERT_GE(fd_mntns, 0);
  45. /* Get the mount namespace ID */
  46. ret = ioctl(fd_mntns, NS_GET_MNTNS_ID, &mnt_ns_id);
  47. ASSERT_EQ(ret, 0);
  48. ASSERT_NE(mnt_ns_id, 0);
  49. /* Verify we can get the same ID again */
  50. __u64 mnt_ns_id2 = 0;
  51. ret = ioctl(fd_mntns, NS_GET_ID, &mnt_ns_id2);
  52. ASSERT_EQ(ret, 0);
  53. ASSERT_EQ(mnt_ns_id, mnt_ns_id2);
  54. close(fd_mntns);
  55. }
  56. TEST_F(nsid, mntns_separate)
  57. {
  58. __u64 parent_mnt_ns_id = 0;
  59. __u64 child_mnt_ns_id = 0;
  60. int fd_parent_mntns, fd_child_mntns;
  61. int ret;
  62. pid_t pid;
  63. int pipefd[2];
  64. /* Get parent's mount namespace ID */
  65. fd_parent_mntns = open("/proc/self/ns/mnt", O_RDONLY);
  66. ASSERT_GE(fd_parent_mntns, 0);
  67. ret = ioctl(fd_parent_mntns, NS_GET_ID, &parent_mnt_ns_id);
  68. ASSERT_EQ(ret, 0);
  69. ASSERT_NE(parent_mnt_ns_id, 0);
  70. /* Create a pipe for synchronization */
  71. ASSERT_EQ(pipe(pipefd), 0);
  72. pid = fork();
  73. ASSERT_GE(pid, 0);
  74. if (pid == 0) {
  75. /* Child process */
  76. close(pipefd[0]);
  77. /* Create new mount namespace */
  78. ret = unshare(CLONE_NEWNS);
  79. if (ret != 0) {
  80. /* Skip test if we don't have permission */
  81. if (errno == EPERM || errno == EACCES) {
  82. write(pipefd[1], "S", 1); /* Signal skip */
  83. _exit(0);
  84. }
  85. _exit(1);
  86. }
  87. /* Signal success */
  88. write(pipefd[1], "Y", 1);
  89. close(pipefd[1]);
  90. /* Keep namespace alive */
  91. pause();
  92. _exit(0);
  93. }
  94. /* Track child for cleanup */
  95. self->child_pid = pid;
  96. /* Parent process */
  97. close(pipefd[1]);
  98. char buf;
  99. ASSERT_EQ(read(pipefd[0], &buf, 1), 1);
  100. close(pipefd[0]);
  101. if (buf == 'S') {
  102. /* Child couldn't create namespace, skip test */
  103. close(fd_parent_mntns);
  104. SKIP(return, "No permission to create mount namespace");
  105. }
  106. ASSERT_EQ(buf, 'Y');
  107. /* Open child's mount namespace */
  108. char path[256];
  109. snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
  110. fd_child_mntns = open(path, O_RDONLY);
  111. ASSERT_GE(fd_child_mntns, 0);
  112. /* Get child's mount namespace ID */
  113. ret = ioctl(fd_child_mntns, NS_GET_ID, &child_mnt_ns_id);
  114. ASSERT_EQ(ret, 0);
  115. ASSERT_NE(child_mnt_ns_id, 0);
  116. /* Parent and child should have different mount namespace IDs */
  117. ASSERT_NE(parent_mnt_ns_id, child_mnt_ns_id);
  118. close(fd_parent_mntns);
  119. close(fd_child_mntns);
  120. }
  121. TEST(nsid_cgroupns_basic)
  122. {
  123. __u64 cgroup_ns_id = 0;
  124. int fd_cgroupns;
  125. int ret;
  126. /* Open the current cgroup namespace */
  127. fd_cgroupns = open("/proc/self/ns/cgroup", O_RDONLY);
  128. ASSERT_GE(fd_cgroupns, 0);
  129. /* Get the cgroup namespace ID */
  130. ret = ioctl(fd_cgroupns, NS_GET_ID, &cgroup_ns_id);
  131. ASSERT_EQ(ret, 0);
  132. ASSERT_NE(cgroup_ns_id, 0);
  133. /* Verify we can get the same ID again */
  134. __u64 cgroup_ns_id2 = 0;
  135. ret = ioctl(fd_cgroupns, NS_GET_ID, &cgroup_ns_id2);
  136. ASSERT_EQ(ret, 0);
  137. ASSERT_EQ(cgroup_ns_id, cgroup_ns_id2);
  138. close(fd_cgroupns);
  139. }
  140. TEST_F(nsid, cgroupns_separate)
  141. {
  142. __u64 parent_cgroup_ns_id = 0;
  143. __u64 child_cgroup_ns_id = 0;
  144. int fd_parent_cgroupns, fd_child_cgroupns;
  145. int ret;
  146. pid_t pid;
  147. int pipefd[2];
  148. /* Get parent's cgroup namespace ID */
  149. fd_parent_cgroupns = open("/proc/self/ns/cgroup", O_RDONLY);
  150. ASSERT_GE(fd_parent_cgroupns, 0);
  151. ret = ioctl(fd_parent_cgroupns, NS_GET_ID, &parent_cgroup_ns_id);
  152. ASSERT_EQ(ret, 0);
  153. ASSERT_NE(parent_cgroup_ns_id, 0);
  154. /* Create a pipe for synchronization */
  155. ASSERT_EQ(pipe(pipefd), 0);
  156. pid = fork();
  157. ASSERT_GE(pid, 0);
  158. if (pid == 0) {
  159. /* Child process */
  160. close(pipefd[0]);
  161. /* Create new cgroup namespace */
  162. ret = unshare(CLONE_NEWCGROUP);
  163. if (ret != 0) {
  164. /* Skip test if we don't have permission */
  165. if (errno == EPERM || errno == EACCES) {
  166. write(pipefd[1], "S", 1); /* Signal skip */
  167. _exit(0);
  168. }
  169. _exit(1);
  170. }
  171. /* Signal success */
  172. write(pipefd[1], "Y", 1);
  173. close(pipefd[1]);
  174. /* Keep namespace alive */
  175. pause();
  176. _exit(0);
  177. }
  178. /* Track child for cleanup */
  179. self->child_pid = pid;
  180. /* Parent process */
  181. close(pipefd[1]);
  182. char buf;
  183. ASSERT_EQ(read(pipefd[0], &buf, 1), 1);
  184. close(pipefd[0]);
  185. if (buf == 'S') {
  186. /* Child couldn't create namespace, skip test */
  187. close(fd_parent_cgroupns);
  188. SKIP(return, "No permission to create cgroup namespace");
  189. }
  190. ASSERT_EQ(buf, 'Y');
  191. /* Open child's cgroup namespace */
  192. char path[256];
  193. snprintf(path, sizeof(path), "/proc/%d/ns/cgroup", pid);
  194. fd_child_cgroupns = open(path, O_RDONLY);
  195. ASSERT_GE(fd_child_cgroupns, 0);
  196. /* Get child's cgroup namespace ID */
  197. ret = ioctl(fd_child_cgroupns, NS_GET_ID, &child_cgroup_ns_id);
  198. ASSERT_EQ(ret, 0);
  199. ASSERT_NE(child_cgroup_ns_id, 0);
  200. /* Parent and child should have different cgroup namespace IDs */
  201. ASSERT_NE(parent_cgroup_ns_id, child_cgroup_ns_id);
  202. close(fd_parent_cgroupns);
  203. close(fd_child_cgroupns);
  204. }
  205. TEST(nsid_ipcns_basic)
  206. {
  207. __u64 ipc_ns_id = 0;
  208. int fd_ipcns;
  209. int ret;
  210. /* Open the current IPC namespace */
  211. fd_ipcns = open("/proc/self/ns/ipc", O_RDONLY);
  212. ASSERT_GE(fd_ipcns, 0);
  213. /* Get the IPC namespace ID */
  214. ret = ioctl(fd_ipcns, NS_GET_ID, &ipc_ns_id);
  215. ASSERT_EQ(ret, 0);
  216. ASSERT_NE(ipc_ns_id, 0);
  217. /* Verify we can get the same ID again */
  218. __u64 ipc_ns_id2 = 0;
  219. ret = ioctl(fd_ipcns, NS_GET_ID, &ipc_ns_id2);
  220. ASSERT_EQ(ret, 0);
  221. ASSERT_EQ(ipc_ns_id, ipc_ns_id2);
  222. close(fd_ipcns);
  223. }
  224. TEST_F(nsid, ipcns_separate)
  225. {
  226. __u64 parent_ipc_ns_id = 0;
  227. __u64 child_ipc_ns_id = 0;
  228. int fd_parent_ipcns, fd_child_ipcns;
  229. int ret;
  230. pid_t pid;
  231. int pipefd[2];
  232. /* Get parent's IPC namespace ID */
  233. fd_parent_ipcns = open("/proc/self/ns/ipc", O_RDONLY);
  234. ASSERT_GE(fd_parent_ipcns, 0);
  235. ret = ioctl(fd_parent_ipcns, NS_GET_ID, &parent_ipc_ns_id);
  236. ASSERT_EQ(ret, 0);
  237. ASSERT_NE(parent_ipc_ns_id, 0);
  238. /* Create a pipe for synchronization */
  239. ASSERT_EQ(pipe(pipefd), 0);
  240. pid = fork();
  241. ASSERT_GE(pid, 0);
  242. if (pid == 0) {
  243. /* Child process */
  244. close(pipefd[0]);
  245. /* Create new IPC namespace */
  246. ret = unshare(CLONE_NEWIPC);
  247. if (ret != 0) {
  248. /* Skip test if we don't have permission */
  249. if (errno == EPERM || errno == EACCES) {
  250. write(pipefd[1], "S", 1); /* Signal skip */
  251. _exit(0);
  252. }
  253. _exit(1);
  254. }
  255. /* Signal success */
  256. write(pipefd[1], "Y", 1);
  257. close(pipefd[1]);
  258. /* Keep namespace alive */
  259. pause();
  260. _exit(0);
  261. }
  262. /* Track child for cleanup */
  263. self->child_pid = pid;
  264. /* Parent process */
  265. close(pipefd[1]);
  266. char buf;
  267. ASSERT_EQ(read(pipefd[0], &buf, 1), 1);
  268. close(pipefd[0]);
  269. if (buf == 'S') {
  270. /* Child couldn't create namespace, skip test */
  271. close(fd_parent_ipcns);
  272. SKIP(return, "No permission to create IPC namespace");
  273. }
  274. ASSERT_EQ(buf, 'Y');
  275. /* Open child's IPC namespace */
  276. char path[256];
  277. snprintf(path, sizeof(path), "/proc/%d/ns/ipc", pid);
  278. fd_child_ipcns = open(path, O_RDONLY);
  279. ASSERT_GE(fd_child_ipcns, 0);
  280. /* Get child's IPC namespace ID */
  281. ret = ioctl(fd_child_ipcns, NS_GET_ID, &child_ipc_ns_id);
  282. ASSERT_EQ(ret, 0);
  283. ASSERT_NE(child_ipc_ns_id, 0);
  284. /* Parent and child should have different IPC namespace IDs */
  285. ASSERT_NE(parent_ipc_ns_id, child_ipc_ns_id);
  286. close(fd_parent_ipcns);
  287. close(fd_child_ipcns);
  288. }
  289. TEST(nsid_utsns_basic)
  290. {
  291. __u64 uts_ns_id = 0;
  292. int fd_utsns;
  293. int ret;
  294. /* Open the current UTS namespace */
  295. fd_utsns = open("/proc/self/ns/uts", O_RDONLY);
  296. ASSERT_GE(fd_utsns, 0);
  297. /* Get the UTS namespace ID */
  298. ret = ioctl(fd_utsns, NS_GET_ID, &uts_ns_id);
  299. ASSERT_EQ(ret, 0);
  300. ASSERT_NE(uts_ns_id, 0);
  301. /* Verify we can get the same ID again */
  302. __u64 uts_ns_id2 = 0;
  303. ret = ioctl(fd_utsns, NS_GET_ID, &uts_ns_id2);
  304. ASSERT_EQ(ret, 0);
  305. ASSERT_EQ(uts_ns_id, uts_ns_id2);
  306. close(fd_utsns);
  307. }
  308. TEST_F(nsid, utsns_separate)
  309. {
  310. __u64 parent_uts_ns_id = 0;
  311. __u64 child_uts_ns_id = 0;
  312. int fd_parent_utsns, fd_child_utsns;
  313. int ret;
  314. pid_t pid;
  315. int pipefd[2];
  316. /* Get parent's UTS namespace ID */
  317. fd_parent_utsns = open("/proc/self/ns/uts", O_RDONLY);
  318. ASSERT_GE(fd_parent_utsns, 0);
  319. ret = ioctl(fd_parent_utsns, NS_GET_ID, &parent_uts_ns_id);
  320. ASSERT_EQ(ret, 0);
  321. ASSERT_NE(parent_uts_ns_id, 0);
  322. /* Create a pipe for synchronization */
  323. ASSERT_EQ(pipe(pipefd), 0);
  324. pid = fork();
  325. ASSERT_GE(pid, 0);
  326. if (pid == 0) {
  327. /* Child process */
  328. close(pipefd[0]);
  329. /* Create new UTS namespace */
  330. ret = unshare(CLONE_NEWUTS);
  331. if (ret != 0) {
  332. /* Skip test if we don't have permission */
  333. if (errno == EPERM || errno == EACCES) {
  334. write(pipefd[1], "S", 1); /* Signal skip */
  335. _exit(0);
  336. }
  337. _exit(1);
  338. }
  339. /* Signal success */
  340. write(pipefd[1], "Y", 1);
  341. close(pipefd[1]);
  342. /* Keep namespace alive */
  343. pause();
  344. _exit(0);
  345. }
  346. /* Track child for cleanup */
  347. self->child_pid = pid;
  348. /* Parent process */
  349. close(pipefd[1]);
  350. char buf;
  351. ASSERT_EQ(read(pipefd[0], &buf, 1), 1);
  352. close(pipefd[0]);
  353. if (buf == 'S') {
  354. /* Child couldn't create namespace, skip test */
  355. close(fd_parent_utsns);
  356. SKIP(return, "No permission to create UTS namespace");
  357. }
  358. ASSERT_EQ(buf, 'Y');
  359. /* Open child's UTS namespace */
  360. char path[256];
  361. snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid);
  362. fd_child_utsns = open(path, O_RDONLY);
  363. ASSERT_GE(fd_child_utsns, 0);
  364. /* Get child's UTS namespace ID */
  365. ret = ioctl(fd_child_utsns, NS_GET_ID, &child_uts_ns_id);
  366. ASSERT_EQ(ret, 0);
  367. ASSERT_NE(child_uts_ns_id, 0);
  368. /* Parent and child should have different UTS namespace IDs */
  369. ASSERT_NE(parent_uts_ns_id, child_uts_ns_id);
  370. close(fd_parent_utsns);
  371. close(fd_child_utsns);
  372. }
  373. TEST(nsid_userns_basic)
  374. {
  375. __u64 user_ns_id = 0;
  376. int fd_userns;
  377. int ret;
  378. /* Open the current user namespace */
  379. fd_userns = open("/proc/self/ns/user", O_RDONLY);
  380. ASSERT_GE(fd_userns, 0);
  381. /* Get the user namespace ID */
  382. ret = ioctl(fd_userns, NS_GET_ID, &user_ns_id);
  383. ASSERT_EQ(ret, 0);
  384. ASSERT_NE(user_ns_id, 0);
  385. /* Verify we can get the same ID again */
  386. __u64 user_ns_id2 = 0;
  387. ret = ioctl(fd_userns, NS_GET_ID, &user_ns_id2);
  388. ASSERT_EQ(ret, 0);
  389. ASSERT_EQ(user_ns_id, user_ns_id2);
  390. close(fd_userns);
  391. }
  392. TEST_F(nsid, userns_separate)
  393. {
  394. __u64 parent_user_ns_id = 0;
  395. __u64 child_user_ns_id = 0;
  396. int fd_parent_userns, fd_child_userns;
  397. int ret;
  398. pid_t pid;
  399. int pipefd[2];
  400. /* Get parent's user namespace ID */
  401. fd_parent_userns = open("/proc/self/ns/user", O_RDONLY);
  402. ASSERT_GE(fd_parent_userns, 0);
  403. ret = ioctl(fd_parent_userns, NS_GET_ID, &parent_user_ns_id);
  404. ASSERT_EQ(ret, 0);
  405. ASSERT_NE(parent_user_ns_id, 0);
  406. /* Create a pipe for synchronization */
  407. ASSERT_EQ(pipe(pipefd), 0);
  408. pid = fork();
  409. ASSERT_GE(pid, 0);
  410. if (pid == 0) {
  411. /* Child process */
  412. close(pipefd[0]);
  413. /* Create new user namespace */
  414. ret = unshare(CLONE_NEWUSER);
  415. if (ret != 0) {
  416. /* Skip test if we don't have permission */
  417. if (errno == EPERM || errno == EACCES) {
  418. write(pipefd[1], "S", 1); /* Signal skip */
  419. _exit(0);
  420. }
  421. _exit(1);
  422. }
  423. /* Signal success */
  424. write(pipefd[1], "Y", 1);
  425. close(pipefd[1]);
  426. /* Keep namespace alive */
  427. pause();
  428. _exit(0);
  429. }
  430. /* Track child for cleanup */
  431. self->child_pid = pid;
  432. /* Parent process */
  433. close(pipefd[1]);
  434. char buf;
  435. ASSERT_EQ(read(pipefd[0], &buf, 1), 1);
  436. close(pipefd[0]);
  437. if (buf == 'S') {
  438. /* Child couldn't create namespace, skip test */
  439. close(fd_parent_userns);
  440. SKIP(return, "No permission to create user namespace");
  441. }
  442. ASSERT_EQ(buf, 'Y');
  443. /* Open child's user namespace */
  444. char path[256];
  445. snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
  446. fd_child_userns = open(path, O_RDONLY);
  447. ASSERT_GE(fd_child_userns, 0);
  448. /* Get child's user namespace ID */
  449. ret = ioctl(fd_child_userns, NS_GET_ID, &child_user_ns_id);
  450. ASSERT_EQ(ret, 0);
  451. ASSERT_NE(child_user_ns_id, 0);
  452. /* Parent and child should have different user namespace IDs */
  453. ASSERT_NE(parent_user_ns_id, child_user_ns_id);
  454. close(fd_parent_userns);
  455. close(fd_child_userns);
  456. }
  457. TEST(nsid_timens_basic)
  458. {
  459. __u64 time_ns_id = 0;
  460. int fd_timens;
  461. int ret;
  462. /* Open the current time namespace */
  463. fd_timens = open("/proc/self/ns/time", O_RDONLY);
  464. if (fd_timens < 0) {
  465. SKIP(return, "Time namespaces not supported");
  466. }
  467. /* Get the time namespace ID */
  468. ret = ioctl(fd_timens, NS_GET_ID, &time_ns_id);
  469. ASSERT_EQ(ret, 0);
  470. ASSERT_NE(time_ns_id, 0);
  471. /* Verify we can get the same ID again */
  472. __u64 time_ns_id2 = 0;
  473. ret = ioctl(fd_timens, NS_GET_ID, &time_ns_id2);
  474. ASSERT_EQ(ret, 0);
  475. ASSERT_EQ(time_ns_id, time_ns_id2);
  476. close(fd_timens);
  477. }
  478. TEST_F(nsid, timens_separate)
  479. {
  480. __u64 parent_time_ns_id = 0;
  481. __u64 child_time_ns_id = 0;
  482. int fd_parent_timens, fd_child_timens;
  483. int ret;
  484. pid_t pid;
  485. int pipefd[2];
  486. /* Open the current time namespace */
  487. fd_parent_timens = open("/proc/self/ns/time", O_RDONLY);
  488. if (fd_parent_timens < 0) {
  489. SKIP(return, "Time namespaces not supported");
  490. }
  491. /* Get parent's time namespace ID */
  492. ret = ioctl(fd_parent_timens, NS_GET_ID, &parent_time_ns_id);
  493. ASSERT_EQ(ret, 0);
  494. ASSERT_NE(parent_time_ns_id, 0);
  495. /* Create a pipe for synchronization */
  496. ASSERT_EQ(pipe(pipefd), 0);
  497. pid = fork();
  498. ASSERT_GE(pid, 0);
  499. if (pid == 0) {
  500. /* Child process */
  501. close(pipefd[0]);
  502. /* Create new time namespace */
  503. ret = unshare(CLONE_NEWTIME);
  504. if (ret != 0) {
  505. /* Skip test if we don't have permission */
  506. if (errno == EPERM || errno == EACCES || errno == EINVAL) {
  507. write(pipefd[1], "S", 1); /* Signal skip */
  508. _exit(0);
  509. }
  510. _exit(1);
  511. }
  512. /* Fork a grandchild to actually enter the new namespace */
  513. pid_t grandchild = fork();
  514. if (grandchild == 0) {
  515. /* Grandchild is in the new namespace */
  516. write(pipefd[1], "Y", 1);
  517. close(pipefd[1]);
  518. pause();
  519. _exit(0);
  520. } else if (grandchild > 0) {
  521. /* Child writes grandchild PID and waits */
  522. write(pipefd[1], "Y", 1);
  523. write(pipefd[1], &grandchild, sizeof(grandchild));
  524. close(pipefd[1]);
  525. pause(); /* Keep the parent alive to maintain the grandchild */
  526. _exit(0);
  527. } else {
  528. _exit(1);
  529. }
  530. }
  531. /* Track child for cleanup */
  532. self->child_pid = pid;
  533. /* Parent process */
  534. close(pipefd[1]);
  535. char buf;
  536. ASSERT_EQ(read(pipefd[0], &buf, 1), 1);
  537. if (buf == 'S') {
  538. /* Child couldn't create namespace, skip test */
  539. close(fd_parent_timens);
  540. close(pipefd[0]);
  541. SKIP(return, "Cannot create time namespace");
  542. }
  543. ASSERT_EQ(buf, 'Y');
  544. pid_t grandchild_pid;
  545. ASSERT_EQ(read(pipefd[0], &grandchild_pid, sizeof(grandchild_pid)), sizeof(grandchild_pid));
  546. close(pipefd[0]);
  547. /* Open grandchild's time namespace */
  548. char path[256];
  549. snprintf(path, sizeof(path), "/proc/%d/ns/time", grandchild_pid);
  550. fd_child_timens = open(path, O_RDONLY);
  551. ASSERT_GE(fd_child_timens, 0);
  552. /* Get child's time namespace ID */
  553. ret = ioctl(fd_child_timens, NS_GET_ID, &child_time_ns_id);
  554. ASSERT_EQ(ret, 0);
  555. ASSERT_NE(child_time_ns_id, 0);
  556. /* Parent and child should have different time namespace IDs */
  557. ASSERT_NE(parent_time_ns_id, child_time_ns_id);
  558. close(fd_parent_timens);
  559. close(fd_child_timens);
  560. }
  561. TEST(nsid_pidns_basic)
  562. {
  563. __u64 pid_ns_id = 0;
  564. int fd_pidns;
  565. int ret;
  566. /* Open the current PID namespace */
  567. fd_pidns = open("/proc/self/ns/pid", O_RDONLY);
  568. ASSERT_GE(fd_pidns, 0);
  569. /* Get the PID namespace ID */
  570. ret = ioctl(fd_pidns, NS_GET_ID, &pid_ns_id);
  571. ASSERT_EQ(ret, 0);
  572. ASSERT_NE(pid_ns_id, 0);
  573. /* Verify we can get the same ID again */
  574. __u64 pid_ns_id2 = 0;
  575. ret = ioctl(fd_pidns, NS_GET_ID, &pid_ns_id2);
  576. ASSERT_EQ(ret, 0);
  577. ASSERT_EQ(pid_ns_id, pid_ns_id2);
  578. close(fd_pidns);
  579. }
  580. TEST_F(nsid, pidns_separate)
  581. {
  582. __u64 parent_pid_ns_id = 0;
  583. __u64 child_pid_ns_id = 0;
  584. int fd_parent_pidns, fd_child_pidns;
  585. int ret;
  586. pid_t pid;
  587. int pipefd[2];
  588. /* Get parent's PID namespace ID */
  589. fd_parent_pidns = open("/proc/self/ns/pid", O_RDONLY);
  590. ASSERT_GE(fd_parent_pidns, 0);
  591. ret = ioctl(fd_parent_pidns, NS_GET_ID, &parent_pid_ns_id);
  592. ASSERT_EQ(ret, 0);
  593. ASSERT_NE(parent_pid_ns_id, 0);
  594. /* Create a pipe for synchronization */
  595. ASSERT_EQ(pipe(pipefd), 0);
  596. pid = fork();
  597. ASSERT_GE(pid, 0);
  598. if (pid == 0) {
  599. /* Child process */
  600. close(pipefd[0]);
  601. /* Create new PID namespace */
  602. ret = unshare(CLONE_NEWPID);
  603. if (ret != 0) {
  604. /* Skip test if we don't have permission */
  605. if (errno == EPERM || errno == EACCES) {
  606. write(pipefd[1], "S", 1); /* Signal skip */
  607. _exit(0);
  608. }
  609. _exit(1);
  610. }
  611. /* Fork a grandchild to actually enter the new namespace */
  612. pid_t grandchild = fork();
  613. if (grandchild == 0) {
  614. /* Grandchild is in the new namespace */
  615. write(pipefd[1], "Y", 1);
  616. close(pipefd[1]);
  617. pause();
  618. _exit(0);
  619. } else if (grandchild > 0) {
  620. /* Child writes grandchild PID and waits */
  621. write(pipefd[1], "Y", 1);
  622. write(pipefd[1], &grandchild, sizeof(grandchild));
  623. close(pipefd[1]);
  624. pause(); /* Keep the parent alive to maintain the grandchild */
  625. _exit(0);
  626. } else {
  627. _exit(1);
  628. }
  629. }
  630. /* Track child for cleanup */
  631. self->child_pid = pid;
  632. /* Parent process */
  633. close(pipefd[1]);
  634. char buf;
  635. ASSERT_EQ(read(pipefd[0], &buf, 1), 1);
  636. if (buf == 'S') {
  637. /* Child couldn't create namespace, skip test */
  638. close(fd_parent_pidns);
  639. close(pipefd[0]);
  640. SKIP(return, "No permission to create PID namespace");
  641. }
  642. ASSERT_EQ(buf, 'Y');
  643. pid_t grandchild_pid;
  644. ASSERT_EQ(read(pipefd[0], &grandchild_pid, sizeof(grandchild_pid)), sizeof(grandchild_pid));
  645. close(pipefd[0]);
  646. /* Open grandchild's PID namespace */
  647. char path[256];
  648. snprintf(path, sizeof(path), "/proc/%d/ns/pid", grandchild_pid);
  649. fd_child_pidns = open(path, O_RDONLY);
  650. ASSERT_GE(fd_child_pidns, 0);
  651. /* Get child's PID namespace ID */
  652. ret = ioctl(fd_child_pidns, NS_GET_ID, &child_pid_ns_id);
  653. ASSERT_EQ(ret, 0);
  654. ASSERT_NE(child_pid_ns_id, 0);
  655. /* Parent and child should have different PID namespace IDs */
  656. ASSERT_NE(parent_pid_ns_id, child_pid_ns_id);
  657. close(fd_parent_pidns);
  658. close(fd_child_pidns);
  659. }
  660. TEST(nsid_netns_basic)
  661. {
  662. __u64 net_ns_id = 0;
  663. __u64 netns_cookie = 0;
  664. int fd_netns;
  665. int sock;
  666. socklen_t optlen;
  667. int ret;
  668. /* Open the current network namespace */
  669. fd_netns = open("/proc/self/ns/net", O_RDONLY);
  670. ASSERT_GE(fd_netns, 0);
  671. /* Get the network namespace ID via ioctl */
  672. ret = ioctl(fd_netns, NS_GET_ID, &net_ns_id);
  673. ASSERT_EQ(ret, 0);
  674. ASSERT_NE(net_ns_id, 0);
  675. /* Create a socket to get the SO_NETNS_COOKIE */
  676. sock = socket(AF_UNIX, SOCK_STREAM, 0);
  677. ASSERT_GE(sock, 0);
  678. /* Get the network namespace cookie via socket option */
  679. optlen = sizeof(netns_cookie);
  680. ret = getsockopt(sock, SOL_SOCKET, SO_NETNS_COOKIE, &netns_cookie, &optlen);
  681. ASSERT_EQ(ret, 0);
  682. ASSERT_EQ(optlen, sizeof(netns_cookie));
  683. /* The namespace ID and cookie should be identical */
  684. ASSERT_EQ(net_ns_id, netns_cookie);
  685. /* Verify we can get the same ID again */
  686. __u64 net_ns_id2 = 0;
  687. ret = ioctl(fd_netns, NS_GET_ID, &net_ns_id2);
  688. ASSERT_EQ(ret, 0);
  689. ASSERT_EQ(net_ns_id, net_ns_id2);
  690. close(sock);
  691. close(fd_netns);
  692. }
  693. TEST_F(nsid, netns_separate)
  694. {
  695. __u64 parent_net_ns_id = 0;
  696. __u64 parent_netns_cookie = 0;
  697. __u64 child_net_ns_id = 0;
  698. __u64 child_netns_cookie = 0;
  699. int fd_parent_netns, fd_child_netns;
  700. int parent_sock, child_sock;
  701. socklen_t optlen;
  702. int ret;
  703. pid_t pid;
  704. int pipefd[2];
  705. /* Get parent's network namespace ID */
  706. fd_parent_netns = open("/proc/self/ns/net", O_RDONLY);
  707. ASSERT_GE(fd_parent_netns, 0);
  708. ret = ioctl(fd_parent_netns, NS_GET_ID, &parent_net_ns_id);
  709. ASSERT_EQ(ret, 0);
  710. ASSERT_NE(parent_net_ns_id, 0);
  711. /* Get parent's network namespace cookie */
  712. parent_sock = socket(AF_UNIX, SOCK_STREAM, 0);
  713. ASSERT_GE(parent_sock, 0);
  714. optlen = sizeof(parent_netns_cookie);
  715. ret = getsockopt(parent_sock, SOL_SOCKET, SO_NETNS_COOKIE, &parent_netns_cookie, &optlen);
  716. ASSERT_EQ(ret, 0);
  717. /* Verify parent's ID and cookie match */
  718. ASSERT_EQ(parent_net_ns_id, parent_netns_cookie);
  719. /* Create a pipe for synchronization */
  720. ASSERT_EQ(pipe(pipefd), 0);
  721. pid = fork();
  722. ASSERT_GE(pid, 0);
  723. if (pid == 0) {
  724. /* Child process */
  725. close(pipefd[0]);
  726. /* Create new network namespace */
  727. ret = unshare(CLONE_NEWNET);
  728. if (ret != 0) {
  729. /* Skip test if we don't have permission */
  730. if (errno == EPERM || errno == EACCES) {
  731. write(pipefd[1], "S", 1); /* Signal skip */
  732. _exit(0);
  733. }
  734. _exit(1);
  735. }
  736. /* Signal success */
  737. write(pipefd[1], "Y", 1);
  738. close(pipefd[1]);
  739. /* Keep namespace alive */
  740. pause();
  741. _exit(0);
  742. }
  743. /* Track child for cleanup */
  744. self->child_pid = pid;
  745. /* Parent process */
  746. close(pipefd[1]);
  747. char buf;
  748. ASSERT_EQ(read(pipefd[0], &buf, 1), 1);
  749. close(pipefd[0]);
  750. if (buf == 'S') {
  751. /* Child couldn't create namespace, skip test */
  752. close(fd_parent_netns);
  753. close(parent_sock);
  754. SKIP(return, "No permission to create network namespace");
  755. }
  756. ASSERT_EQ(buf, 'Y');
  757. /* Open child's network namespace */
  758. char path[256];
  759. snprintf(path, sizeof(path), "/proc/%d/ns/net", pid);
  760. fd_child_netns = open(path, O_RDONLY);
  761. ASSERT_GE(fd_child_netns, 0);
  762. /* Get child's network namespace ID */
  763. ret = ioctl(fd_child_netns, NS_GET_ID, &child_net_ns_id);
  764. ASSERT_EQ(ret, 0);
  765. ASSERT_NE(child_net_ns_id, 0);
  766. /* Create socket in child's namespace to get cookie */
  767. ret = setns(fd_child_netns, CLONE_NEWNET);
  768. if (ret == 0) {
  769. child_sock = socket(AF_UNIX, SOCK_STREAM, 0);
  770. ASSERT_GE(child_sock, 0);
  771. optlen = sizeof(child_netns_cookie);
  772. ret = getsockopt(child_sock, SOL_SOCKET, SO_NETNS_COOKIE, &child_netns_cookie, &optlen);
  773. ASSERT_EQ(ret, 0);
  774. /* Verify child's ID and cookie match */
  775. ASSERT_EQ(child_net_ns_id, child_netns_cookie);
  776. close(child_sock);
  777. /* Return to parent namespace */
  778. setns(fd_parent_netns, CLONE_NEWNET);
  779. }
  780. /* Parent and child should have different network namespace IDs */
  781. ASSERT_NE(parent_net_ns_id, child_net_ns_id);
  782. if (child_netns_cookie != 0) {
  783. ASSERT_NE(parent_netns_cookie, child_netns_cookie);
  784. }
  785. close(fd_parent_netns);
  786. close(fd_child_netns);
  787. close(parent_sock);
  788. }
  789. TEST_HARNESS_MAIN