memfd_test.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. #define _GNU_SOURCE
  2. #define __EXPORTED_HEADERS__
  3. #include <errno.h>
  4. #include <inttypes.h>
  5. #include <limits.h>
  6. #include <linux/falloc.h>
  7. #include <linux/fcntl.h>
  8. #include <linux/memfd.h>
  9. #include <sched.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <signal.h>
  13. #include <string.h>
  14. #include <sys/mman.h>
  15. #include <sys/stat.h>
  16. #include <sys/syscall.h>
  17. #include <unistd.h>
  18. #define MFD_DEF_SIZE 8192
  19. #define STACK_SIZE 65535
  20. static int sys_memfd_create(const char *name,
  21. unsigned int flags)
  22. {
  23. return syscall(__NR_memfd_create, name, flags);
  24. }
  25. static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
  26. {
  27. int r, fd;
  28. fd = sys_memfd_create(name, flags);
  29. if (fd < 0) {
  30. printf("memfd_create(\"%s\", %u) failed: %m\n",
  31. name, flags);
  32. abort();
  33. }
  34. r = ftruncate(fd, sz);
  35. if (r < 0) {
  36. printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz);
  37. abort();
  38. }
  39. return fd;
  40. }
  41. static void mfd_fail_new(const char *name, unsigned int flags)
  42. {
  43. int r;
  44. r = sys_memfd_create(name, flags);
  45. if (r >= 0) {
  46. printf("memfd_create(\"%s\", %u) succeeded, but failure expected\n",
  47. name, flags);
  48. close(r);
  49. abort();
  50. }
  51. }
  52. static __u64 mfd_assert_get_seals(int fd)
  53. {
  54. long r;
  55. r = fcntl(fd, F_GET_SEALS);
  56. if (r < 0) {
  57. printf("GET_SEALS(%d) failed: %m\n", fd);
  58. abort();
  59. }
  60. return r;
  61. }
  62. static void mfd_assert_has_seals(int fd, __u64 seals)
  63. {
  64. __u64 s;
  65. s = mfd_assert_get_seals(fd);
  66. if (s != seals) {
  67. printf("%llu != %llu = GET_SEALS(%d)\n",
  68. (unsigned long long)seals, (unsigned long long)s, fd);
  69. abort();
  70. }
  71. }
  72. static void mfd_assert_add_seals(int fd, __u64 seals)
  73. {
  74. long r;
  75. __u64 s;
  76. s = mfd_assert_get_seals(fd);
  77. r = fcntl(fd, F_ADD_SEALS, seals);
  78. if (r < 0) {
  79. printf("ADD_SEALS(%d, %llu -> %llu) failed: %m\n",
  80. fd, (unsigned long long)s, (unsigned long long)seals);
  81. abort();
  82. }
  83. }
  84. static void mfd_fail_add_seals(int fd, __u64 seals)
  85. {
  86. long r;
  87. __u64 s;
  88. r = fcntl(fd, F_GET_SEALS);
  89. if (r < 0)
  90. s = 0;
  91. else
  92. s = r;
  93. r = fcntl(fd, F_ADD_SEALS, seals);
  94. if (r >= 0) {
  95. printf("ADD_SEALS(%d, %llu -> %llu) didn't fail as expected\n",
  96. fd, (unsigned long long)s, (unsigned long long)seals);
  97. abort();
  98. }
  99. }
  100. static void mfd_assert_size(int fd, size_t size)
  101. {
  102. struct stat st;
  103. int r;
  104. r = fstat(fd, &st);
  105. if (r < 0) {
  106. printf("fstat(%d) failed: %m\n", fd);
  107. abort();
  108. } else if (st.st_size != size) {
  109. printf("wrong file size %lld, but expected %lld\n",
  110. (long long)st.st_size, (long long)size);
  111. abort();
  112. }
  113. }
  114. static int mfd_assert_dup(int fd)
  115. {
  116. int r;
  117. r = dup(fd);
  118. if (r < 0) {
  119. printf("dup(%d) failed: %m\n", fd);
  120. abort();
  121. }
  122. return r;
  123. }
  124. static void *mfd_assert_mmap_shared(int fd)
  125. {
  126. void *p;
  127. p = mmap(NULL,
  128. MFD_DEF_SIZE,
  129. PROT_READ | PROT_WRITE,
  130. MAP_SHARED,
  131. fd,
  132. 0);
  133. if (p == MAP_FAILED) {
  134. printf("mmap() failed: %m\n");
  135. abort();
  136. }
  137. return p;
  138. }
  139. static void *mfd_assert_mmap_private(int fd)
  140. {
  141. void *p;
  142. p = mmap(NULL,
  143. MFD_DEF_SIZE,
  144. PROT_READ,
  145. MAP_PRIVATE,
  146. fd,
  147. 0);
  148. if (p == MAP_FAILED) {
  149. printf("mmap() failed: %m\n");
  150. abort();
  151. }
  152. return p;
  153. }
  154. static int mfd_assert_open(int fd, int flags, mode_t mode)
  155. {
  156. char buf[512];
  157. int r;
  158. sprintf(buf, "/proc/self/fd/%d", fd);
  159. r = open(buf, flags, mode);
  160. if (r < 0) {
  161. printf("open(%s) failed: %m\n", buf);
  162. abort();
  163. }
  164. return r;
  165. }
  166. static void mfd_fail_open(int fd, int flags, mode_t mode)
  167. {
  168. char buf[512];
  169. int r;
  170. sprintf(buf, "/proc/self/fd/%d", fd);
  171. r = open(buf, flags, mode);
  172. if (r >= 0) {
  173. printf("open(%s) didn't fail as expected\n");
  174. abort();
  175. }
  176. }
  177. static void mfd_assert_read(int fd)
  178. {
  179. char buf[16];
  180. void *p;
  181. ssize_t l;
  182. l = read(fd, buf, sizeof(buf));
  183. if (l != sizeof(buf)) {
  184. printf("read() failed: %m\n");
  185. abort();
  186. }
  187. /* verify PROT_READ *is* allowed */
  188. p = mmap(NULL,
  189. MFD_DEF_SIZE,
  190. PROT_READ,
  191. MAP_PRIVATE,
  192. fd,
  193. 0);
  194. if (p == MAP_FAILED) {
  195. printf("mmap() failed: %m\n");
  196. abort();
  197. }
  198. munmap(p, MFD_DEF_SIZE);
  199. /* verify MAP_PRIVATE is *always* allowed (even writable) */
  200. p = mmap(NULL,
  201. MFD_DEF_SIZE,
  202. PROT_READ | PROT_WRITE,
  203. MAP_PRIVATE,
  204. fd,
  205. 0);
  206. if (p == MAP_FAILED) {
  207. printf("mmap() failed: %m\n");
  208. abort();
  209. }
  210. munmap(p, MFD_DEF_SIZE);
  211. }
  212. static void mfd_assert_write(int fd)
  213. {
  214. ssize_t l;
  215. void *p;
  216. int r;
  217. /* verify write() succeeds */
  218. l = write(fd, "\0\0\0\0", 4);
  219. if (l != 4) {
  220. printf("write() failed: %m\n");
  221. abort();
  222. }
  223. /* verify PROT_READ | PROT_WRITE is allowed */
  224. p = mmap(NULL,
  225. MFD_DEF_SIZE,
  226. PROT_READ | PROT_WRITE,
  227. MAP_SHARED,
  228. fd,
  229. 0);
  230. if (p == MAP_FAILED) {
  231. printf("mmap() failed: %m\n");
  232. abort();
  233. }
  234. *(char *)p = 0;
  235. munmap(p, MFD_DEF_SIZE);
  236. /* verify PROT_WRITE is allowed */
  237. p = mmap(NULL,
  238. MFD_DEF_SIZE,
  239. PROT_WRITE,
  240. MAP_SHARED,
  241. fd,
  242. 0);
  243. if (p == MAP_FAILED) {
  244. printf("mmap() failed: %m\n");
  245. abort();
  246. }
  247. *(char *)p = 0;
  248. munmap(p, MFD_DEF_SIZE);
  249. /* verify PROT_READ with MAP_SHARED is allowed and a following
  250. * mprotect(PROT_WRITE) allows writing */
  251. p = mmap(NULL,
  252. MFD_DEF_SIZE,
  253. PROT_READ,
  254. MAP_SHARED,
  255. fd,
  256. 0);
  257. if (p == MAP_FAILED) {
  258. printf("mmap() failed: %m\n");
  259. abort();
  260. }
  261. r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
  262. if (r < 0) {
  263. printf("mprotect() failed: %m\n");
  264. abort();
  265. }
  266. *(char *)p = 0;
  267. munmap(p, MFD_DEF_SIZE);
  268. /* verify PUNCH_HOLE works */
  269. r = fallocate(fd,
  270. FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
  271. 0,
  272. MFD_DEF_SIZE);
  273. if (r < 0) {
  274. printf("fallocate(PUNCH_HOLE) failed: %m\n");
  275. abort();
  276. }
  277. }
  278. static void mfd_fail_write(int fd)
  279. {
  280. ssize_t l;
  281. void *p;
  282. int r;
  283. /* verify write() fails */
  284. l = write(fd, "data", 4);
  285. if (l != -EPERM) {
  286. printf("expected EPERM on write(), but got %d: %m\n", (int)l);
  287. abort();
  288. }
  289. /* verify PROT_READ | PROT_WRITE is not allowed */
  290. p = mmap(NULL,
  291. MFD_DEF_SIZE,
  292. PROT_READ | PROT_WRITE,
  293. MAP_SHARED,
  294. fd,
  295. 0);
  296. if (p != MAP_FAILED) {
  297. printf("mmap() didn't fail as expected\n");
  298. abort();
  299. }
  300. /* verify PROT_WRITE is not allowed */
  301. p = mmap(NULL,
  302. MFD_DEF_SIZE,
  303. PROT_WRITE,
  304. MAP_SHARED,
  305. fd,
  306. 0);
  307. if (p != MAP_FAILED) {
  308. printf("mmap() didn't fail as expected\n");
  309. abort();
  310. }
  311. /* Verify PROT_READ with MAP_SHARED with a following mprotect is not
  312. * allowed. Note that for r/w the kernel already prevents the mmap. */
  313. p = mmap(NULL,
  314. MFD_DEF_SIZE,
  315. PROT_READ,
  316. MAP_SHARED,
  317. fd,
  318. 0);
  319. if (p != MAP_FAILED) {
  320. r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
  321. if (r >= 0) {
  322. printf("mmap()+mprotect() didn't fail as expected\n");
  323. abort();
  324. }
  325. }
  326. /* verify PUNCH_HOLE fails */
  327. r = fallocate(fd,
  328. FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
  329. 0,
  330. MFD_DEF_SIZE);
  331. if (r >= 0) {
  332. printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
  333. abort();
  334. }
  335. }
  336. static void mfd_assert_shrink(int fd)
  337. {
  338. int r, fd2;
  339. r = ftruncate(fd, MFD_DEF_SIZE / 2);
  340. if (r < 0) {
  341. printf("ftruncate(SHRINK) failed: %m\n");
  342. abort();
  343. }
  344. mfd_assert_size(fd, MFD_DEF_SIZE / 2);
  345. fd2 = mfd_assert_open(fd,
  346. O_RDWR | O_CREAT | O_TRUNC,
  347. S_IRUSR | S_IWUSR);
  348. close(fd2);
  349. mfd_assert_size(fd, 0);
  350. }
  351. static void mfd_fail_shrink(int fd)
  352. {
  353. int r;
  354. r = ftruncate(fd, MFD_DEF_SIZE / 2);
  355. if (r >= 0) {
  356. printf("ftruncate(SHRINK) didn't fail as expected\n");
  357. abort();
  358. }
  359. mfd_fail_open(fd,
  360. O_RDWR | O_CREAT | O_TRUNC,
  361. S_IRUSR | S_IWUSR);
  362. }
  363. static void mfd_assert_grow(int fd)
  364. {
  365. int r;
  366. r = ftruncate(fd, MFD_DEF_SIZE * 2);
  367. if (r < 0) {
  368. printf("ftruncate(GROW) failed: %m\n");
  369. abort();
  370. }
  371. mfd_assert_size(fd, MFD_DEF_SIZE * 2);
  372. r = fallocate(fd,
  373. 0,
  374. 0,
  375. MFD_DEF_SIZE * 4);
  376. if (r < 0) {
  377. printf("fallocate(ALLOC) failed: %m\n");
  378. abort();
  379. }
  380. mfd_assert_size(fd, MFD_DEF_SIZE * 4);
  381. }
  382. static void mfd_fail_grow(int fd)
  383. {
  384. int r;
  385. r = ftruncate(fd, MFD_DEF_SIZE * 2);
  386. if (r >= 0) {
  387. printf("ftruncate(GROW) didn't fail as expected\n");
  388. abort();
  389. }
  390. r = fallocate(fd,
  391. 0,
  392. 0,
  393. MFD_DEF_SIZE * 4);
  394. if (r >= 0) {
  395. printf("fallocate(ALLOC) didn't fail as expected\n");
  396. abort();
  397. }
  398. }
  399. static void mfd_assert_grow_write(int fd)
  400. {
  401. static char buf[MFD_DEF_SIZE * 8];
  402. ssize_t l;
  403. l = pwrite(fd, buf, sizeof(buf), 0);
  404. if (l != sizeof(buf)) {
  405. printf("pwrite() failed: %m\n");
  406. abort();
  407. }
  408. mfd_assert_size(fd, MFD_DEF_SIZE * 8);
  409. }
  410. static void mfd_fail_grow_write(int fd)
  411. {
  412. static char buf[MFD_DEF_SIZE * 8];
  413. ssize_t l;
  414. l = pwrite(fd, buf, sizeof(buf), 0);
  415. if (l == sizeof(buf)) {
  416. printf("pwrite() didn't fail as expected\n");
  417. abort();
  418. }
  419. }
  420. static int idle_thread_fn(void *arg)
  421. {
  422. sigset_t set;
  423. int sig;
  424. /* dummy waiter; SIGTERM terminates us anyway */
  425. sigemptyset(&set);
  426. sigaddset(&set, SIGTERM);
  427. sigwait(&set, &sig);
  428. return 0;
  429. }
  430. static pid_t spawn_idle_thread(unsigned int flags)
  431. {
  432. uint8_t *stack;
  433. pid_t pid;
  434. stack = malloc(STACK_SIZE);
  435. if (!stack) {
  436. printf("malloc(STACK_SIZE) failed: %m\n");
  437. abort();
  438. }
  439. pid = clone(idle_thread_fn,
  440. stack + STACK_SIZE,
  441. SIGCHLD | flags,
  442. NULL);
  443. if (pid < 0) {
  444. printf("clone() failed: %m\n");
  445. abort();
  446. }
  447. return pid;
  448. }
  449. static void join_idle_thread(pid_t pid)
  450. {
  451. kill(pid, SIGTERM);
  452. waitpid(pid, NULL, 0);
  453. }
  454. /*
  455. * Test memfd_create() syscall
  456. * Verify syscall-argument validation, including name checks, flag validation
  457. * and more.
  458. */
  459. static void test_create(void)
  460. {
  461. char buf[2048];
  462. int fd;
  463. /* test NULL name */
  464. mfd_fail_new(NULL, 0);
  465. /* test over-long name (not zero-terminated) */
  466. memset(buf, 0xff, sizeof(buf));
  467. mfd_fail_new(buf, 0);
  468. /* test over-long zero-terminated name */
  469. memset(buf, 0xff, sizeof(buf));
  470. buf[sizeof(buf) - 1] = 0;
  471. mfd_fail_new(buf, 0);
  472. /* verify "" is a valid name */
  473. fd = mfd_assert_new("", 0, 0);
  474. close(fd);
  475. /* verify invalid O_* open flags */
  476. mfd_fail_new("", 0x0100);
  477. mfd_fail_new("", ~MFD_CLOEXEC);
  478. mfd_fail_new("", ~MFD_ALLOW_SEALING);
  479. mfd_fail_new("", ~0);
  480. mfd_fail_new("", 0x80000000U);
  481. /* verify MFD_CLOEXEC is allowed */
  482. fd = mfd_assert_new("", 0, MFD_CLOEXEC);
  483. close(fd);
  484. /* verify MFD_ALLOW_SEALING is allowed */
  485. fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
  486. close(fd);
  487. /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
  488. fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
  489. close(fd);
  490. }
  491. /*
  492. * Test basic sealing
  493. * A very basic sealing test to see whether setting/retrieving seals works.
  494. */
  495. static void test_basic(void)
  496. {
  497. int fd;
  498. fd = mfd_assert_new("kern_memfd_basic",
  499. MFD_DEF_SIZE,
  500. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  501. /* add basic seals */
  502. mfd_assert_has_seals(fd, 0);
  503. mfd_assert_add_seals(fd, F_SEAL_SHRINK |
  504. F_SEAL_WRITE);
  505. mfd_assert_has_seals(fd, F_SEAL_SHRINK |
  506. F_SEAL_WRITE);
  507. /* add them again */
  508. mfd_assert_add_seals(fd, F_SEAL_SHRINK |
  509. F_SEAL_WRITE);
  510. mfd_assert_has_seals(fd, F_SEAL_SHRINK |
  511. F_SEAL_WRITE);
  512. /* add more seals and seal against sealing */
  513. mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL);
  514. mfd_assert_has_seals(fd, F_SEAL_SHRINK |
  515. F_SEAL_GROW |
  516. F_SEAL_WRITE |
  517. F_SEAL_SEAL);
  518. /* verify that sealing no longer works */
  519. mfd_fail_add_seals(fd, F_SEAL_GROW);
  520. mfd_fail_add_seals(fd, 0);
  521. close(fd);
  522. /* verify sealing does not work without MFD_ALLOW_SEALING */
  523. fd = mfd_assert_new("kern_memfd_basic",
  524. MFD_DEF_SIZE,
  525. MFD_CLOEXEC);
  526. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  527. mfd_fail_add_seals(fd, F_SEAL_SHRINK |
  528. F_SEAL_GROW |
  529. F_SEAL_WRITE);
  530. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  531. close(fd);
  532. }
  533. /*
  534. * Test SEAL_WRITE
  535. * Test whether SEAL_WRITE actually prevents modifications.
  536. */
  537. static void test_seal_write(void)
  538. {
  539. int fd;
  540. fd = mfd_assert_new("kern_memfd_seal_write",
  541. MFD_DEF_SIZE,
  542. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  543. mfd_assert_has_seals(fd, 0);
  544. mfd_assert_add_seals(fd, F_SEAL_WRITE);
  545. mfd_assert_has_seals(fd, F_SEAL_WRITE);
  546. mfd_assert_read(fd);
  547. mfd_fail_write(fd);
  548. mfd_assert_shrink(fd);
  549. mfd_assert_grow(fd);
  550. mfd_fail_grow_write(fd);
  551. close(fd);
  552. }
  553. /*
  554. * Test SEAL_SHRINK
  555. * Test whether SEAL_SHRINK actually prevents shrinking
  556. */
  557. static void test_seal_shrink(void)
  558. {
  559. int fd;
  560. fd = mfd_assert_new("kern_memfd_seal_shrink",
  561. MFD_DEF_SIZE,
  562. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  563. mfd_assert_has_seals(fd, 0);
  564. mfd_assert_add_seals(fd, F_SEAL_SHRINK);
  565. mfd_assert_has_seals(fd, F_SEAL_SHRINK);
  566. mfd_assert_read(fd);
  567. mfd_assert_write(fd);
  568. mfd_fail_shrink(fd);
  569. mfd_assert_grow(fd);
  570. mfd_assert_grow_write(fd);
  571. close(fd);
  572. }
  573. /*
  574. * Test SEAL_GROW
  575. * Test whether SEAL_GROW actually prevents growing
  576. */
  577. static void test_seal_grow(void)
  578. {
  579. int fd;
  580. fd = mfd_assert_new("kern_memfd_seal_grow",
  581. MFD_DEF_SIZE,
  582. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  583. mfd_assert_has_seals(fd, 0);
  584. mfd_assert_add_seals(fd, F_SEAL_GROW);
  585. mfd_assert_has_seals(fd, F_SEAL_GROW);
  586. mfd_assert_read(fd);
  587. mfd_assert_write(fd);
  588. mfd_assert_shrink(fd);
  589. mfd_fail_grow(fd);
  590. mfd_fail_grow_write(fd);
  591. close(fd);
  592. }
  593. /*
  594. * Test SEAL_SHRINK | SEAL_GROW
  595. * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
  596. */
  597. static void test_seal_resize(void)
  598. {
  599. int fd;
  600. fd = mfd_assert_new("kern_memfd_seal_resize",
  601. MFD_DEF_SIZE,
  602. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  603. mfd_assert_has_seals(fd, 0);
  604. mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
  605. mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
  606. mfd_assert_read(fd);
  607. mfd_assert_write(fd);
  608. mfd_fail_shrink(fd);
  609. mfd_fail_grow(fd);
  610. mfd_fail_grow_write(fd);
  611. close(fd);
  612. }
  613. /*
  614. * Test sharing via dup()
  615. * Test that seals are shared between dupped FDs and they're all equal.
  616. */
  617. static void test_share_dup(void)
  618. {
  619. int fd, fd2;
  620. fd = mfd_assert_new("kern_memfd_share_dup",
  621. MFD_DEF_SIZE,
  622. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  623. mfd_assert_has_seals(fd, 0);
  624. fd2 = mfd_assert_dup(fd);
  625. mfd_assert_has_seals(fd2, 0);
  626. mfd_assert_add_seals(fd, F_SEAL_WRITE);
  627. mfd_assert_has_seals(fd, F_SEAL_WRITE);
  628. mfd_assert_has_seals(fd2, F_SEAL_WRITE);
  629. mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
  630. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
  631. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
  632. mfd_assert_add_seals(fd, F_SEAL_SEAL);
  633. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
  634. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
  635. mfd_fail_add_seals(fd, F_SEAL_GROW);
  636. mfd_fail_add_seals(fd2, F_SEAL_GROW);
  637. mfd_fail_add_seals(fd, F_SEAL_SEAL);
  638. mfd_fail_add_seals(fd2, F_SEAL_SEAL);
  639. close(fd2);
  640. mfd_fail_add_seals(fd, F_SEAL_GROW);
  641. close(fd);
  642. }
  643. /*
  644. * Test sealing with active mmap()s
  645. * Modifying seals is only allowed if no other mmap() refs exist.
  646. */
  647. static void test_share_mmap(void)
  648. {
  649. int fd;
  650. void *p;
  651. fd = mfd_assert_new("kern_memfd_share_mmap",
  652. MFD_DEF_SIZE,
  653. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  654. mfd_assert_has_seals(fd, 0);
  655. /* shared/writable ref prevents sealing WRITE, but allows others */
  656. p = mfd_assert_mmap_shared(fd);
  657. mfd_fail_add_seals(fd, F_SEAL_WRITE);
  658. mfd_assert_has_seals(fd, 0);
  659. mfd_assert_add_seals(fd, F_SEAL_SHRINK);
  660. mfd_assert_has_seals(fd, F_SEAL_SHRINK);
  661. munmap(p, MFD_DEF_SIZE);
  662. /* readable ref allows sealing */
  663. p = mfd_assert_mmap_private(fd);
  664. mfd_assert_add_seals(fd, F_SEAL_WRITE);
  665. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
  666. munmap(p, MFD_DEF_SIZE);
  667. close(fd);
  668. }
  669. /*
  670. * Test sealing with open(/proc/self/fd/%d)
  671. * Via /proc we can get access to a separate file-context for the same memfd.
  672. * This is *not* like dup(), but like a real separate open(). Make sure the
  673. * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
  674. */
  675. static void test_share_open(void)
  676. {
  677. int fd, fd2;
  678. fd = mfd_assert_new("kern_memfd_share_open",
  679. MFD_DEF_SIZE,
  680. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  681. mfd_assert_has_seals(fd, 0);
  682. fd2 = mfd_assert_open(fd, O_RDWR, 0);
  683. mfd_assert_add_seals(fd, F_SEAL_WRITE);
  684. mfd_assert_has_seals(fd, F_SEAL_WRITE);
  685. mfd_assert_has_seals(fd2, F_SEAL_WRITE);
  686. mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
  687. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
  688. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
  689. close(fd);
  690. fd = mfd_assert_open(fd2, O_RDONLY, 0);
  691. mfd_fail_add_seals(fd, F_SEAL_SEAL);
  692. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
  693. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
  694. close(fd2);
  695. fd2 = mfd_assert_open(fd, O_RDWR, 0);
  696. mfd_assert_add_seals(fd2, F_SEAL_SEAL);
  697. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
  698. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
  699. close(fd2);
  700. close(fd);
  701. }
  702. /*
  703. * Test sharing via fork()
  704. * Test whether seal-modifications work as expected with forked childs.
  705. */
  706. static void test_share_fork(void)
  707. {
  708. int fd;
  709. pid_t pid;
  710. fd = mfd_assert_new("kern_memfd_share_fork",
  711. MFD_DEF_SIZE,
  712. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  713. mfd_assert_has_seals(fd, 0);
  714. pid = spawn_idle_thread(0);
  715. mfd_assert_add_seals(fd, F_SEAL_SEAL);
  716. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  717. mfd_fail_add_seals(fd, F_SEAL_WRITE);
  718. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  719. join_idle_thread(pid);
  720. mfd_fail_add_seals(fd, F_SEAL_WRITE);
  721. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  722. close(fd);
  723. }
  724. int main(int argc, char **argv)
  725. {
  726. pid_t pid;
  727. printf("memfd: CREATE\n");
  728. test_create();
  729. printf("memfd: BASIC\n");
  730. test_basic();
  731. printf("memfd: SEAL-WRITE\n");
  732. test_seal_write();
  733. printf("memfd: SEAL-SHRINK\n");
  734. test_seal_shrink();
  735. printf("memfd: SEAL-GROW\n");
  736. test_seal_grow();
  737. printf("memfd: SEAL-RESIZE\n");
  738. test_seal_resize();
  739. printf("memfd: SHARE-DUP\n");
  740. test_share_dup();
  741. printf("memfd: SHARE-MMAP\n");
  742. test_share_mmap();
  743. printf("memfd: SHARE-OPEN\n");
  744. test_share_open();
  745. printf("memfd: SHARE-FORK\n");
  746. test_share_fork();
  747. /* Run test-suite in a multi-threaded environment with a shared
  748. * file-table. */
  749. pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
  750. printf("memfd: SHARE-DUP (shared file-table)\n");
  751. test_share_dup();
  752. printf("memfd: SHARE-MMAP (shared file-table)\n");
  753. test_share_mmap();
  754. printf("memfd: SHARE-OPEN (shared file-table)\n");
  755. test_share_open();
  756. printf("memfd: SHARE-FORK (shared file-table)\n");
  757. test_share_fork();
  758. join_idle_thread(pid);
  759. printf("memfd: DONE\n");
  760. return 0;
  761. }