file_handle_test.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <errno.h>
  4. #include <fcntl.h>
  5. #include <grp.h>
  6. #include <limits.h>
  7. #include <sched.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <sys/mount.h>
  12. #include <sys/stat.h>
  13. #include <sys/types.h>
  14. #include <sys/wait.h>
  15. #include <unistd.h>
  16. #include <linux/unistd.h>
  17. #include "kselftest_harness.h"
  18. #ifndef FD_NSFS_ROOT
  19. #define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */
  20. #endif
  21. TEST(nsfs_net_handle)
  22. {
  23. struct file_handle *handle;
  24. int mount_id;
  25. int ret;
  26. int fd;
  27. int ns_fd;
  28. struct stat st1, st2;
  29. /* Drop to unprivileged uid/gid */
  30. ASSERT_EQ(setresgid(65534, 65534, 65534), 0); /* nogroup */
  31. ASSERT_EQ(setresuid(65534, 65534, 65534), 0); /* nobody */
  32. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  33. ASSERT_NE(handle, NULL);
  34. /* Open a namespace file descriptor */
  35. ns_fd = open("/proc/self/ns/net", O_RDONLY);
  36. ASSERT_GE(ns_fd, 0);
  37. /* Get handle for the namespace */
  38. handle->handle_bytes = MAX_HANDLE_SZ;
  39. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  40. if (ret < 0 && errno == EOPNOTSUPP) {
  41. SKIP(free(handle); close(ns_fd);
  42. return, "nsfs doesn't support file handles");
  43. }
  44. ASSERT_EQ(ret, 0);
  45. ASSERT_GT(handle->handle_bytes, 0);
  46. /* Try to open using FD_NSFS_ROOT as unprivileged user */
  47. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  48. if (fd < 0 && (errno == EINVAL || errno == EOPNOTSUPP)) {
  49. SKIP(free(handle); close(ns_fd);
  50. return,
  51. "open_by_handle_at with FD_NSFS_ROOT not supported");
  52. }
  53. if (fd < 0 && errno == EPERM) {
  54. SKIP(free(handle); close(ns_fd);
  55. return,
  56. "Permission denied for unprivileged user (expected)");
  57. }
  58. ASSERT_GE(fd, 0);
  59. /* Verify we opened the correct namespace */
  60. ASSERT_EQ(fstat(ns_fd, &st1), 0);
  61. ASSERT_EQ(fstat(fd, &st2), 0);
  62. ASSERT_EQ(st1.st_ino, st2.st_ino);
  63. ASSERT_EQ(st1.st_dev, st2.st_dev);
  64. close(fd);
  65. close(ns_fd);
  66. free(handle);
  67. }
  68. TEST(nsfs_uts_handle)
  69. {
  70. struct file_handle *handle;
  71. int mount_id;
  72. int ret;
  73. int fd;
  74. int ns_fd;
  75. struct stat st1, st2;
  76. /* Drop to unprivileged uid/gid */
  77. ASSERT_EQ(setresgid(65534, 65534, 65534), 0); /* nogroup */
  78. ASSERT_EQ(setresuid(65534, 65534, 65534), 0); /* nobody */
  79. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  80. ASSERT_NE(handle, NULL);
  81. /* Open UTS namespace file descriptor */
  82. ns_fd = open("/proc/self/ns/uts", O_RDONLY);
  83. ASSERT_GE(ns_fd, 0);
  84. /* Get handle for the namespace */
  85. handle->handle_bytes = MAX_HANDLE_SZ;
  86. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  87. if (ret < 0 && errno == EOPNOTSUPP) {
  88. SKIP(free(handle); close(ns_fd);
  89. return, "nsfs doesn't support file handles");
  90. }
  91. ASSERT_EQ(ret, 0);
  92. ASSERT_GT(handle->handle_bytes, 0);
  93. /* Try to open using FD_NSFS_ROOT */
  94. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  95. if (fd < 0 && (errno == EINVAL || errno == EOPNOTSUPP)) {
  96. SKIP(free(handle); close(ns_fd);
  97. return,
  98. "open_by_handle_at with FD_NSFS_ROOT not supported");
  99. }
  100. ASSERT_GE(fd, 0);
  101. /* Verify we opened the correct namespace */
  102. ASSERT_EQ(fstat(ns_fd, &st1), 0);
  103. ASSERT_EQ(fstat(fd, &st2), 0);
  104. ASSERT_EQ(st1.st_ino, st2.st_ino);
  105. ASSERT_EQ(st1.st_dev, st2.st_dev);
  106. close(fd);
  107. close(ns_fd);
  108. free(handle);
  109. }
  110. TEST(nsfs_ipc_handle)
  111. {
  112. struct file_handle *handle;
  113. int mount_id;
  114. int ret;
  115. int fd;
  116. int ns_fd;
  117. struct stat st1, st2;
  118. /* Drop to unprivileged uid/gid */
  119. ASSERT_EQ(setresgid(65534, 65534, 65534), 0); /* nogroup */
  120. ASSERT_EQ(setresuid(65534, 65534, 65534), 0); /* nobody */
  121. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  122. ASSERT_NE(handle, NULL);
  123. /* Open IPC namespace file descriptor */
  124. ns_fd = open("/proc/self/ns/ipc", O_RDONLY);
  125. ASSERT_GE(ns_fd, 0);
  126. /* Get handle for the namespace */
  127. handle->handle_bytes = MAX_HANDLE_SZ;
  128. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  129. if (ret < 0 && errno == EOPNOTSUPP) {
  130. SKIP(free(handle); close(ns_fd);
  131. return, "nsfs doesn't support file handles");
  132. }
  133. ASSERT_EQ(ret, 0);
  134. ASSERT_GT(handle->handle_bytes, 0);
  135. /* Try to open using FD_NSFS_ROOT */
  136. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  137. if (fd < 0 && (errno == EINVAL || errno == EOPNOTSUPP)) {
  138. SKIP(free(handle); close(ns_fd);
  139. return,
  140. "open_by_handle_at with FD_NSFS_ROOT not supported");
  141. }
  142. ASSERT_GE(fd, 0);
  143. /* Verify we opened the correct namespace */
  144. ASSERT_EQ(fstat(ns_fd, &st1), 0);
  145. ASSERT_EQ(fstat(fd, &st2), 0);
  146. ASSERT_EQ(st1.st_ino, st2.st_ino);
  147. ASSERT_EQ(st1.st_dev, st2.st_dev);
  148. close(fd);
  149. close(ns_fd);
  150. free(handle);
  151. }
  152. TEST(nsfs_pid_handle)
  153. {
  154. struct file_handle *handle;
  155. int mount_id;
  156. int ret;
  157. int fd;
  158. int ns_fd;
  159. struct stat st1, st2;
  160. /* Drop to unprivileged uid/gid */
  161. ASSERT_EQ(setresgid(65534, 65534, 65534), 0); /* nogroup */
  162. ASSERT_EQ(setresuid(65534, 65534, 65534), 0); /* nobody */
  163. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  164. ASSERT_NE(handle, NULL);
  165. /* Open PID namespace file descriptor */
  166. ns_fd = open("/proc/self/ns/pid", O_RDONLY);
  167. ASSERT_GE(ns_fd, 0);
  168. /* Get handle for the namespace */
  169. handle->handle_bytes = MAX_HANDLE_SZ;
  170. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  171. if (ret < 0 && errno == EOPNOTSUPP) {
  172. SKIP(free(handle); close(ns_fd);
  173. return, "nsfs doesn't support file handles");
  174. }
  175. ASSERT_EQ(ret, 0);
  176. ASSERT_GT(handle->handle_bytes, 0);
  177. /* Try to open using FD_NSFS_ROOT */
  178. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  179. if (fd < 0 && (errno == EINVAL || errno == EOPNOTSUPP)) {
  180. SKIP(free(handle); close(ns_fd);
  181. return,
  182. "open_by_handle_at with FD_NSFS_ROOT not supported");
  183. }
  184. ASSERT_GE(fd, 0);
  185. /* Verify we opened the correct namespace */
  186. ASSERT_EQ(fstat(ns_fd, &st1), 0);
  187. ASSERT_EQ(fstat(fd, &st2), 0);
  188. ASSERT_EQ(st1.st_ino, st2.st_ino);
  189. ASSERT_EQ(st1.st_dev, st2.st_dev);
  190. close(fd);
  191. close(ns_fd);
  192. free(handle);
  193. }
  194. TEST(nsfs_mnt_handle)
  195. {
  196. struct file_handle *handle;
  197. int mount_id;
  198. int ret;
  199. int fd;
  200. int ns_fd;
  201. struct stat st1, st2;
  202. /* Drop to unprivileged uid/gid */
  203. ASSERT_EQ(setresgid(65534, 65534, 65534), 0); /* nogroup */
  204. ASSERT_EQ(setresuid(65534, 65534, 65534), 0); /* nobody */
  205. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  206. ASSERT_NE(handle, NULL);
  207. /* Open mount namespace file descriptor */
  208. ns_fd = open("/proc/self/ns/mnt", O_RDONLY);
  209. ASSERT_GE(ns_fd, 0);
  210. /* Get handle for the namespace */
  211. handle->handle_bytes = MAX_HANDLE_SZ;
  212. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  213. if (ret < 0 && errno == EOPNOTSUPP) {
  214. SKIP(free(handle); close(ns_fd);
  215. return, "nsfs doesn't support file handles");
  216. }
  217. ASSERT_EQ(ret, 0);
  218. ASSERT_GT(handle->handle_bytes, 0);
  219. /* Try to open using FD_NSFS_ROOT */
  220. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  221. if (fd < 0 && (errno == EINVAL || errno == EOPNOTSUPP)) {
  222. SKIP(free(handle); close(ns_fd);
  223. return,
  224. "open_by_handle_at with FD_NSFS_ROOT not supported");
  225. }
  226. ASSERT_GE(fd, 0);
  227. /* Verify we opened the correct namespace */
  228. ASSERT_EQ(fstat(ns_fd, &st1), 0);
  229. ASSERT_EQ(fstat(fd, &st2), 0);
  230. ASSERT_EQ(st1.st_ino, st2.st_ino);
  231. ASSERT_EQ(st1.st_dev, st2.st_dev);
  232. close(fd);
  233. close(ns_fd);
  234. free(handle);
  235. }
  236. TEST(nsfs_user_handle)
  237. {
  238. struct file_handle *handle;
  239. int mount_id;
  240. int ret;
  241. int fd;
  242. int ns_fd;
  243. struct stat st1, st2;
  244. /* Drop to unprivileged uid/gid */
  245. ASSERT_EQ(setresgid(65534, 65534, 65534), 0); /* nogroup */
  246. ASSERT_EQ(setresuid(65534, 65534, 65534), 0); /* nobody */
  247. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  248. ASSERT_NE(handle, NULL);
  249. /* Open user namespace file descriptor */
  250. ns_fd = open("/proc/self/ns/user", O_RDONLY);
  251. ASSERT_GE(ns_fd, 0);
  252. /* Get handle for the namespace */
  253. handle->handle_bytes = MAX_HANDLE_SZ;
  254. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  255. if (ret < 0 && errno == EOPNOTSUPP) {
  256. SKIP(free(handle); close(ns_fd);
  257. return, "nsfs doesn't support file handles");
  258. }
  259. ASSERT_EQ(ret, 0);
  260. ASSERT_GT(handle->handle_bytes, 0);
  261. /* Try to open using FD_NSFS_ROOT */
  262. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  263. if (fd < 0 && (errno == EINVAL || errno == EOPNOTSUPP)) {
  264. SKIP(free(handle); close(ns_fd);
  265. return,
  266. "open_by_handle_at with FD_NSFS_ROOT not supported");
  267. }
  268. ASSERT_GE(fd, 0);
  269. /* Verify we opened the correct namespace */
  270. ASSERT_EQ(fstat(ns_fd, &st1), 0);
  271. ASSERT_EQ(fstat(fd, &st2), 0);
  272. ASSERT_EQ(st1.st_ino, st2.st_ino);
  273. ASSERT_EQ(st1.st_dev, st2.st_dev);
  274. close(fd);
  275. close(ns_fd);
  276. free(handle);
  277. }
  278. TEST(nsfs_cgroup_handle)
  279. {
  280. struct file_handle *handle;
  281. int mount_id;
  282. int ret;
  283. int fd;
  284. int ns_fd;
  285. struct stat st1, st2;
  286. /* Drop to unprivileged uid/gid */
  287. ASSERT_EQ(setresgid(65534, 65534, 65534), 0); /* nogroup */
  288. ASSERT_EQ(setresuid(65534, 65534, 65534), 0); /* nobody */
  289. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  290. ASSERT_NE(handle, NULL);
  291. /* Open cgroup namespace file descriptor */
  292. ns_fd = open("/proc/self/ns/cgroup", O_RDONLY);
  293. if (ns_fd < 0) {
  294. SKIP(free(handle); return, "cgroup namespace not available");
  295. }
  296. /* Get handle for the namespace */
  297. handle->handle_bytes = MAX_HANDLE_SZ;
  298. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  299. if (ret < 0 && errno == EOPNOTSUPP) {
  300. SKIP(free(handle); close(ns_fd);
  301. return, "nsfs doesn't support file handles");
  302. }
  303. ASSERT_EQ(ret, 0);
  304. ASSERT_GT(handle->handle_bytes, 0);
  305. /* Try to open using FD_NSFS_ROOT */
  306. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  307. if (fd < 0 && (errno == EINVAL || errno == EOPNOTSUPP)) {
  308. SKIP(free(handle); close(ns_fd);
  309. return,
  310. "open_by_handle_at with FD_NSFS_ROOT not supported");
  311. }
  312. ASSERT_GE(fd, 0);
  313. /* Verify we opened the correct namespace */
  314. ASSERT_EQ(fstat(ns_fd, &st1), 0);
  315. ASSERT_EQ(fstat(fd, &st2), 0);
  316. ASSERT_EQ(st1.st_ino, st2.st_ino);
  317. ASSERT_EQ(st1.st_dev, st2.st_dev);
  318. close(fd);
  319. close(ns_fd);
  320. free(handle);
  321. }
  322. TEST(nsfs_time_handle)
  323. {
  324. struct file_handle *handle;
  325. int mount_id;
  326. int ret;
  327. int fd;
  328. int ns_fd;
  329. struct stat st1, st2;
  330. /* Drop to unprivileged uid/gid */
  331. ASSERT_EQ(setresgid(65534, 65534, 65534), 0); /* nogroup */
  332. ASSERT_EQ(setresuid(65534, 65534, 65534), 0); /* nobody */
  333. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  334. ASSERT_NE(handle, NULL);
  335. /* Open time namespace file descriptor */
  336. ns_fd = open("/proc/self/ns/time", O_RDONLY);
  337. if (ns_fd < 0) {
  338. SKIP(free(handle); return, "time namespace not available");
  339. }
  340. /* Get handle for the namespace */
  341. handle->handle_bytes = MAX_HANDLE_SZ;
  342. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  343. if (ret < 0 && errno == EOPNOTSUPP) {
  344. SKIP(free(handle); close(ns_fd);
  345. return, "nsfs doesn't support file handles");
  346. }
  347. ASSERT_EQ(ret, 0);
  348. ASSERT_GT(handle->handle_bytes, 0);
  349. /* Try to open using FD_NSFS_ROOT */
  350. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  351. if (fd < 0 && (errno == EINVAL || errno == EOPNOTSUPP)) {
  352. SKIP(free(handle); close(ns_fd);
  353. return,
  354. "open_by_handle_at with FD_NSFS_ROOT not supported");
  355. }
  356. ASSERT_GE(fd, 0);
  357. /* Verify we opened the correct namespace */
  358. ASSERT_EQ(fstat(ns_fd, &st1), 0);
  359. ASSERT_EQ(fstat(fd, &st2), 0);
  360. ASSERT_EQ(st1.st_ino, st2.st_ino);
  361. ASSERT_EQ(st1.st_dev, st2.st_dev);
  362. close(fd);
  363. close(ns_fd);
  364. free(handle);
  365. }
  366. TEST(nsfs_user_net_namespace_isolation)
  367. {
  368. struct file_handle *handle;
  369. int mount_id;
  370. int ret;
  371. int fd;
  372. int ns_fd;
  373. pid_t pid;
  374. int status;
  375. int pipefd[2];
  376. char result;
  377. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  378. ASSERT_NE(handle, NULL);
  379. /* Create pipe for communication */
  380. ASSERT_EQ(pipe(pipefd), 0);
  381. /* Get handle for current network namespace */
  382. ns_fd = open("/proc/self/ns/net", O_RDONLY);
  383. ASSERT_GE(ns_fd, 0);
  384. handle->handle_bytes = MAX_HANDLE_SZ;
  385. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  386. if (ret < 0 && errno == EOPNOTSUPP) {
  387. SKIP(free(handle); close(ns_fd); close(pipefd[0]);
  388. close(pipefd[1]);
  389. return, "nsfs doesn't support file handles");
  390. }
  391. ASSERT_EQ(ret, 0);
  392. close(ns_fd);
  393. pid = fork();
  394. ASSERT_GE(pid, 0);
  395. if (pid == 0) {
  396. /* Child process */
  397. close(pipefd[0]);
  398. /* First create new user namespace to drop privileges */
  399. ret = unshare(CLONE_NEWUSER);
  400. if (ret < 0) {
  401. write(pipefd[1], "U",
  402. 1); /* Unable to create user namespace */
  403. close(pipefd[1]);
  404. exit(0);
  405. }
  406. /* Write uid/gid mappings to maintain some capabilities */
  407. int uid_map_fd = open("/proc/self/uid_map", O_WRONLY);
  408. int gid_map_fd = open("/proc/self/gid_map", O_WRONLY);
  409. int setgroups_fd = open("/proc/self/setgroups", O_WRONLY);
  410. if (uid_map_fd < 0 || gid_map_fd < 0 || setgroups_fd < 0) {
  411. write(pipefd[1], "M", 1); /* Unable to set mappings */
  412. close(pipefd[1]);
  413. exit(0);
  414. }
  415. /* Disable setgroups to allow gid mapping */
  416. write(setgroups_fd, "deny", 4);
  417. close(setgroups_fd);
  418. /* Map current uid/gid to root in the new namespace */
  419. char mapping[64];
  420. snprintf(mapping, sizeof(mapping), "0 %d 1", getuid());
  421. write(uid_map_fd, mapping, strlen(mapping));
  422. close(uid_map_fd);
  423. snprintf(mapping, sizeof(mapping), "0 %d 1", getgid());
  424. write(gid_map_fd, mapping, strlen(mapping));
  425. close(gid_map_fd);
  426. /* Now create new network namespace */
  427. ret = unshare(CLONE_NEWNET);
  428. if (ret < 0) {
  429. write(pipefd[1], "N",
  430. 1); /* Unable to create network namespace */
  431. close(pipefd[1]);
  432. exit(0);
  433. }
  434. /* Try to open parent's network namespace handle from new user+net namespace */
  435. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  436. if (fd >= 0) {
  437. /* Should NOT succeed - we're in a different user namespace */
  438. write(pipefd[1], "S", 1); /* Unexpected success */
  439. close(fd);
  440. } else if (errno == ESTALE) {
  441. /* Expected: Stale file handle */
  442. write(pipefd[1], "P", 1);
  443. } else {
  444. /* Other error */
  445. write(pipefd[1], "F", 1);
  446. }
  447. close(pipefd[1]);
  448. exit(0);
  449. }
  450. /* Parent process */
  451. close(pipefd[1]);
  452. ASSERT_EQ(read(pipefd[0], &result, 1), 1);
  453. waitpid(pid, &status, 0);
  454. ASSERT_TRUE(WIFEXITED(status));
  455. ASSERT_EQ(WEXITSTATUS(status), 0);
  456. if (result == 'U') {
  457. SKIP(free(handle); close(pipefd[0]);
  458. return, "Cannot create new user namespace");
  459. }
  460. if (result == 'M') {
  461. SKIP(free(handle); close(pipefd[0]);
  462. return, "Cannot set uid/gid mappings");
  463. }
  464. if (result == 'N') {
  465. SKIP(free(handle); close(pipefd[0]);
  466. return, "Cannot create new network namespace");
  467. }
  468. /* Should fail with permission denied since we're in a different user namespace */
  469. ASSERT_EQ(result, 'P');
  470. close(pipefd[0]);
  471. free(handle);
  472. }
  473. TEST(nsfs_user_uts_namespace_isolation)
  474. {
  475. struct file_handle *handle;
  476. int mount_id;
  477. int ret;
  478. int fd;
  479. int ns_fd;
  480. pid_t pid;
  481. int status;
  482. int pipefd[2];
  483. char result;
  484. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  485. ASSERT_NE(handle, NULL);
  486. /* Create pipe for communication */
  487. ASSERT_EQ(pipe(pipefd), 0);
  488. /* Get handle for current UTS namespace */
  489. ns_fd = open("/proc/self/ns/uts", O_RDONLY);
  490. ASSERT_GE(ns_fd, 0);
  491. handle->handle_bytes = MAX_HANDLE_SZ;
  492. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  493. if (ret < 0 && errno == EOPNOTSUPP) {
  494. SKIP(free(handle); close(ns_fd); close(pipefd[0]);
  495. close(pipefd[1]);
  496. return, "nsfs doesn't support file handles");
  497. }
  498. ASSERT_EQ(ret, 0);
  499. close(ns_fd);
  500. pid = fork();
  501. ASSERT_GE(pid, 0);
  502. if (pid == 0) {
  503. /* Child process */
  504. close(pipefd[0]);
  505. /* First create new user namespace to drop privileges */
  506. ret = unshare(CLONE_NEWUSER);
  507. if (ret < 0) {
  508. write(pipefd[1], "U",
  509. 1); /* Unable to create user namespace */
  510. close(pipefd[1]);
  511. exit(0);
  512. }
  513. /* Write uid/gid mappings to maintain some capabilities */
  514. int uid_map_fd = open("/proc/self/uid_map", O_WRONLY);
  515. int gid_map_fd = open("/proc/self/gid_map", O_WRONLY);
  516. int setgroups_fd = open("/proc/self/setgroups", O_WRONLY);
  517. if (uid_map_fd < 0 || gid_map_fd < 0 || setgroups_fd < 0) {
  518. write(pipefd[1], "M", 1); /* Unable to set mappings */
  519. close(pipefd[1]);
  520. exit(0);
  521. }
  522. /* Disable setgroups to allow gid mapping */
  523. write(setgroups_fd, "deny", 4);
  524. close(setgroups_fd);
  525. /* Map current uid/gid to root in the new namespace */
  526. char mapping[64];
  527. snprintf(mapping, sizeof(mapping), "0 %d 1", getuid());
  528. write(uid_map_fd, mapping, strlen(mapping));
  529. close(uid_map_fd);
  530. snprintf(mapping, sizeof(mapping), "0 %d 1", getgid());
  531. write(gid_map_fd, mapping, strlen(mapping));
  532. close(gid_map_fd);
  533. /* Now create new UTS namespace */
  534. ret = unshare(CLONE_NEWUTS);
  535. if (ret < 0) {
  536. write(pipefd[1], "N",
  537. 1); /* Unable to create UTS namespace */
  538. close(pipefd[1]);
  539. exit(0);
  540. }
  541. /* Try to open parent's UTS namespace handle from new user+uts namespace */
  542. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  543. if (fd >= 0) {
  544. /* Should NOT succeed - we're in a different user namespace */
  545. write(pipefd[1], "S", 1); /* Unexpected success */
  546. close(fd);
  547. } else if (errno == ESTALE) {
  548. /* Expected: Stale file handle */
  549. write(pipefd[1], "P", 1);
  550. } else {
  551. /* Other error */
  552. write(pipefd[1], "F", 1);
  553. }
  554. close(pipefd[1]);
  555. exit(0);
  556. }
  557. /* Parent process */
  558. close(pipefd[1]);
  559. ASSERT_EQ(read(pipefd[0], &result, 1), 1);
  560. waitpid(pid, &status, 0);
  561. ASSERT_TRUE(WIFEXITED(status));
  562. ASSERT_EQ(WEXITSTATUS(status), 0);
  563. if (result == 'U') {
  564. SKIP(free(handle); close(pipefd[0]);
  565. return, "Cannot create new user namespace");
  566. }
  567. if (result == 'M') {
  568. SKIP(free(handle); close(pipefd[0]);
  569. return, "Cannot set uid/gid mappings");
  570. }
  571. if (result == 'N') {
  572. SKIP(free(handle); close(pipefd[0]);
  573. return, "Cannot create new UTS namespace");
  574. }
  575. /* Should fail with ESTALE since we're in a different user namespace */
  576. ASSERT_EQ(result, 'P');
  577. close(pipefd[0]);
  578. free(handle);
  579. }
  580. TEST(nsfs_user_ipc_namespace_isolation)
  581. {
  582. struct file_handle *handle;
  583. int mount_id;
  584. int ret;
  585. int fd;
  586. int ns_fd;
  587. pid_t pid;
  588. int status;
  589. int pipefd[2];
  590. char result;
  591. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  592. ASSERT_NE(handle, NULL);
  593. /* Create pipe for communication */
  594. ASSERT_EQ(pipe(pipefd), 0);
  595. /* Get handle for current IPC namespace */
  596. ns_fd = open("/proc/self/ns/ipc", O_RDONLY);
  597. ASSERT_GE(ns_fd, 0);
  598. handle->handle_bytes = MAX_HANDLE_SZ;
  599. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  600. if (ret < 0 && errno == EOPNOTSUPP) {
  601. SKIP(free(handle); close(ns_fd); close(pipefd[0]);
  602. close(pipefd[1]);
  603. return, "nsfs doesn't support file handles");
  604. }
  605. ASSERT_EQ(ret, 0);
  606. close(ns_fd);
  607. pid = fork();
  608. ASSERT_GE(pid, 0);
  609. if (pid == 0) {
  610. /* Child process */
  611. close(pipefd[0]);
  612. /* First create new user namespace to drop privileges */
  613. ret = unshare(CLONE_NEWUSER);
  614. if (ret < 0) {
  615. write(pipefd[1], "U",
  616. 1); /* Unable to create user namespace */
  617. close(pipefd[1]);
  618. exit(0);
  619. }
  620. /* Write uid/gid mappings to maintain some capabilities */
  621. int uid_map_fd = open("/proc/self/uid_map", O_WRONLY);
  622. int gid_map_fd = open("/proc/self/gid_map", O_WRONLY);
  623. int setgroups_fd = open("/proc/self/setgroups", O_WRONLY);
  624. if (uid_map_fd < 0 || gid_map_fd < 0 || setgroups_fd < 0) {
  625. write(pipefd[1], "M", 1); /* Unable to set mappings */
  626. close(pipefd[1]);
  627. exit(0);
  628. }
  629. /* Disable setgroups to allow gid mapping */
  630. write(setgroups_fd, "deny", 4);
  631. close(setgroups_fd);
  632. /* Map current uid/gid to root in the new namespace */
  633. char mapping[64];
  634. snprintf(mapping, sizeof(mapping), "0 %d 1", getuid());
  635. write(uid_map_fd, mapping, strlen(mapping));
  636. close(uid_map_fd);
  637. snprintf(mapping, sizeof(mapping), "0 %d 1", getgid());
  638. write(gid_map_fd, mapping, strlen(mapping));
  639. close(gid_map_fd);
  640. /* Now create new IPC namespace */
  641. ret = unshare(CLONE_NEWIPC);
  642. if (ret < 0) {
  643. write(pipefd[1], "N",
  644. 1); /* Unable to create IPC namespace */
  645. close(pipefd[1]);
  646. exit(0);
  647. }
  648. /* Try to open parent's IPC namespace handle from new user+ipc namespace */
  649. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  650. if (fd >= 0) {
  651. /* Should NOT succeed - we're in a different user namespace */
  652. write(pipefd[1], "S", 1); /* Unexpected success */
  653. close(fd);
  654. } else if (errno == ESTALE) {
  655. /* Expected: Stale file handle */
  656. write(pipefd[1], "P", 1);
  657. } else {
  658. /* Other error */
  659. write(pipefd[1], "F", 1);
  660. }
  661. close(pipefd[1]);
  662. exit(0);
  663. }
  664. /* Parent process */
  665. close(pipefd[1]);
  666. ASSERT_EQ(read(pipefd[0], &result, 1), 1);
  667. waitpid(pid, &status, 0);
  668. ASSERT_TRUE(WIFEXITED(status));
  669. ASSERT_EQ(WEXITSTATUS(status), 0);
  670. if (result == 'U') {
  671. SKIP(free(handle); close(pipefd[0]);
  672. return, "Cannot create new user namespace");
  673. }
  674. if (result == 'M') {
  675. SKIP(free(handle); close(pipefd[0]);
  676. return, "Cannot set uid/gid mappings");
  677. }
  678. if (result == 'N') {
  679. SKIP(free(handle); close(pipefd[0]);
  680. return, "Cannot create new IPC namespace");
  681. }
  682. /* Should fail with ESTALE since we're in a different user namespace */
  683. ASSERT_EQ(result, 'P');
  684. close(pipefd[0]);
  685. free(handle);
  686. }
  687. TEST(nsfs_user_mnt_namespace_isolation)
  688. {
  689. struct file_handle *handle;
  690. int mount_id;
  691. int ret;
  692. int fd;
  693. int ns_fd;
  694. pid_t pid;
  695. int status;
  696. int pipefd[2];
  697. char result;
  698. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  699. ASSERT_NE(handle, NULL);
  700. /* Create pipe for communication */
  701. ASSERT_EQ(pipe(pipefd), 0);
  702. /* Get handle for current mount namespace */
  703. ns_fd = open("/proc/self/ns/mnt", O_RDONLY);
  704. ASSERT_GE(ns_fd, 0);
  705. handle->handle_bytes = MAX_HANDLE_SZ;
  706. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  707. if (ret < 0 && errno == EOPNOTSUPP) {
  708. SKIP(free(handle); close(ns_fd); close(pipefd[0]);
  709. close(pipefd[1]);
  710. return, "nsfs doesn't support file handles");
  711. }
  712. ASSERT_EQ(ret, 0);
  713. close(ns_fd);
  714. pid = fork();
  715. ASSERT_GE(pid, 0);
  716. if (pid == 0) {
  717. /* Child process */
  718. close(pipefd[0]);
  719. /* First create new user namespace to drop privileges */
  720. ret = unshare(CLONE_NEWUSER);
  721. if (ret < 0) {
  722. write(pipefd[1], "U",
  723. 1); /* Unable to create user namespace */
  724. close(pipefd[1]);
  725. exit(0);
  726. }
  727. /* Write uid/gid mappings to maintain some capabilities */
  728. int uid_map_fd = open("/proc/self/uid_map", O_WRONLY);
  729. int gid_map_fd = open("/proc/self/gid_map", O_WRONLY);
  730. int setgroups_fd = open("/proc/self/setgroups", O_WRONLY);
  731. if (uid_map_fd < 0 || gid_map_fd < 0 || setgroups_fd < 0) {
  732. write(pipefd[1], "M", 1); /* Unable to set mappings */
  733. close(pipefd[1]);
  734. exit(0);
  735. }
  736. /* Disable setgroups to allow gid mapping */
  737. write(setgroups_fd, "deny", 4);
  738. close(setgroups_fd);
  739. /* Map current uid/gid to root in the new namespace */
  740. char mapping[64];
  741. snprintf(mapping, sizeof(mapping), "0 %d 1", getuid());
  742. write(uid_map_fd, mapping, strlen(mapping));
  743. close(uid_map_fd);
  744. snprintf(mapping, sizeof(mapping), "0 %d 1", getgid());
  745. write(gid_map_fd, mapping, strlen(mapping));
  746. close(gid_map_fd);
  747. /* Now create new mount namespace */
  748. ret = unshare(CLONE_NEWNS);
  749. if (ret < 0) {
  750. write(pipefd[1], "N",
  751. 1); /* Unable to create mount namespace */
  752. close(pipefd[1]);
  753. exit(0);
  754. }
  755. /* Try to open parent's mount namespace handle from new user+mnt namespace */
  756. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  757. if (fd >= 0) {
  758. /* Should NOT succeed - we're in a different user namespace */
  759. write(pipefd[1], "S", 1); /* Unexpected success */
  760. close(fd);
  761. } else if (errno == ESTALE) {
  762. /* Expected: Stale file handle */
  763. write(pipefd[1], "P", 1);
  764. } else {
  765. /* Other error */
  766. write(pipefd[1], "F", 1);
  767. }
  768. close(pipefd[1]);
  769. exit(0);
  770. }
  771. /* Parent process */
  772. close(pipefd[1]);
  773. ASSERT_EQ(read(pipefd[0], &result, 1), 1);
  774. waitpid(pid, &status, 0);
  775. ASSERT_TRUE(WIFEXITED(status));
  776. ASSERT_EQ(WEXITSTATUS(status), 0);
  777. if (result == 'U') {
  778. SKIP(free(handle); close(pipefd[0]);
  779. return, "Cannot create new user namespace");
  780. }
  781. if (result == 'M') {
  782. SKIP(free(handle); close(pipefd[0]);
  783. return, "Cannot set uid/gid mappings");
  784. }
  785. if (result == 'N') {
  786. SKIP(free(handle); close(pipefd[0]);
  787. return, "Cannot create new mount namespace");
  788. }
  789. /* Should fail with ESTALE since we're in a different user namespace */
  790. ASSERT_EQ(result, 'P');
  791. close(pipefd[0]);
  792. free(handle);
  793. }
  794. TEST(nsfs_user_cgroup_namespace_isolation)
  795. {
  796. struct file_handle *handle;
  797. int mount_id;
  798. int ret;
  799. int fd;
  800. int ns_fd;
  801. pid_t pid;
  802. int status;
  803. int pipefd[2];
  804. char result;
  805. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  806. ASSERT_NE(handle, NULL);
  807. /* Create pipe for communication */
  808. ASSERT_EQ(pipe(pipefd), 0);
  809. /* Get handle for current cgroup namespace */
  810. ns_fd = open("/proc/self/ns/cgroup", O_RDONLY);
  811. if (ns_fd < 0) {
  812. SKIP(free(handle); close(pipefd[0]); close(pipefd[1]);
  813. return, "cgroup namespace not available");
  814. }
  815. handle->handle_bytes = MAX_HANDLE_SZ;
  816. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  817. if (ret < 0 && errno == EOPNOTSUPP) {
  818. SKIP(free(handle); close(ns_fd); close(pipefd[0]);
  819. close(pipefd[1]);
  820. return, "nsfs doesn't support file handles");
  821. }
  822. ASSERT_EQ(ret, 0);
  823. close(ns_fd);
  824. pid = fork();
  825. ASSERT_GE(pid, 0);
  826. if (pid == 0) {
  827. /* Child process */
  828. close(pipefd[0]);
  829. /* First create new user namespace to drop privileges */
  830. ret = unshare(CLONE_NEWUSER);
  831. if (ret < 0) {
  832. write(pipefd[1], "U",
  833. 1); /* Unable to create user namespace */
  834. close(pipefd[1]);
  835. exit(0);
  836. }
  837. /* Write uid/gid mappings to maintain some capabilities */
  838. int uid_map_fd = open("/proc/self/uid_map", O_WRONLY);
  839. int gid_map_fd = open("/proc/self/gid_map", O_WRONLY);
  840. int setgroups_fd = open("/proc/self/setgroups", O_WRONLY);
  841. if (uid_map_fd < 0 || gid_map_fd < 0 || setgroups_fd < 0) {
  842. write(pipefd[1], "M", 1); /* Unable to set mappings */
  843. close(pipefd[1]);
  844. exit(0);
  845. }
  846. /* Disable setgroups to allow gid mapping */
  847. write(setgroups_fd, "deny", 4);
  848. close(setgroups_fd);
  849. /* Map current uid/gid to root in the new namespace */
  850. char mapping[64];
  851. snprintf(mapping, sizeof(mapping), "0 %d 1", getuid());
  852. write(uid_map_fd, mapping, strlen(mapping));
  853. close(uid_map_fd);
  854. snprintf(mapping, sizeof(mapping), "0 %d 1", getgid());
  855. write(gid_map_fd, mapping, strlen(mapping));
  856. close(gid_map_fd);
  857. /* Now create new cgroup namespace */
  858. ret = unshare(CLONE_NEWCGROUP);
  859. if (ret < 0) {
  860. write(pipefd[1], "N",
  861. 1); /* Unable to create cgroup namespace */
  862. close(pipefd[1]);
  863. exit(0);
  864. }
  865. /* Try to open parent's cgroup namespace handle from new user+cgroup namespace */
  866. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  867. if (fd >= 0) {
  868. /* Should NOT succeed - we're in a different user namespace */
  869. write(pipefd[1], "S", 1); /* Unexpected success */
  870. close(fd);
  871. } else if (errno == ESTALE) {
  872. /* Expected: Stale file handle */
  873. write(pipefd[1], "P", 1);
  874. } else {
  875. /* Other error */
  876. write(pipefd[1], "F", 1);
  877. }
  878. close(pipefd[1]);
  879. exit(0);
  880. }
  881. /* Parent process */
  882. close(pipefd[1]);
  883. ASSERT_EQ(read(pipefd[0], &result, 1), 1);
  884. waitpid(pid, &status, 0);
  885. ASSERT_TRUE(WIFEXITED(status));
  886. ASSERT_EQ(WEXITSTATUS(status), 0);
  887. if (result == 'U') {
  888. SKIP(free(handle); close(pipefd[0]);
  889. return, "Cannot create new user namespace");
  890. }
  891. if (result == 'M') {
  892. SKIP(free(handle); close(pipefd[0]);
  893. return, "Cannot set uid/gid mappings");
  894. }
  895. if (result == 'N') {
  896. SKIP(free(handle); close(pipefd[0]);
  897. return, "Cannot create new cgroup namespace");
  898. }
  899. /* Should fail with ESTALE since we're in a different user namespace */
  900. ASSERT_EQ(result, 'P');
  901. close(pipefd[0]);
  902. free(handle);
  903. }
  904. TEST(nsfs_user_pid_namespace_isolation)
  905. {
  906. struct file_handle *handle;
  907. int mount_id;
  908. int ret;
  909. int fd;
  910. int ns_fd;
  911. pid_t pid;
  912. int status;
  913. int pipefd[2];
  914. char result;
  915. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  916. ASSERT_NE(handle, NULL);
  917. /* Create pipe for communication */
  918. ASSERT_EQ(pipe(pipefd), 0);
  919. /* Get handle for current PID namespace */
  920. ns_fd = open("/proc/self/ns/pid", O_RDONLY);
  921. ASSERT_GE(ns_fd, 0);
  922. handle->handle_bytes = MAX_HANDLE_SZ;
  923. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  924. if (ret < 0 && errno == EOPNOTSUPP) {
  925. SKIP(free(handle); close(ns_fd); close(pipefd[0]);
  926. close(pipefd[1]);
  927. return, "nsfs doesn't support file handles");
  928. }
  929. ASSERT_EQ(ret, 0);
  930. close(ns_fd);
  931. pid = fork();
  932. ASSERT_GE(pid, 0);
  933. if (pid == 0) {
  934. /* Child process */
  935. close(pipefd[0]);
  936. /* First create new user namespace to drop privileges */
  937. ret = unshare(CLONE_NEWUSER);
  938. if (ret < 0) {
  939. write(pipefd[1], "U",
  940. 1); /* Unable to create user namespace */
  941. close(pipefd[1]);
  942. exit(0);
  943. }
  944. /* Write uid/gid mappings to maintain some capabilities */
  945. int uid_map_fd = open("/proc/self/uid_map", O_WRONLY);
  946. int gid_map_fd = open("/proc/self/gid_map", O_WRONLY);
  947. int setgroups_fd = open("/proc/self/setgroups", O_WRONLY);
  948. if (uid_map_fd < 0 || gid_map_fd < 0 || setgroups_fd < 0) {
  949. write(pipefd[1], "M", 1); /* Unable to set mappings */
  950. close(pipefd[1]);
  951. exit(0);
  952. }
  953. /* Disable setgroups to allow gid mapping */
  954. write(setgroups_fd, "deny", 4);
  955. close(setgroups_fd);
  956. /* Map current uid/gid to root in the new namespace */
  957. char mapping[64];
  958. snprintf(mapping, sizeof(mapping), "0 %d 1", getuid());
  959. write(uid_map_fd, mapping, strlen(mapping));
  960. close(uid_map_fd);
  961. snprintf(mapping, sizeof(mapping), "0 %d 1", getgid());
  962. write(gid_map_fd, mapping, strlen(mapping));
  963. close(gid_map_fd);
  964. /* Now create new PID namespace - requires fork to take effect */
  965. ret = unshare(CLONE_NEWPID);
  966. if (ret < 0) {
  967. write(pipefd[1], "N",
  968. 1); /* Unable to create PID namespace */
  969. close(pipefd[1]);
  970. exit(0);
  971. }
  972. /* Fork again for PID namespace to take effect */
  973. pid_t child_pid = fork();
  974. if (child_pid < 0) {
  975. write(pipefd[1], "N",
  976. 1); /* Unable to fork in PID namespace */
  977. close(pipefd[1]);
  978. exit(0);
  979. }
  980. if (child_pid == 0) {
  981. /* Grandchild in new PID namespace */
  982. /* Try to open parent's PID namespace handle from new user+pid namespace */
  983. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  984. if (fd >= 0) {
  985. /* Should NOT succeed - we're in a different user namespace */
  986. write(pipefd[1], "S",
  987. 1); /* Unexpected success */
  988. close(fd);
  989. } else if (errno == ESTALE) {
  990. /* Expected: Stale file handle */
  991. write(pipefd[1], "P", 1);
  992. } else {
  993. /* Other error */
  994. write(pipefd[1], "F", 1);
  995. }
  996. close(pipefd[1]);
  997. exit(0);
  998. }
  999. /* Wait for grandchild */
  1000. waitpid(child_pid, NULL, 0);
  1001. exit(0);
  1002. }
  1003. /* Parent process */
  1004. close(pipefd[1]);
  1005. ASSERT_EQ(read(pipefd[0], &result, 1), 1);
  1006. waitpid(pid, &status, 0);
  1007. ASSERT_TRUE(WIFEXITED(status));
  1008. ASSERT_EQ(WEXITSTATUS(status), 0);
  1009. if (result == 'U') {
  1010. SKIP(free(handle); close(pipefd[0]);
  1011. return, "Cannot create new user namespace");
  1012. }
  1013. if (result == 'M') {
  1014. SKIP(free(handle); close(pipefd[0]);
  1015. return, "Cannot set uid/gid mappings");
  1016. }
  1017. if (result == 'N') {
  1018. SKIP(free(handle); close(pipefd[0]);
  1019. return, "Cannot create new PID namespace");
  1020. }
  1021. /* Should fail with ESTALE since we're in a different user namespace */
  1022. ASSERT_EQ(result, 'P');
  1023. close(pipefd[0]);
  1024. free(handle);
  1025. }
  1026. TEST(nsfs_user_time_namespace_isolation)
  1027. {
  1028. struct file_handle *handle;
  1029. int mount_id;
  1030. int ret;
  1031. int fd;
  1032. int ns_fd;
  1033. pid_t pid;
  1034. int status;
  1035. int pipefd[2];
  1036. char result;
  1037. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  1038. ASSERT_NE(handle, NULL);
  1039. /* Create pipe for communication */
  1040. ASSERT_EQ(pipe(pipefd), 0);
  1041. /* Get handle for current time namespace */
  1042. ns_fd = open("/proc/self/ns/time", O_RDONLY);
  1043. if (ns_fd < 0) {
  1044. SKIP(free(handle); close(pipefd[0]); close(pipefd[1]);
  1045. return, "time namespace not available");
  1046. }
  1047. handle->handle_bytes = MAX_HANDLE_SZ;
  1048. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  1049. if (ret < 0 && errno == EOPNOTSUPP) {
  1050. SKIP(free(handle); close(ns_fd); close(pipefd[0]);
  1051. close(pipefd[1]);
  1052. return, "nsfs doesn't support file handles");
  1053. }
  1054. ASSERT_EQ(ret, 0);
  1055. close(ns_fd);
  1056. pid = fork();
  1057. ASSERT_GE(pid, 0);
  1058. if (pid == 0) {
  1059. /* Child process */
  1060. close(pipefd[0]);
  1061. /* First create new user namespace to drop privileges */
  1062. ret = unshare(CLONE_NEWUSER);
  1063. if (ret < 0) {
  1064. write(pipefd[1], "U",
  1065. 1); /* Unable to create user namespace */
  1066. close(pipefd[1]);
  1067. exit(0);
  1068. }
  1069. /* Write uid/gid mappings to maintain some capabilities */
  1070. int uid_map_fd = open("/proc/self/uid_map", O_WRONLY);
  1071. int gid_map_fd = open("/proc/self/gid_map", O_WRONLY);
  1072. int setgroups_fd = open("/proc/self/setgroups", O_WRONLY);
  1073. if (uid_map_fd < 0 || gid_map_fd < 0 || setgroups_fd < 0) {
  1074. write(pipefd[1], "M", 1); /* Unable to set mappings */
  1075. close(pipefd[1]);
  1076. exit(0);
  1077. }
  1078. /* Disable setgroups to allow gid mapping */
  1079. write(setgroups_fd, "deny", 4);
  1080. close(setgroups_fd);
  1081. /* Map current uid/gid to root in the new namespace */
  1082. char mapping[64];
  1083. snprintf(mapping, sizeof(mapping), "0 %d 1", getuid());
  1084. write(uid_map_fd, mapping, strlen(mapping));
  1085. close(uid_map_fd);
  1086. snprintf(mapping, sizeof(mapping), "0 %d 1", getgid());
  1087. write(gid_map_fd, mapping, strlen(mapping));
  1088. close(gid_map_fd);
  1089. /* Now create new time namespace - requires fork to take effect */
  1090. ret = unshare(CLONE_NEWTIME);
  1091. if (ret < 0) {
  1092. write(pipefd[1], "N",
  1093. 1); /* Unable to create time namespace */
  1094. close(pipefd[1]);
  1095. exit(0);
  1096. }
  1097. /* Fork again for time namespace to take effect */
  1098. pid_t child_pid = fork();
  1099. if (child_pid < 0) {
  1100. write(pipefd[1], "N",
  1101. 1); /* Unable to fork in time namespace */
  1102. close(pipefd[1]);
  1103. exit(0);
  1104. }
  1105. if (child_pid == 0) {
  1106. /* Grandchild in new time namespace */
  1107. /* Try to open parent's time namespace handle from new user+time namespace */
  1108. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
  1109. if (fd >= 0) {
  1110. /* Should NOT succeed - we're in a different user namespace */
  1111. write(pipefd[1], "S",
  1112. 1); /* Unexpected success */
  1113. close(fd);
  1114. } else if (errno == ESTALE) {
  1115. /* Expected: Stale file handle */
  1116. write(pipefd[1], "P", 1);
  1117. } else {
  1118. /* Other error */
  1119. write(pipefd[1], "F", 1);
  1120. }
  1121. close(pipefd[1]);
  1122. exit(0);
  1123. }
  1124. /* Wait for grandchild */
  1125. waitpid(child_pid, NULL, 0);
  1126. exit(0);
  1127. }
  1128. /* Parent process */
  1129. close(pipefd[1]);
  1130. ASSERT_EQ(read(pipefd[0], &result, 1), 1);
  1131. waitpid(pid, &status, 0);
  1132. ASSERT_TRUE(WIFEXITED(status));
  1133. ASSERT_EQ(WEXITSTATUS(status), 0);
  1134. if (result == 'U') {
  1135. SKIP(free(handle); close(pipefd[0]);
  1136. return, "Cannot create new user namespace");
  1137. }
  1138. if (result == 'M') {
  1139. SKIP(free(handle); close(pipefd[0]);
  1140. return, "Cannot set uid/gid mappings");
  1141. }
  1142. if (result == 'N') {
  1143. SKIP(free(handle); close(pipefd[0]);
  1144. return, "Cannot create new time namespace");
  1145. }
  1146. /* Should fail with ESTALE since we're in a different user namespace */
  1147. ASSERT_EQ(result, 'P');
  1148. close(pipefd[0]);
  1149. free(handle);
  1150. }
  1151. TEST(nsfs_open_flags)
  1152. {
  1153. struct file_handle *handle;
  1154. int mount_id;
  1155. int ret;
  1156. int fd;
  1157. int ns_fd;
  1158. handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
  1159. ASSERT_NE(handle, NULL);
  1160. /* Open a namespace file descriptor */
  1161. ns_fd = open("/proc/self/ns/net", O_RDONLY);
  1162. ASSERT_GE(ns_fd, 0);
  1163. /* Get handle for the namespace */
  1164. handle->handle_bytes = MAX_HANDLE_SZ;
  1165. ret = name_to_handle_at(ns_fd, "", handle, &mount_id, AT_EMPTY_PATH);
  1166. if (ret < 0 && errno == EOPNOTSUPP) {
  1167. SKIP(free(handle); close(ns_fd);
  1168. return, "nsfs doesn't support file handles");
  1169. }
  1170. ASSERT_EQ(ret, 0);
  1171. ASSERT_GT(handle->handle_bytes, 0);
  1172. /* Test invalid flags that should fail */
  1173. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_WRONLY);
  1174. ASSERT_LT(fd, 0);
  1175. ASSERT_EQ(errno, EPERM);
  1176. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDWR);
  1177. ASSERT_LT(fd, 0);
  1178. ASSERT_EQ(errno, EPERM);
  1179. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_TRUNC);
  1180. ASSERT_LT(fd, 0);
  1181. ASSERT_EQ(errno, EPERM);
  1182. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_DIRECT);
  1183. ASSERT_LT(fd, 0);
  1184. ASSERT_EQ(errno, EINVAL);
  1185. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_TMPFILE);
  1186. ASSERT_LT(fd, 0);
  1187. ASSERT_EQ(errno, EINVAL);
  1188. fd = open_by_handle_at(FD_NSFS_ROOT, handle, O_DIRECTORY);
  1189. ASSERT_LT(fd, 0);
  1190. ASSERT_EQ(errno, ENOTDIR);
  1191. close(ns_fd);
  1192. free(handle);
  1193. }
  1194. TEST_HARNESS_MAIN