mount_setattr_test.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <sched.h>
  4. #include <stdio.h>
  5. #include <errno.h>
  6. #include <pthread.h>
  7. #include <string.h>
  8. #include <sys/stat.h>
  9. #include <sys/types.h>
  10. #include <sys/mount.h>
  11. #include <sys/wait.h>
  12. #include <sys/vfs.h>
  13. #include <sys/statvfs.h>
  14. #include <sys/sysinfo.h>
  15. #include <stdlib.h>
  16. #include <unistd.h>
  17. #include <fcntl.h>
  18. #include <grp.h>
  19. #include <stdbool.h>
  20. #include <stdarg.h>
  21. #include <linux/mount.h>
  22. #include "../kselftest_harness.h"
  23. #ifndef CLONE_NEWNS
  24. #define CLONE_NEWNS 0x00020000
  25. #endif
  26. #ifndef CLONE_NEWUSER
  27. #define CLONE_NEWUSER 0x10000000
  28. #endif
  29. #ifndef MS_REC
  30. #define MS_REC 16384
  31. #endif
  32. #ifndef MS_RELATIME
  33. #define MS_RELATIME (1 << 21)
  34. #endif
  35. #ifndef MS_STRICTATIME
  36. #define MS_STRICTATIME (1 << 24)
  37. #endif
  38. #ifndef MOUNT_ATTR_RDONLY
  39. #define MOUNT_ATTR_RDONLY 0x00000001
  40. #endif
  41. #ifndef MOUNT_ATTR_NOSUID
  42. #define MOUNT_ATTR_NOSUID 0x00000002
  43. #endif
  44. #ifndef MOUNT_ATTR_NOEXEC
  45. #define MOUNT_ATTR_NOEXEC 0x00000008
  46. #endif
  47. #ifndef MOUNT_ATTR_NODIRATIME
  48. #define MOUNT_ATTR_NODIRATIME 0x00000080
  49. #endif
  50. #ifndef MOUNT_ATTR__ATIME
  51. #define MOUNT_ATTR__ATIME 0x00000070
  52. #endif
  53. #ifndef MOUNT_ATTR_RELATIME
  54. #define MOUNT_ATTR_RELATIME 0x00000000
  55. #endif
  56. #ifndef MOUNT_ATTR_NOATIME
  57. #define MOUNT_ATTR_NOATIME 0x00000010
  58. #endif
  59. #ifndef MOUNT_ATTR_STRICTATIME
  60. #define MOUNT_ATTR_STRICTATIME 0x00000020
  61. #endif
  62. #ifndef AT_RECURSIVE
  63. #define AT_RECURSIVE 0x8000
  64. #endif
  65. #ifndef MS_SHARED
  66. #define MS_SHARED (1 << 20)
  67. #endif
  68. #define DEFAULT_THREADS 4
  69. #define ptr_to_int(p) ((int)((intptr_t)(p)))
  70. #define int_to_ptr(u) ((void *)((intptr_t)(u)))
  71. #ifndef __NR_mount_setattr
  72. #if defined __alpha__
  73. #define __NR_mount_setattr 552
  74. #elif defined _MIPS_SIM
  75. #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
  76. #define __NR_mount_setattr (442 + 4000)
  77. #endif
  78. #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
  79. #define __NR_mount_setattr (442 + 6000)
  80. #endif
  81. #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
  82. #define __NR_mount_setattr (442 + 5000)
  83. #endif
  84. #elif defined __ia64__
  85. #define __NR_mount_setattr (442 + 1024)
  86. #else
  87. #define __NR_mount_setattr 442
  88. #endif
  89. #endif
  90. #ifndef __NR_open_tree
  91. #if defined __alpha__
  92. #define __NR_open_tree 538
  93. #elif defined _MIPS_SIM
  94. #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
  95. #define __NR_open_tree 4428
  96. #endif
  97. #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
  98. #define __NR_open_tree 6428
  99. #endif
  100. #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
  101. #define __NR_open_tree 5428
  102. #endif
  103. #elif defined __ia64__
  104. #define __NR_open_tree (428 + 1024)
  105. #else
  106. #define __NR_open_tree 428
  107. #endif
  108. #endif
  109. #ifndef MOUNT_ATTR_IDMAP
  110. #define MOUNT_ATTR_IDMAP 0x00100000
  111. #endif
  112. #ifndef MOUNT_ATTR_NOSYMFOLLOW
  113. #define MOUNT_ATTR_NOSYMFOLLOW 0x00200000
  114. #endif
  115. static inline int sys_mount_setattr(int dfd, const char *path, unsigned int flags,
  116. struct mount_attr *attr, size_t size)
  117. {
  118. return syscall(__NR_mount_setattr, dfd, path, flags, attr, size);
  119. }
  120. #ifndef OPEN_TREE_CLONE
  121. #define OPEN_TREE_CLONE 1
  122. #endif
  123. #ifndef OPEN_TREE_CLOEXEC
  124. #define OPEN_TREE_CLOEXEC O_CLOEXEC
  125. #endif
  126. #ifndef AT_RECURSIVE
  127. #define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
  128. #endif
  129. static inline int sys_open_tree(int dfd, const char *filename, unsigned int flags)
  130. {
  131. return syscall(__NR_open_tree, dfd, filename, flags);
  132. }
  133. static ssize_t write_nointr(int fd, const void *buf, size_t count)
  134. {
  135. ssize_t ret;
  136. do {
  137. ret = write(fd, buf, count);
  138. } while (ret < 0 && errno == EINTR);
  139. return ret;
  140. }
  141. static int write_file(const char *path, const void *buf, size_t count)
  142. {
  143. int fd;
  144. ssize_t ret;
  145. fd = open(path, O_WRONLY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW);
  146. if (fd < 0)
  147. return -1;
  148. ret = write_nointr(fd, buf, count);
  149. close(fd);
  150. if (ret < 0 || (size_t)ret != count)
  151. return -1;
  152. return 0;
  153. }
  154. static int create_and_enter_userns(void)
  155. {
  156. uid_t uid;
  157. gid_t gid;
  158. char map[100];
  159. uid = getuid();
  160. gid = getgid();
  161. if (unshare(CLONE_NEWUSER))
  162. return -1;
  163. if (write_file("/proc/self/setgroups", "deny", sizeof("deny") - 1) &&
  164. errno != ENOENT)
  165. return -1;
  166. snprintf(map, sizeof(map), "0 %d 1", uid);
  167. if (write_file("/proc/self/uid_map", map, strlen(map)))
  168. return -1;
  169. snprintf(map, sizeof(map), "0 %d 1", gid);
  170. if (write_file("/proc/self/gid_map", map, strlen(map)))
  171. return -1;
  172. if (setgid(0))
  173. return -1;
  174. if (setuid(0))
  175. return -1;
  176. return 0;
  177. }
  178. static int prepare_unpriv_mountns(void)
  179. {
  180. if (create_and_enter_userns())
  181. return -1;
  182. if (unshare(CLONE_NEWNS))
  183. return -1;
  184. if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0))
  185. return -1;
  186. return 0;
  187. }
  188. #ifndef ST_NOSYMFOLLOW
  189. #define ST_NOSYMFOLLOW 0x2000 /* do not follow symlinks */
  190. #endif
  191. static int read_mnt_flags(const char *path)
  192. {
  193. int ret;
  194. struct statvfs stat;
  195. unsigned int mnt_flags;
  196. ret = statvfs(path, &stat);
  197. if (ret != 0)
  198. return -EINVAL;
  199. if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | ST_NOEXEC |
  200. ST_NOATIME | ST_NODIRATIME | ST_RELATIME |
  201. ST_SYNCHRONOUS | ST_MANDLOCK | ST_NOSYMFOLLOW))
  202. return -EINVAL;
  203. mnt_flags = 0;
  204. if (stat.f_flag & ST_RDONLY)
  205. mnt_flags |= MS_RDONLY;
  206. if (stat.f_flag & ST_NOSUID)
  207. mnt_flags |= MS_NOSUID;
  208. if (stat.f_flag & ST_NODEV)
  209. mnt_flags |= MS_NODEV;
  210. if (stat.f_flag & ST_NOEXEC)
  211. mnt_flags |= MS_NOEXEC;
  212. if (stat.f_flag & ST_NOATIME)
  213. mnt_flags |= MS_NOATIME;
  214. if (stat.f_flag & ST_NODIRATIME)
  215. mnt_flags |= MS_NODIRATIME;
  216. if (stat.f_flag & ST_RELATIME)
  217. mnt_flags |= MS_RELATIME;
  218. if (stat.f_flag & ST_SYNCHRONOUS)
  219. mnt_flags |= MS_SYNCHRONOUS;
  220. if (stat.f_flag & ST_MANDLOCK)
  221. mnt_flags |= ST_MANDLOCK;
  222. if (stat.f_flag & ST_NOSYMFOLLOW)
  223. mnt_flags |= ST_NOSYMFOLLOW;
  224. return mnt_flags;
  225. }
  226. static char *get_field(char *src, int nfields)
  227. {
  228. int i;
  229. char *p = src;
  230. for (i = 0; i < nfields; i++) {
  231. while (*p && *p != ' ' && *p != '\t')
  232. p++;
  233. if (!*p)
  234. break;
  235. p++;
  236. }
  237. return p;
  238. }
  239. static void null_endofword(char *word)
  240. {
  241. while (*word && *word != ' ' && *word != '\t')
  242. word++;
  243. *word = '\0';
  244. }
  245. static bool is_shared_mount(const char *path)
  246. {
  247. size_t len = 0;
  248. char *line = NULL;
  249. FILE *f = NULL;
  250. f = fopen("/proc/self/mountinfo", "re");
  251. if (!f)
  252. return false;
  253. while (getline(&line, &len, f) != -1) {
  254. char *opts, *target;
  255. target = get_field(line, 4);
  256. if (!target)
  257. continue;
  258. opts = get_field(target, 2);
  259. if (!opts)
  260. continue;
  261. null_endofword(target);
  262. if (strcmp(target, path) != 0)
  263. continue;
  264. null_endofword(opts);
  265. if (strstr(opts, "shared:"))
  266. return true;
  267. }
  268. free(line);
  269. fclose(f);
  270. return false;
  271. }
  272. static void *mount_setattr_thread(void *data)
  273. {
  274. struct mount_attr attr = {
  275. .attr_set = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID,
  276. .attr_clr = 0,
  277. .propagation = MS_SHARED,
  278. };
  279. if (sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)))
  280. pthread_exit(int_to_ptr(-1));
  281. pthread_exit(int_to_ptr(0));
  282. }
  283. /* Attempt to de-conflict with the selftests tree. */
  284. #ifndef SKIP
  285. #define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__)
  286. #endif
  287. static bool mount_setattr_supported(void)
  288. {
  289. int ret;
  290. ret = sys_mount_setattr(-EBADF, "", AT_EMPTY_PATH, NULL, 0);
  291. if (ret < 0 && errno == ENOSYS)
  292. return false;
  293. return true;
  294. }
  295. FIXTURE(mount_setattr) {
  296. };
  297. #define NOSYMFOLLOW_TARGET "/mnt/A/AA/data"
  298. #define NOSYMFOLLOW_SYMLINK "/mnt/A/AA/symlink"
  299. FIXTURE_SETUP(mount_setattr)
  300. {
  301. int fd = -EBADF;
  302. if (!mount_setattr_supported())
  303. SKIP(return, "mount_setattr syscall not supported");
  304. ASSERT_EQ(prepare_unpriv_mountns(), 0);
  305. (void)umount2("/mnt", MNT_DETACH);
  306. (void)umount2("/tmp", MNT_DETACH);
  307. ASSERT_EQ(mount("testing", "/tmp", "tmpfs", MS_NOATIME | MS_NODEV,
  308. "size=100000,mode=700"), 0);
  309. ASSERT_EQ(mkdir("/tmp/B", 0777), 0);
  310. ASSERT_EQ(mount("testing", "/tmp/B", "tmpfs", MS_NOATIME | MS_NODEV,
  311. "size=100000,mode=700"), 0);
  312. ASSERT_EQ(mkdir("/tmp/B/BB", 0777), 0);
  313. ASSERT_EQ(mount("testing", "/tmp/B/BB", "tmpfs", MS_NOATIME | MS_NODEV,
  314. "size=100000,mode=700"), 0);
  315. ASSERT_EQ(mount("testing", "/mnt", "tmpfs", MS_NOATIME | MS_NODEV,
  316. "size=100000,mode=700"), 0);
  317. ASSERT_EQ(mkdir("/mnt/A", 0777), 0);
  318. ASSERT_EQ(mount("testing", "/mnt/A", "tmpfs", MS_NOATIME | MS_NODEV,
  319. "size=100000,mode=700"), 0);
  320. ASSERT_EQ(mkdir("/mnt/A/AA", 0777), 0);
  321. ASSERT_EQ(mount("/tmp", "/mnt/A/AA", NULL, MS_BIND | MS_REC, NULL), 0);
  322. ASSERT_EQ(mkdir("/mnt/B", 0777), 0);
  323. ASSERT_EQ(mount("testing", "/mnt/B", "ramfs",
  324. MS_NOATIME | MS_NODEV | MS_NOSUID, 0), 0);
  325. ASSERT_EQ(mkdir("/mnt/B/BB", 0777), 0);
  326. ASSERT_EQ(mount("testing", "/tmp/B/BB", "devpts",
  327. MS_RELATIME | MS_NOEXEC | MS_RDONLY, 0), 0);
  328. fd = creat(NOSYMFOLLOW_TARGET, O_RDWR | O_CLOEXEC);
  329. ASSERT_GT(fd, 0);
  330. ASSERT_EQ(symlink(NOSYMFOLLOW_TARGET, NOSYMFOLLOW_SYMLINK), 0);
  331. ASSERT_EQ(close(fd), 0);
  332. }
  333. FIXTURE_TEARDOWN(mount_setattr)
  334. {
  335. if (!mount_setattr_supported())
  336. SKIP(return, "mount_setattr syscall not supported");
  337. (void)umount2("/mnt/A", MNT_DETACH);
  338. (void)umount2("/tmp", MNT_DETACH);
  339. }
  340. TEST_F(mount_setattr, invalid_attributes)
  341. {
  342. struct mount_attr invalid_attr = {
  343. .attr_set = (1U << 31),
  344. };
  345. if (!mount_setattr_supported())
  346. SKIP(return, "mount_setattr syscall not supported");
  347. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &invalid_attr,
  348. sizeof(invalid_attr)), 0);
  349. invalid_attr.attr_set = 0;
  350. invalid_attr.attr_clr = (1U << 31);
  351. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &invalid_attr,
  352. sizeof(invalid_attr)), 0);
  353. invalid_attr.attr_clr = 0;
  354. invalid_attr.propagation = (1U << 31);
  355. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &invalid_attr,
  356. sizeof(invalid_attr)), 0);
  357. invalid_attr.attr_set = (1U << 31);
  358. invalid_attr.attr_clr = (1U << 31);
  359. invalid_attr.propagation = (1U << 31);
  360. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &invalid_attr,
  361. sizeof(invalid_attr)), 0);
  362. ASSERT_NE(sys_mount_setattr(-1, "mnt/A", AT_RECURSIVE, &invalid_attr,
  363. sizeof(invalid_attr)), 0);
  364. }
  365. TEST_F(mount_setattr, extensibility)
  366. {
  367. unsigned int old_flags = 0, new_flags = 0, expected_flags = 0;
  368. char *s = "dummy";
  369. struct mount_attr invalid_attr = {};
  370. struct mount_attr_large {
  371. struct mount_attr attr1;
  372. struct mount_attr attr2;
  373. struct mount_attr attr3;
  374. } large_attr = {};
  375. if (!mount_setattr_supported())
  376. SKIP(return, "mount_setattr syscall not supported");
  377. old_flags = read_mnt_flags("/mnt/A");
  378. ASSERT_GT(old_flags, 0);
  379. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, NULL,
  380. sizeof(invalid_attr)), 0);
  381. ASSERT_EQ(errno, EFAULT);
  382. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, (void *)s,
  383. sizeof(invalid_attr)), 0);
  384. ASSERT_EQ(errno, EINVAL);
  385. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &invalid_attr, 0), 0);
  386. ASSERT_EQ(errno, EINVAL);
  387. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &invalid_attr,
  388. sizeof(invalid_attr) / 2), 0);
  389. ASSERT_EQ(errno, EINVAL);
  390. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &invalid_attr,
  391. sizeof(invalid_attr) / 2), 0);
  392. ASSERT_EQ(errno, EINVAL);
  393. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE,
  394. (void *)&large_attr, sizeof(large_attr)), 0);
  395. large_attr.attr3.attr_set = MOUNT_ATTR_RDONLY;
  396. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE,
  397. (void *)&large_attr, sizeof(large_attr)), 0);
  398. large_attr.attr3.attr_set = 0;
  399. large_attr.attr1.attr_set = MOUNT_ATTR_RDONLY;
  400. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE,
  401. (void *)&large_attr, sizeof(large_attr)), 0);
  402. expected_flags = old_flags;
  403. expected_flags |= MS_RDONLY;
  404. new_flags = read_mnt_flags("/mnt/A");
  405. ASSERT_EQ(new_flags, expected_flags);
  406. new_flags = read_mnt_flags("/mnt/A/AA");
  407. ASSERT_EQ(new_flags, expected_flags);
  408. new_flags = read_mnt_flags("/mnt/A/AA/B");
  409. ASSERT_EQ(new_flags, expected_flags);
  410. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  411. ASSERT_EQ(new_flags, expected_flags);
  412. }
  413. TEST_F(mount_setattr, basic)
  414. {
  415. unsigned int old_flags = 0, new_flags = 0, expected_flags = 0;
  416. struct mount_attr attr = {
  417. .attr_set = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOEXEC | MOUNT_ATTR_RELATIME,
  418. .attr_clr = MOUNT_ATTR__ATIME,
  419. };
  420. if (!mount_setattr_supported())
  421. SKIP(return, "mount_setattr syscall not supported");
  422. old_flags = read_mnt_flags("/mnt/A");
  423. ASSERT_GT(old_flags, 0);
  424. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", 0, &attr, sizeof(attr)), 0);
  425. expected_flags = old_flags;
  426. expected_flags |= MS_RDONLY;
  427. expected_flags |= MS_NOEXEC;
  428. expected_flags &= ~MS_NOATIME;
  429. expected_flags |= MS_RELATIME;
  430. new_flags = read_mnt_flags("/mnt/A");
  431. ASSERT_EQ(new_flags, expected_flags);
  432. new_flags = read_mnt_flags("/mnt/A/AA");
  433. ASSERT_EQ(new_flags, old_flags);
  434. new_flags = read_mnt_flags("/mnt/A/AA/B");
  435. ASSERT_EQ(new_flags, old_flags);
  436. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  437. ASSERT_EQ(new_flags, old_flags);
  438. }
  439. TEST_F(mount_setattr, basic_recursive)
  440. {
  441. int fd;
  442. unsigned int old_flags = 0, new_flags = 0, expected_flags = 0;
  443. struct mount_attr attr = {
  444. .attr_set = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOEXEC | MOUNT_ATTR_RELATIME,
  445. .attr_clr = MOUNT_ATTR__ATIME,
  446. };
  447. if (!mount_setattr_supported())
  448. SKIP(return, "mount_setattr syscall not supported");
  449. old_flags = read_mnt_flags("/mnt/A");
  450. ASSERT_GT(old_flags, 0);
  451. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  452. expected_flags = old_flags;
  453. expected_flags |= MS_RDONLY;
  454. expected_flags |= MS_NOEXEC;
  455. expected_flags &= ~MS_NOATIME;
  456. expected_flags |= MS_RELATIME;
  457. new_flags = read_mnt_flags("/mnt/A");
  458. ASSERT_EQ(new_flags, expected_flags);
  459. new_flags = read_mnt_flags("/mnt/A/AA");
  460. ASSERT_EQ(new_flags, expected_flags);
  461. new_flags = read_mnt_flags("/mnt/A/AA/B");
  462. ASSERT_EQ(new_flags, expected_flags);
  463. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  464. ASSERT_EQ(new_flags, expected_flags);
  465. memset(&attr, 0, sizeof(attr));
  466. attr.attr_clr = MOUNT_ATTR_RDONLY;
  467. attr.propagation = MS_SHARED;
  468. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  469. expected_flags &= ~MS_RDONLY;
  470. new_flags = read_mnt_flags("/mnt/A");
  471. ASSERT_EQ(new_flags, expected_flags);
  472. ASSERT_EQ(is_shared_mount("/mnt/A"), true);
  473. new_flags = read_mnt_flags("/mnt/A/AA");
  474. ASSERT_EQ(new_flags, expected_flags);
  475. ASSERT_EQ(is_shared_mount("/mnt/A/AA"), true);
  476. new_flags = read_mnt_flags("/mnt/A/AA/B");
  477. ASSERT_EQ(new_flags, expected_flags);
  478. ASSERT_EQ(is_shared_mount("/mnt/A/AA/B"), true);
  479. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  480. ASSERT_EQ(new_flags, expected_flags);
  481. ASSERT_EQ(is_shared_mount("/mnt/A/AA/B/BB"), true);
  482. fd = open("/mnt/A/AA/B/b", O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL, 0777);
  483. ASSERT_GE(fd, 0);
  484. /*
  485. * We're holding a fd open for writing so this needs to fail somewhere
  486. * in the middle and the mount options need to be unchanged.
  487. */
  488. attr.attr_set = MOUNT_ATTR_RDONLY;
  489. ASSERT_LT(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  490. new_flags = read_mnt_flags("/mnt/A");
  491. ASSERT_EQ(new_flags, expected_flags);
  492. ASSERT_EQ(is_shared_mount("/mnt/A"), true);
  493. new_flags = read_mnt_flags("/mnt/A/AA");
  494. ASSERT_EQ(new_flags, expected_flags);
  495. ASSERT_EQ(is_shared_mount("/mnt/A/AA"), true);
  496. new_flags = read_mnt_flags("/mnt/A/AA/B");
  497. ASSERT_EQ(new_flags, expected_flags);
  498. ASSERT_EQ(is_shared_mount("/mnt/A/AA/B"), true);
  499. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  500. ASSERT_EQ(new_flags, expected_flags);
  501. ASSERT_EQ(is_shared_mount("/mnt/A/AA/B/BB"), true);
  502. EXPECT_EQ(close(fd), 0);
  503. }
  504. TEST_F(mount_setattr, mount_has_writers)
  505. {
  506. int fd, dfd;
  507. unsigned int old_flags = 0, new_flags = 0;
  508. struct mount_attr attr = {
  509. .attr_set = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOEXEC | MOUNT_ATTR_RELATIME,
  510. .attr_clr = MOUNT_ATTR__ATIME,
  511. .propagation = MS_SHARED,
  512. };
  513. if (!mount_setattr_supported())
  514. SKIP(return, "mount_setattr syscall not supported");
  515. old_flags = read_mnt_flags("/mnt/A");
  516. ASSERT_GT(old_flags, 0);
  517. fd = open("/mnt/A/AA/B/b", O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL, 0777);
  518. ASSERT_GE(fd, 0);
  519. /*
  520. * We're holding a fd open to a mount somwhere in the middle so this
  521. * needs to fail somewhere in the middle. After this the mount options
  522. * need to be unchanged.
  523. */
  524. ASSERT_LT(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  525. new_flags = read_mnt_flags("/mnt/A");
  526. ASSERT_EQ(new_flags, old_flags);
  527. ASSERT_EQ(is_shared_mount("/mnt/A"), false);
  528. new_flags = read_mnt_flags("/mnt/A/AA");
  529. ASSERT_EQ(new_flags, old_flags);
  530. ASSERT_EQ(is_shared_mount("/mnt/A/AA"), false);
  531. new_flags = read_mnt_flags("/mnt/A/AA/B");
  532. ASSERT_EQ(new_flags, old_flags);
  533. ASSERT_EQ(is_shared_mount("/mnt/A/AA/B"), false);
  534. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  535. ASSERT_EQ(new_flags, old_flags);
  536. ASSERT_EQ(is_shared_mount("/mnt/A/AA/B/BB"), false);
  537. dfd = open("/mnt/A/AA/B", O_DIRECTORY | O_CLOEXEC);
  538. ASSERT_GE(dfd, 0);
  539. EXPECT_EQ(fsync(dfd), 0);
  540. EXPECT_EQ(close(dfd), 0);
  541. EXPECT_EQ(fsync(fd), 0);
  542. EXPECT_EQ(close(fd), 0);
  543. /* All writers are gone so this should succeed. */
  544. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  545. }
  546. TEST_F(mount_setattr, mixed_mount_options)
  547. {
  548. unsigned int old_flags1 = 0, old_flags2 = 0, new_flags = 0, expected_flags = 0;
  549. struct mount_attr attr = {
  550. .attr_clr = MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID | MOUNT_ATTR_NOEXEC | MOUNT_ATTR__ATIME,
  551. .attr_set = MOUNT_ATTR_RELATIME,
  552. };
  553. if (!mount_setattr_supported())
  554. SKIP(return, "mount_setattr syscall not supported");
  555. old_flags1 = read_mnt_flags("/mnt/B");
  556. ASSERT_GT(old_flags1, 0);
  557. old_flags2 = read_mnt_flags("/mnt/B/BB");
  558. ASSERT_GT(old_flags2, 0);
  559. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/B", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  560. expected_flags = old_flags2;
  561. expected_flags &= ~(MS_RDONLY | MS_NOEXEC | MS_NOATIME | MS_NOSUID);
  562. expected_flags |= MS_RELATIME;
  563. new_flags = read_mnt_flags("/mnt/B");
  564. ASSERT_EQ(new_flags, expected_flags);
  565. expected_flags = old_flags2;
  566. expected_flags &= ~(MS_RDONLY | MS_NOEXEC | MS_NOATIME | MS_NOSUID);
  567. expected_flags |= MS_RELATIME;
  568. new_flags = read_mnt_flags("/mnt/B/BB");
  569. ASSERT_EQ(new_flags, expected_flags);
  570. }
  571. TEST_F(mount_setattr, time_changes)
  572. {
  573. unsigned int old_flags = 0, new_flags = 0, expected_flags = 0;
  574. struct mount_attr attr = {
  575. .attr_set = MOUNT_ATTR_NODIRATIME | MOUNT_ATTR_NOATIME,
  576. };
  577. if (!mount_setattr_supported())
  578. SKIP(return, "mount_setattr syscall not supported");
  579. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  580. attr.attr_set = MOUNT_ATTR_STRICTATIME;
  581. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  582. attr.attr_set = MOUNT_ATTR_STRICTATIME | MOUNT_ATTR_NOATIME;
  583. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  584. attr.attr_set = MOUNT_ATTR_STRICTATIME | MOUNT_ATTR_NOATIME;
  585. attr.attr_clr = MOUNT_ATTR__ATIME;
  586. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  587. attr.attr_set = 0;
  588. attr.attr_clr = MOUNT_ATTR_STRICTATIME;
  589. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  590. attr.attr_clr = MOUNT_ATTR_NOATIME;
  591. ASSERT_NE(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  592. old_flags = read_mnt_flags("/mnt/A");
  593. ASSERT_GT(old_flags, 0);
  594. attr.attr_set = MOUNT_ATTR_NODIRATIME | MOUNT_ATTR_NOATIME;
  595. attr.attr_clr = MOUNT_ATTR__ATIME;
  596. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  597. expected_flags = old_flags;
  598. expected_flags |= MS_NOATIME;
  599. expected_flags |= MS_NODIRATIME;
  600. new_flags = read_mnt_flags("/mnt/A");
  601. ASSERT_EQ(new_flags, expected_flags);
  602. new_flags = read_mnt_flags("/mnt/A/AA");
  603. ASSERT_EQ(new_flags, expected_flags);
  604. new_flags = read_mnt_flags("/mnt/A/AA/B");
  605. ASSERT_EQ(new_flags, expected_flags);
  606. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  607. ASSERT_EQ(new_flags, expected_flags);
  608. memset(&attr, 0, sizeof(attr));
  609. attr.attr_set &= ~MOUNT_ATTR_NOATIME;
  610. attr.attr_set |= MOUNT_ATTR_RELATIME;
  611. attr.attr_clr |= MOUNT_ATTR__ATIME;
  612. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  613. expected_flags &= ~MS_NOATIME;
  614. expected_flags |= MS_RELATIME;
  615. new_flags = read_mnt_flags("/mnt/A");
  616. ASSERT_EQ(new_flags, expected_flags);
  617. new_flags = read_mnt_flags("/mnt/A/AA");
  618. ASSERT_EQ(new_flags, expected_flags);
  619. new_flags = read_mnt_flags("/mnt/A/AA/B");
  620. ASSERT_EQ(new_flags, expected_flags);
  621. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  622. ASSERT_EQ(new_flags, expected_flags);
  623. memset(&attr, 0, sizeof(attr));
  624. attr.attr_set &= ~MOUNT_ATTR_RELATIME;
  625. attr.attr_set |= MOUNT_ATTR_STRICTATIME;
  626. attr.attr_clr |= MOUNT_ATTR__ATIME;
  627. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  628. expected_flags &= ~MS_RELATIME;
  629. new_flags = read_mnt_flags("/mnt/A");
  630. ASSERT_EQ(new_flags, expected_flags);
  631. new_flags = read_mnt_flags("/mnt/A/AA");
  632. ASSERT_EQ(new_flags, expected_flags);
  633. new_flags = read_mnt_flags("/mnt/A/AA/B");
  634. ASSERT_EQ(new_flags, expected_flags);
  635. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  636. ASSERT_EQ(new_flags, expected_flags);
  637. memset(&attr, 0, sizeof(attr));
  638. attr.attr_set &= ~MOUNT_ATTR_STRICTATIME;
  639. attr.attr_set |= MOUNT_ATTR_NOATIME;
  640. attr.attr_clr |= MOUNT_ATTR__ATIME;
  641. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  642. expected_flags |= MS_NOATIME;
  643. new_flags = read_mnt_flags("/mnt/A");
  644. ASSERT_EQ(new_flags, expected_flags);
  645. new_flags = read_mnt_flags("/mnt/A/AA");
  646. ASSERT_EQ(new_flags, expected_flags);
  647. new_flags = read_mnt_flags("/mnt/A/AA/B");
  648. ASSERT_EQ(new_flags, expected_flags);
  649. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  650. ASSERT_EQ(new_flags, expected_flags);
  651. memset(&attr, 0, sizeof(attr));
  652. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  653. new_flags = read_mnt_flags("/mnt/A");
  654. ASSERT_EQ(new_flags, expected_flags);
  655. new_flags = read_mnt_flags("/mnt/A/AA");
  656. ASSERT_EQ(new_flags, expected_flags);
  657. new_flags = read_mnt_flags("/mnt/A/AA/B");
  658. ASSERT_EQ(new_flags, expected_flags);
  659. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  660. ASSERT_EQ(new_flags, expected_flags);
  661. memset(&attr, 0, sizeof(attr));
  662. attr.attr_clr = MOUNT_ATTR_NODIRATIME;
  663. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  664. expected_flags &= ~MS_NODIRATIME;
  665. new_flags = read_mnt_flags("/mnt/A");
  666. ASSERT_EQ(new_flags, expected_flags);
  667. new_flags = read_mnt_flags("/mnt/A/AA");
  668. ASSERT_EQ(new_flags, expected_flags);
  669. new_flags = read_mnt_flags("/mnt/A/AA/B");
  670. ASSERT_EQ(new_flags, expected_flags);
  671. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  672. ASSERT_EQ(new_flags, expected_flags);
  673. }
  674. TEST_F(mount_setattr, multi_threaded)
  675. {
  676. int i, j, nthreads, ret = 0;
  677. unsigned int old_flags = 0, new_flags = 0, expected_flags = 0;
  678. pthread_attr_t pattr;
  679. pthread_t threads[DEFAULT_THREADS];
  680. if (!mount_setattr_supported())
  681. SKIP(return, "mount_setattr syscall not supported");
  682. old_flags = read_mnt_flags("/mnt/A");
  683. ASSERT_GT(old_flags, 0);
  684. /* Try to change mount options from multiple threads. */
  685. nthreads = get_nprocs_conf();
  686. if (nthreads > DEFAULT_THREADS)
  687. nthreads = DEFAULT_THREADS;
  688. pthread_attr_init(&pattr);
  689. for (i = 0; i < nthreads; i++)
  690. ASSERT_EQ(pthread_create(&threads[i], &pattr, mount_setattr_thread, NULL), 0);
  691. for (j = 0; j < i; j++) {
  692. void *retptr = NULL;
  693. EXPECT_EQ(pthread_join(threads[j], &retptr), 0);
  694. ret += ptr_to_int(retptr);
  695. EXPECT_EQ(ret, 0);
  696. }
  697. pthread_attr_destroy(&pattr);
  698. ASSERT_EQ(ret, 0);
  699. expected_flags = old_flags;
  700. expected_flags |= MS_RDONLY;
  701. expected_flags |= MS_NOSUID;
  702. new_flags = read_mnt_flags("/mnt/A");
  703. ASSERT_EQ(new_flags, expected_flags);
  704. ASSERT_EQ(is_shared_mount("/mnt/A"), true);
  705. new_flags = read_mnt_flags("/mnt/A/AA");
  706. ASSERT_EQ(new_flags, expected_flags);
  707. ASSERT_EQ(is_shared_mount("/mnt/A/AA"), true);
  708. new_flags = read_mnt_flags("/mnt/A/AA/B");
  709. ASSERT_EQ(new_flags, expected_flags);
  710. ASSERT_EQ(is_shared_mount("/mnt/A/AA/B"), true);
  711. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  712. ASSERT_EQ(new_flags, expected_flags);
  713. ASSERT_EQ(is_shared_mount("/mnt/A/AA/B/BB"), true);
  714. }
  715. TEST_F(mount_setattr, wrong_user_namespace)
  716. {
  717. int ret;
  718. struct mount_attr attr = {
  719. .attr_set = MOUNT_ATTR_RDONLY,
  720. };
  721. if (!mount_setattr_supported())
  722. SKIP(return, "mount_setattr syscall not supported");
  723. EXPECT_EQ(create_and_enter_userns(), 0);
  724. ret = sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr));
  725. ASSERT_LT(ret, 0);
  726. ASSERT_EQ(errno, EPERM);
  727. }
  728. TEST_F(mount_setattr, wrong_mount_namespace)
  729. {
  730. int fd, ret;
  731. struct mount_attr attr = {
  732. .attr_set = MOUNT_ATTR_RDONLY,
  733. };
  734. if (!mount_setattr_supported())
  735. SKIP(return, "mount_setattr syscall not supported");
  736. fd = open("/mnt/A", O_DIRECTORY | O_CLOEXEC);
  737. ASSERT_GE(fd, 0);
  738. ASSERT_EQ(unshare(CLONE_NEWNS), 0);
  739. ret = sys_mount_setattr(fd, "", AT_EMPTY_PATH | AT_RECURSIVE, &attr, sizeof(attr));
  740. ASSERT_LT(ret, 0);
  741. ASSERT_EQ(errno, EINVAL);
  742. }
  743. FIXTURE(mount_setattr_idmapped) {
  744. };
  745. FIXTURE_SETUP(mount_setattr_idmapped)
  746. {
  747. int img_fd = -EBADF;
  748. ASSERT_EQ(unshare(CLONE_NEWNS), 0);
  749. ASSERT_EQ(mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0), 0);
  750. (void)umount2("/mnt", MNT_DETACH);
  751. (void)umount2("/tmp", MNT_DETACH);
  752. ASSERT_EQ(mount("testing", "/tmp", "tmpfs", MS_NOATIME | MS_NODEV,
  753. "size=100000,mode=700"), 0);
  754. ASSERT_EQ(mkdir("/tmp/B", 0777), 0);
  755. ASSERT_EQ(mknodat(-EBADF, "/tmp/B/b", S_IFREG | 0644, 0), 0);
  756. ASSERT_EQ(chown("/tmp/B/b", 0, 0), 0);
  757. ASSERT_EQ(mount("testing", "/tmp/B", "tmpfs", MS_NOATIME | MS_NODEV,
  758. "size=100000,mode=700"), 0);
  759. ASSERT_EQ(mkdir("/tmp/B/BB", 0777), 0);
  760. ASSERT_EQ(mknodat(-EBADF, "/tmp/B/BB/b", S_IFREG | 0644, 0), 0);
  761. ASSERT_EQ(chown("/tmp/B/BB/b", 0, 0), 0);
  762. ASSERT_EQ(mount("testing", "/tmp/B/BB", "tmpfs", MS_NOATIME | MS_NODEV,
  763. "size=100000,mode=700"), 0);
  764. ASSERT_EQ(mount("testing", "/mnt", "tmpfs", MS_NOATIME | MS_NODEV,
  765. "size=2m,mode=700"), 0);
  766. ASSERT_EQ(mkdir("/mnt/A", 0777), 0);
  767. ASSERT_EQ(mount("testing", "/mnt/A", "tmpfs", MS_NOATIME | MS_NODEV,
  768. "size=100000,mode=700"), 0);
  769. ASSERT_EQ(mkdir("/mnt/A/AA", 0777), 0);
  770. ASSERT_EQ(mount("/tmp", "/mnt/A/AA", NULL, MS_BIND | MS_REC, NULL), 0);
  771. ASSERT_EQ(mkdir("/mnt/B", 0777), 0);
  772. ASSERT_EQ(mount("testing", "/mnt/B", "ramfs",
  773. MS_NOATIME | MS_NODEV | MS_NOSUID, 0), 0);
  774. ASSERT_EQ(mkdir("/mnt/B/BB", 0777), 0);
  775. ASSERT_EQ(mount("testing", "/tmp/B/BB", "devpts",
  776. MS_RELATIME | MS_NOEXEC | MS_RDONLY, 0), 0);
  777. ASSERT_EQ(mkdir("/mnt/C", 0777), 0);
  778. ASSERT_EQ(mkdir("/mnt/D", 0777), 0);
  779. img_fd = openat(-EBADF, "/mnt/C/ext4.img", O_CREAT | O_WRONLY, 0600);
  780. ASSERT_GE(img_fd, 0);
  781. ASSERT_EQ(ftruncate(img_fd, 1024 * 2048), 0);
  782. ASSERT_EQ(system("mkfs.ext4 -q /mnt/C/ext4.img"), 0);
  783. ASSERT_EQ(system("mount -o loop -t ext4 /mnt/C/ext4.img /mnt/D/"), 0);
  784. ASSERT_EQ(close(img_fd), 0);
  785. }
  786. FIXTURE_TEARDOWN(mount_setattr_idmapped)
  787. {
  788. (void)umount2("/mnt/A", MNT_DETACH);
  789. (void)umount2("/tmp", MNT_DETACH);
  790. }
  791. /**
  792. * Validate that negative fd values are rejected.
  793. */
  794. TEST_F(mount_setattr_idmapped, invalid_fd_negative)
  795. {
  796. struct mount_attr attr = {
  797. .attr_set = MOUNT_ATTR_IDMAP,
  798. .userns_fd = -EBADF,
  799. };
  800. if (!mount_setattr_supported())
  801. SKIP(return, "mount_setattr syscall not supported");
  802. ASSERT_NE(sys_mount_setattr(-1, "/", 0, &attr, sizeof(attr)), 0) {
  803. TH_LOG("failure: created idmapped mount with negative fd");
  804. }
  805. }
  806. /**
  807. * Validate that excessively large fd values are rejected.
  808. */
  809. TEST_F(mount_setattr_idmapped, invalid_fd_large)
  810. {
  811. struct mount_attr attr = {
  812. .attr_set = MOUNT_ATTR_IDMAP,
  813. .userns_fd = INT64_MAX,
  814. };
  815. if (!mount_setattr_supported())
  816. SKIP(return, "mount_setattr syscall not supported");
  817. ASSERT_NE(sys_mount_setattr(-1, "/", 0, &attr, sizeof(attr)), 0) {
  818. TH_LOG("failure: created idmapped mount with too large fd value");
  819. }
  820. }
  821. /**
  822. * Validate that closed fd values are rejected.
  823. */
  824. TEST_F(mount_setattr_idmapped, invalid_fd_closed)
  825. {
  826. int fd;
  827. struct mount_attr attr = {
  828. .attr_set = MOUNT_ATTR_IDMAP,
  829. };
  830. if (!mount_setattr_supported())
  831. SKIP(return, "mount_setattr syscall not supported");
  832. fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
  833. ASSERT_GE(fd, 0);
  834. ASSERT_GE(close(fd), 0);
  835. attr.userns_fd = fd;
  836. ASSERT_NE(sys_mount_setattr(-1, "/", 0, &attr, sizeof(attr)), 0) {
  837. TH_LOG("failure: created idmapped mount with closed fd");
  838. }
  839. }
  840. /**
  841. * Validate that the initial user namespace is rejected.
  842. */
  843. TEST_F(mount_setattr_idmapped, invalid_fd_initial_userns)
  844. {
  845. int open_tree_fd = -EBADF;
  846. struct mount_attr attr = {
  847. .attr_set = MOUNT_ATTR_IDMAP,
  848. };
  849. if (!mount_setattr_supported())
  850. SKIP(return, "mount_setattr syscall not supported");
  851. open_tree_fd = sys_open_tree(-EBADF, "/mnt/D",
  852. AT_NO_AUTOMOUNT |
  853. AT_SYMLINK_NOFOLLOW |
  854. OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE);
  855. ASSERT_GE(open_tree_fd, 0);
  856. attr.userns_fd = open("/proc/1/ns/user", O_RDONLY | O_CLOEXEC);
  857. ASSERT_GE(attr.userns_fd, 0);
  858. ASSERT_NE(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0);
  859. ASSERT_EQ(errno, EPERM);
  860. ASSERT_EQ(close(attr.userns_fd), 0);
  861. ASSERT_EQ(close(open_tree_fd), 0);
  862. }
  863. static int map_ids(pid_t pid, unsigned long nsid, unsigned long hostid,
  864. unsigned long range)
  865. {
  866. char map[100], procfile[256];
  867. snprintf(procfile, sizeof(procfile), "/proc/%d/uid_map", pid);
  868. snprintf(map, sizeof(map), "%lu %lu %lu", nsid, hostid, range);
  869. if (write_file(procfile, map, strlen(map)))
  870. return -1;
  871. snprintf(procfile, sizeof(procfile), "/proc/%d/gid_map", pid);
  872. snprintf(map, sizeof(map), "%lu %lu %lu", nsid, hostid, range);
  873. if (write_file(procfile, map, strlen(map)))
  874. return -1;
  875. return 0;
  876. }
  877. #define __STACK_SIZE (8 * 1024 * 1024)
  878. static pid_t do_clone(int (*fn)(void *), void *arg, int flags)
  879. {
  880. void *stack;
  881. stack = malloc(__STACK_SIZE);
  882. if (!stack)
  883. return -ENOMEM;
  884. #ifdef __ia64__
  885. return __clone2(fn, stack, __STACK_SIZE, flags | SIGCHLD, arg, NULL);
  886. #else
  887. return clone(fn, stack + __STACK_SIZE, flags | SIGCHLD, arg, NULL);
  888. #endif
  889. }
  890. static int get_userns_fd_cb(void *data)
  891. {
  892. return kill(getpid(), SIGSTOP);
  893. }
  894. static int wait_for_pid(pid_t pid)
  895. {
  896. int status, ret;
  897. again:
  898. ret = waitpid(pid, &status, 0);
  899. if (ret == -1) {
  900. if (errno == EINTR)
  901. goto again;
  902. return -1;
  903. }
  904. if (!WIFEXITED(status))
  905. return -1;
  906. return WEXITSTATUS(status);
  907. }
  908. static int get_userns_fd(unsigned long nsid, unsigned long hostid, unsigned long range)
  909. {
  910. int ret;
  911. pid_t pid;
  912. char path[256];
  913. pid = do_clone(get_userns_fd_cb, NULL, CLONE_NEWUSER);
  914. if (pid < 0)
  915. return -errno;
  916. ret = map_ids(pid, nsid, hostid, range);
  917. if (ret < 0)
  918. return ret;
  919. snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
  920. ret = open(path, O_RDONLY | O_CLOEXEC);
  921. kill(pid, SIGKILL);
  922. wait_for_pid(pid);
  923. return ret;
  924. }
  925. /**
  926. * Validate that an attached mount in our mount namespace cannot be idmapped.
  927. * (The kernel enforces that the mount's mount namespace and the caller's mount
  928. * namespace match.)
  929. */
  930. TEST_F(mount_setattr_idmapped, attached_mount_inside_current_mount_namespace)
  931. {
  932. int open_tree_fd = -EBADF;
  933. struct mount_attr attr = {
  934. .attr_set = MOUNT_ATTR_IDMAP,
  935. };
  936. if (!mount_setattr_supported())
  937. SKIP(return, "mount_setattr syscall not supported");
  938. open_tree_fd = sys_open_tree(-EBADF, "/mnt/D",
  939. AT_EMPTY_PATH |
  940. AT_NO_AUTOMOUNT |
  941. AT_SYMLINK_NOFOLLOW |
  942. OPEN_TREE_CLOEXEC);
  943. ASSERT_GE(open_tree_fd, 0);
  944. attr.userns_fd = get_userns_fd(0, 10000, 10000);
  945. ASSERT_GE(attr.userns_fd, 0);
  946. ASSERT_NE(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0);
  947. ASSERT_EQ(close(attr.userns_fd), 0);
  948. ASSERT_EQ(close(open_tree_fd), 0);
  949. }
  950. /**
  951. * Validate that idmapping a mount is rejected if the mount's mount namespace
  952. * and our mount namespace don't match.
  953. * (The kernel enforces that the mount's mount namespace and the caller's mount
  954. * namespace match.)
  955. */
  956. TEST_F(mount_setattr_idmapped, attached_mount_outside_current_mount_namespace)
  957. {
  958. int open_tree_fd = -EBADF;
  959. struct mount_attr attr = {
  960. .attr_set = MOUNT_ATTR_IDMAP,
  961. };
  962. if (!mount_setattr_supported())
  963. SKIP(return, "mount_setattr syscall not supported");
  964. open_tree_fd = sys_open_tree(-EBADF, "/mnt/D",
  965. AT_EMPTY_PATH |
  966. AT_NO_AUTOMOUNT |
  967. AT_SYMLINK_NOFOLLOW |
  968. OPEN_TREE_CLOEXEC);
  969. ASSERT_GE(open_tree_fd, 0);
  970. ASSERT_EQ(unshare(CLONE_NEWNS), 0);
  971. attr.userns_fd = get_userns_fd(0, 10000, 10000);
  972. ASSERT_GE(attr.userns_fd, 0);
  973. ASSERT_NE(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr,
  974. sizeof(attr)), 0);
  975. ASSERT_EQ(close(attr.userns_fd), 0);
  976. ASSERT_EQ(close(open_tree_fd), 0);
  977. }
  978. /**
  979. * Validate that an attached mount in our mount namespace can be idmapped.
  980. */
  981. TEST_F(mount_setattr_idmapped, detached_mount_inside_current_mount_namespace)
  982. {
  983. int open_tree_fd = -EBADF;
  984. struct mount_attr attr = {
  985. .attr_set = MOUNT_ATTR_IDMAP,
  986. };
  987. if (!mount_setattr_supported())
  988. SKIP(return, "mount_setattr syscall not supported");
  989. open_tree_fd = sys_open_tree(-EBADF, "/mnt/D",
  990. AT_EMPTY_PATH |
  991. AT_NO_AUTOMOUNT |
  992. AT_SYMLINK_NOFOLLOW |
  993. OPEN_TREE_CLOEXEC |
  994. OPEN_TREE_CLONE);
  995. ASSERT_GE(open_tree_fd, 0);
  996. /* Changing mount properties on a detached mount. */
  997. attr.userns_fd = get_userns_fd(0, 10000, 10000);
  998. ASSERT_GE(attr.userns_fd, 0);
  999. ASSERT_EQ(sys_mount_setattr(open_tree_fd, "",
  1000. AT_EMPTY_PATH, &attr, sizeof(attr)), 0);
  1001. ASSERT_EQ(close(attr.userns_fd), 0);
  1002. ASSERT_EQ(close(open_tree_fd), 0);
  1003. }
  1004. /**
  1005. * Validate that a detached mount not in our mount namespace can be idmapped.
  1006. */
  1007. TEST_F(mount_setattr_idmapped, detached_mount_outside_current_mount_namespace)
  1008. {
  1009. int open_tree_fd = -EBADF;
  1010. struct mount_attr attr = {
  1011. .attr_set = MOUNT_ATTR_IDMAP,
  1012. };
  1013. if (!mount_setattr_supported())
  1014. SKIP(return, "mount_setattr syscall not supported");
  1015. open_tree_fd = sys_open_tree(-EBADF, "/mnt/D",
  1016. AT_EMPTY_PATH |
  1017. AT_NO_AUTOMOUNT |
  1018. AT_SYMLINK_NOFOLLOW |
  1019. OPEN_TREE_CLOEXEC |
  1020. OPEN_TREE_CLONE);
  1021. ASSERT_GE(open_tree_fd, 0);
  1022. ASSERT_EQ(unshare(CLONE_NEWNS), 0);
  1023. /* Changing mount properties on a detached mount. */
  1024. attr.userns_fd = get_userns_fd(0, 10000, 10000);
  1025. ASSERT_GE(attr.userns_fd, 0);
  1026. ASSERT_EQ(sys_mount_setattr(open_tree_fd, "",
  1027. AT_EMPTY_PATH, &attr, sizeof(attr)), 0);
  1028. ASSERT_EQ(close(attr.userns_fd), 0);
  1029. ASSERT_EQ(close(open_tree_fd), 0);
  1030. }
  1031. /**
  1032. * Validate that currently changing the idmapping of an idmapped mount fails.
  1033. */
  1034. TEST_F(mount_setattr_idmapped, change_idmapping)
  1035. {
  1036. int open_tree_fd = -EBADF;
  1037. struct mount_attr attr = {
  1038. .attr_set = MOUNT_ATTR_IDMAP,
  1039. };
  1040. if (!mount_setattr_supported())
  1041. SKIP(return, "mount_setattr syscall not supported");
  1042. open_tree_fd = sys_open_tree(-EBADF, "/mnt/D",
  1043. AT_EMPTY_PATH |
  1044. AT_NO_AUTOMOUNT |
  1045. AT_SYMLINK_NOFOLLOW |
  1046. OPEN_TREE_CLOEXEC |
  1047. OPEN_TREE_CLONE);
  1048. ASSERT_GE(open_tree_fd, 0);
  1049. attr.userns_fd = get_userns_fd(0, 10000, 10000);
  1050. ASSERT_GE(attr.userns_fd, 0);
  1051. ASSERT_EQ(sys_mount_setattr(open_tree_fd, "",
  1052. AT_EMPTY_PATH, &attr, sizeof(attr)), 0);
  1053. ASSERT_EQ(close(attr.userns_fd), 0);
  1054. /* Change idmapping on a detached mount that is already idmapped. */
  1055. attr.userns_fd = get_userns_fd(0, 20000, 10000);
  1056. ASSERT_GE(attr.userns_fd, 0);
  1057. ASSERT_NE(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0);
  1058. ASSERT_EQ(close(attr.userns_fd), 0);
  1059. ASSERT_EQ(close(open_tree_fd), 0);
  1060. }
  1061. static bool expected_uid_gid(int dfd, const char *path, int flags,
  1062. uid_t expected_uid, gid_t expected_gid)
  1063. {
  1064. int ret;
  1065. struct stat st;
  1066. ret = fstatat(dfd, path, &st, flags);
  1067. if (ret < 0)
  1068. return false;
  1069. return st.st_uid == expected_uid && st.st_gid == expected_gid;
  1070. }
  1071. TEST_F(mount_setattr_idmapped, idmap_mount_tree_invalid)
  1072. {
  1073. int open_tree_fd = -EBADF;
  1074. struct mount_attr attr = {
  1075. .attr_set = MOUNT_ATTR_IDMAP,
  1076. };
  1077. if (!mount_setattr_supported())
  1078. SKIP(return, "mount_setattr syscall not supported");
  1079. ASSERT_EQ(expected_uid_gid(-EBADF, "/tmp/B/b", 0, 0, 0), 0);
  1080. ASSERT_EQ(expected_uid_gid(-EBADF, "/tmp/B/BB/b", 0, 0, 0), 0);
  1081. ASSERT_EQ(mount("testing", "/mnt/A", "ramfs", MS_NOATIME | MS_NODEV,
  1082. "size=100000,mode=700"), 0);
  1083. ASSERT_EQ(mkdir("/mnt/A/AA", 0777), 0);
  1084. ASSERT_EQ(mount("/tmp", "/mnt/A/AA", NULL, MS_BIND | MS_REC, NULL), 0);
  1085. open_tree_fd = sys_open_tree(-EBADF, "/mnt/A",
  1086. AT_RECURSIVE |
  1087. AT_EMPTY_PATH |
  1088. AT_NO_AUTOMOUNT |
  1089. AT_SYMLINK_NOFOLLOW |
  1090. OPEN_TREE_CLOEXEC |
  1091. OPEN_TREE_CLONE);
  1092. ASSERT_GE(open_tree_fd, 0);
  1093. attr.userns_fd = get_userns_fd(0, 10000, 10000);
  1094. ASSERT_GE(attr.userns_fd, 0);
  1095. ASSERT_NE(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0);
  1096. ASSERT_EQ(close(attr.userns_fd), 0);
  1097. ASSERT_EQ(close(open_tree_fd), 0);
  1098. ASSERT_EQ(expected_uid_gid(-EBADF, "/tmp/B/b", 0, 0, 0), 0);
  1099. ASSERT_EQ(expected_uid_gid(-EBADF, "/tmp/B/BB/b", 0, 0, 0), 0);
  1100. ASSERT_EQ(expected_uid_gid(open_tree_fd, "B/b", 0, 0, 0), 0);
  1101. ASSERT_EQ(expected_uid_gid(open_tree_fd, "B/BB/b", 0, 0, 0), 0);
  1102. (void)umount2("/mnt/A", MNT_DETACH);
  1103. }
  1104. TEST_F(mount_setattr, mount_attr_nosymfollow)
  1105. {
  1106. int fd;
  1107. unsigned int old_flags = 0, new_flags = 0, expected_flags = 0;
  1108. struct mount_attr attr = {
  1109. .attr_set = MOUNT_ATTR_NOSYMFOLLOW,
  1110. };
  1111. if (!mount_setattr_supported())
  1112. SKIP(return, "mount_setattr syscall not supported");
  1113. fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC);
  1114. ASSERT_GT(fd, 0);
  1115. ASSERT_EQ(close(fd), 0);
  1116. old_flags = read_mnt_flags("/mnt/A");
  1117. ASSERT_GT(old_flags, 0);
  1118. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  1119. expected_flags = old_flags;
  1120. expected_flags |= ST_NOSYMFOLLOW;
  1121. new_flags = read_mnt_flags("/mnt/A");
  1122. ASSERT_EQ(new_flags, expected_flags);
  1123. new_flags = read_mnt_flags("/mnt/A/AA");
  1124. ASSERT_EQ(new_flags, expected_flags);
  1125. new_flags = read_mnt_flags("/mnt/A/AA/B");
  1126. ASSERT_EQ(new_flags, expected_flags);
  1127. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  1128. ASSERT_EQ(new_flags, expected_flags);
  1129. fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC);
  1130. ASSERT_LT(fd, 0);
  1131. ASSERT_EQ(errno, ELOOP);
  1132. attr.attr_set &= ~MOUNT_ATTR_NOSYMFOLLOW;
  1133. attr.attr_clr |= MOUNT_ATTR_NOSYMFOLLOW;
  1134. ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
  1135. expected_flags &= ~ST_NOSYMFOLLOW;
  1136. new_flags = read_mnt_flags("/mnt/A");
  1137. ASSERT_EQ(new_flags, expected_flags);
  1138. new_flags = read_mnt_flags("/mnt/A/AA");
  1139. ASSERT_EQ(new_flags, expected_flags);
  1140. new_flags = read_mnt_flags("/mnt/A/AA/B");
  1141. ASSERT_EQ(new_flags, expected_flags);
  1142. new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
  1143. ASSERT_EQ(new_flags, expected_flags);
  1144. fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC);
  1145. ASSERT_GT(fd, 0);
  1146. ASSERT_EQ(close(fd), 0);
  1147. }
  1148. TEST_HARNESS_MAIN