memfd_test.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #define __EXPORTED_HEADERS__
  4. #include <errno.h>
  5. #include <inttypes.h>
  6. #include <limits.h>
  7. #include <linux/falloc.h>
  8. #include <fcntl.h>
  9. #include <linux/memfd.h>
  10. #include <sched.h>
  11. #include <stdbool.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <signal.h>
  15. #include <string.h>
  16. #include <sys/mman.h>
  17. #include <sys/stat.h>
  18. #include <sys/syscall.h>
  19. #include <sys/wait.h>
  20. #include <sys/types.h>
  21. #include <sys/ipc.h>
  22. #include <sys/sem.h>
  23. #include <unistd.h>
  24. #include <ctype.h>
  25. #include "common.h"
  26. #define MEMFD_STR "memfd:"
  27. #define MEMFD_HUGE_STR "memfd-hugetlb:"
  28. #define SHARED_FT_STR "(shared file-table)"
  29. #define MFD_DEF_SIZE 8192
  30. #define STACK_SIZE 65536
  31. #define F_SEAL_EXEC 0x0020
  32. #define F_WX_SEALS (F_SEAL_SHRINK | \
  33. F_SEAL_GROW | \
  34. F_SEAL_WRITE | \
  35. F_SEAL_FUTURE_WRITE | \
  36. F_SEAL_EXEC)
  37. #define MFD_NOEXEC_SEAL 0x0008U
  38. union semun {
  39. int val;
  40. struct semid_ds *buf;
  41. unsigned short int *array;
  42. struct seminfo *__buf;
  43. };
  44. /*
  45. * we use semaphores on nested wait tasks due the use of CLONE_NEWPID: the
  46. * child will be PID 1 and can't send SIGSTOP to themselves due special
  47. * treatment of the init task, so the SIGSTOP/SIGCONT synchronization
  48. * approach can't be used here.
  49. */
  50. #define SEM_KEY 0xdeadbeef
  51. /*
  52. * Default is not to test hugetlbfs
  53. */
  54. static size_t mfd_def_size = MFD_DEF_SIZE;
  55. static const char *memfd_str = MEMFD_STR;
  56. static ssize_t fd2name(int fd, char *buf, size_t bufsize)
  57. {
  58. char buf1[PATH_MAX];
  59. int size;
  60. ssize_t nbytes;
  61. size = snprintf(buf1, PATH_MAX, "/proc/self/fd/%d", fd);
  62. if (size < 0) {
  63. printf("snprintf(%d) failed on %m\n", fd);
  64. abort();
  65. }
  66. /*
  67. * reserver one byte for string termination.
  68. */
  69. nbytes = readlink(buf1, buf, bufsize-1);
  70. if (nbytes == -1) {
  71. printf("readlink(%s) failed %m\n", buf1);
  72. abort();
  73. }
  74. buf[nbytes] = '\0';
  75. return nbytes;
  76. }
  77. static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
  78. {
  79. int r, fd;
  80. fd = sys_memfd_create(name, flags);
  81. if (fd < 0) {
  82. printf("memfd_create(\"%s\", %u) failed: %m\n",
  83. name, flags);
  84. abort();
  85. }
  86. r = ftruncate(fd, sz);
  87. if (r < 0) {
  88. printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz);
  89. abort();
  90. }
  91. return fd;
  92. }
  93. static void sysctl_assert_write(const char *val)
  94. {
  95. int fd = open("/proc/sys/vm/memfd_noexec", O_WRONLY | O_CLOEXEC);
  96. if (fd < 0) {
  97. printf("open sysctl failed: %m\n");
  98. abort();
  99. }
  100. if (write(fd, val, strlen(val)) < 0) {
  101. printf("write sysctl %s failed: %m\n", val);
  102. abort();
  103. }
  104. }
  105. static void sysctl_fail_write(const char *val)
  106. {
  107. int fd = open("/proc/sys/vm/memfd_noexec", O_WRONLY | O_CLOEXEC);
  108. if (fd < 0) {
  109. printf("open sysctl failed: %m\n");
  110. abort();
  111. }
  112. if (write(fd, val, strlen(val)) >= 0) {
  113. printf("write sysctl %s succeeded, but failure expected\n",
  114. val);
  115. abort();
  116. }
  117. }
  118. static void sysctl_assert_equal(const char *val)
  119. {
  120. char *p, buf[128] = {};
  121. int fd = open("/proc/sys/vm/memfd_noexec", O_RDONLY | O_CLOEXEC);
  122. if (fd < 0) {
  123. printf("open sysctl failed: %m\n");
  124. abort();
  125. }
  126. if (read(fd, buf, sizeof(buf)) < 0) {
  127. printf("read sysctl failed: %m\n");
  128. abort();
  129. }
  130. /* Strip trailing whitespace. */
  131. p = buf;
  132. while (!isspace(*p))
  133. p++;
  134. *p = '\0';
  135. if (strcmp(buf, val) != 0) {
  136. printf("unexpected sysctl value: expected %s, got %s\n", val, buf);
  137. abort();
  138. }
  139. }
  140. static int mfd_assert_reopen_fd(int fd_in)
  141. {
  142. int fd;
  143. char path[100];
  144. sprintf(path, "/proc/self/fd/%d", fd_in);
  145. fd = open(path, O_RDWR);
  146. if (fd < 0) {
  147. printf("re-open of existing fd %d failed\n", fd_in);
  148. abort();
  149. }
  150. return fd;
  151. }
  152. static void mfd_fail_new(const char *name, unsigned int flags)
  153. {
  154. int r;
  155. r = sys_memfd_create(name, flags);
  156. if (r >= 0) {
  157. printf("memfd_create(\"%s\", %u) succeeded, but failure expected\n",
  158. name ? name : "NULL", flags);
  159. close(r);
  160. abort();
  161. }
  162. }
  163. static unsigned int mfd_assert_get_seals(int fd)
  164. {
  165. int r;
  166. r = fcntl(fd, F_GET_SEALS);
  167. if (r < 0) {
  168. printf("GET_SEALS(%d) failed: %m\n", fd);
  169. abort();
  170. }
  171. return (unsigned int)r;
  172. }
  173. static void mfd_assert_has_seals(int fd, unsigned int seals)
  174. {
  175. char buf[PATH_MAX];
  176. unsigned int s;
  177. fd2name(fd, buf, PATH_MAX);
  178. s = mfd_assert_get_seals(fd);
  179. if (s != seals) {
  180. printf("%u != %u = GET_SEALS(%s)\n", seals, s, buf);
  181. abort();
  182. }
  183. }
  184. static void mfd_assert_add_seals(int fd, unsigned int seals)
  185. {
  186. int r;
  187. unsigned int s;
  188. s = mfd_assert_get_seals(fd);
  189. r = fcntl(fd, F_ADD_SEALS, seals);
  190. if (r < 0) {
  191. printf("ADD_SEALS(%d, %u -> %u) failed: %m\n", fd, s, seals);
  192. abort();
  193. }
  194. }
  195. static void mfd_fail_add_seals(int fd, unsigned int seals)
  196. {
  197. int r;
  198. unsigned int s;
  199. r = fcntl(fd, F_GET_SEALS);
  200. if (r < 0)
  201. s = 0;
  202. else
  203. s = (unsigned int)r;
  204. r = fcntl(fd, F_ADD_SEALS, seals);
  205. if (r >= 0) {
  206. printf("ADD_SEALS(%d, %u -> %u) didn't fail as expected\n",
  207. fd, s, seals);
  208. abort();
  209. }
  210. }
  211. static void mfd_assert_size(int fd, size_t size)
  212. {
  213. struct stat st;
  214. int r;
  215. r = fstat(fd, &st);
  216. if (r < 0) {
  217. printf("fstat(%d) failed: %m\n", fd);
  218. abort();
  219. } else if (st.st_size != size) {
  220. printf("wrong file size %lld, but expected %lld\n",
  221. (long long)st.st_size, (long long)size);
  222. abort();
  223. }
  224. }
  225. static int mfd_assert_dup(int fd)
  226. {
  227. int r;
  228. r = dup(fd);
  229. if (r < 0) {
  230. printf("dup(%d) failed: %m\n", fd);
  231. abort();
  232. }
  233. return r;
  234. }
  235. static void *mfd_assert_mmap_shared(int fd)
  236. {
  237. void *p;
  238. p = mmap(NULL,
  239. mfd_def_size,
  240. PROT_READ | PROT_WRITE,
  241. MAP_SHARED,
  242. fd,
  243. 0);
  244. if (p == MAP_FAILED) {
  245. printf("mmap() failed: %m\n");
  246. abort();
  247. }
  248. return p;
  249. }
  250. static void *mfd_assert_mmap_read_shared(int fd)
  251. {
  252. void *p;
  253. p = mmap(NULL,
  254. mfd_def_size,
  255. PROT_READ,
  256. MAP_SHARED,
  257. fd,
  258. 0);
  259. if (p == MAP_FAILED) {
  260. printf("mmap() failed: %m\n");
  261. abort();
  262. }
  263. return p;
  264. }
  265. static void *mfd_assert_mmap_private(int fd)
  266. {
  267. void *p;
  268. p = mmap(NULL,
  269. mfd_def_size,
  270. PROT_READ,
  271. MAP_PRIVATE,
  272. fd,
  273. 0);
  274. if (p == MAP_FAILED) {
  275. printf("mmap() failed: %m\n");
  276. abort();
  277. }
  278. return p;
  279. }
  280. static int mfd_assert_open(int fd, int flags, mode_t mode)
  281. {
  282. char buf[512];
  283. int r;
  284. sprintf(buf, "/proc/self/fd/%d", fd);
  285. r = open(buf, flags, mode);
  286. if (r < 0) {
  287. printf("open(%s) failed: %m\n", buf);
  288. abort();
  289. }
  290. return r;
  291. }
  292. static void mfd_fail_open(int fd, int flags, mode_t mode)
  293. {
  294. char buf[512];
  295. int r;
  296. sprintf(buf, "/proc/self/fd/%d", fd);
  297. r = open(buf, flags, mode);
  298. if (r >= 0) {
  299. printf("open(%s) didn't fail as expected\n", buf);
  300. abort();
  301. }
  302. }
  303. static void mfd_assert_read(int fd)
  304. {
  305. char buf[16];
  306. void *p;
  307. ssize_t l;
  308. l = read(fd, buf, sizeof(buf));
  309. if (l != sizeof(buf)) {
  310. printf("read() failed: %m\n");
  311. abort();
  312. }
  313. /* verify PROT_READ *is* allowed */
  314. p = mmap(NULL,
  315. mfd_def_size,
  316. PROT_READ,
  317. MAP_PRIVATE,
  318. fd,
  319. 0);
  320. if (p == MAP_FAILED) {
  321. printf("mmap() failed: %m\n");
  322. abort();
  323. }
  324. munmap(p, mfd_def_size);
  325. /* verify MAP_PRIVATE is *always* allowed (even writable) */
  326. p = mmap(NULL,
  327. mfd_def_size,
  328. PROT_READ | PROT_WRITE,
  329. MAP_PRIVATE,
  330. fd,
  331. 0);
  332. if (p == MAP_FAILED) {
  333. printf("mmap() failed: %m\n");
  334. abort();
  335. }
  336. munmap(p, mfd_def_size);
  337. }
  338. /* Test that PROT_READ + MAP_SHARED mappings work. */
  339. static void mfd_assert_read_shared(int fd)
  340. {
  341. void *p;
  342. /* verify PROT_READ and MAP_SHARED *is* allowed */
  343. p = mmap(NULL,
  344. mfd_def_size,
  345. PROT_READ,
  346. MAP_SHARED,
  347. fd,
  348. 0);
  349. if (p == MAP_FAILED) {
  350. printf("mmap() failed: %m\n");
  351. abort();
  352. }
  353. munmap(p, mfd_def_size);
  354. }
  355. static void mfd_assert_fork_private_write(int fd)
  356. {
  357. int *p;
  358. pid_t pid;
  359. p = mmap(NULL,
  360. mfd_def_size,
  361. PROT_READ | PROT_WRITE,
  362. MAP_PRIVATE,
  363. fd,
  364. 0);
  365. if (p == MAP_FAILED) {
  366. printf("mmap() failed: %m\n");
  367. abort();
  368. }
  369. p[0] = 22;
  370. pid = fork();
  371. if (pid == 0) {
  372. p[0] = 33;
  373. exit(0);
  374. } else {
  375. waitpid(pid, NULL, 0);
  376. if (p[0] != 22) {
  377. printf("MAP_PRIVATE copy-on-write failed: %m\n");
  378. abort();
  379. }
  380. }
  381. munmap(p, mfd_def_size);
  382. }
  383. static void mfd_assert_write(int fd)
  384. {
  385. ssize_t l;
  386. void *p;
  387. int r;
  388. /*
  389. * huegtlbfs does not support write, but we want to
  390. * verify everything else here.
  391. */
  392. if (!hugetlbfs_test) {
  393. /* verify write() succeeds */
  394. l = write(fd, "\0\0\0\0", 4);
  395. if (l != 4) {
  396. printf("write() failed: %m\n");
  397. abort();
  398. }
  399. }
  400. /* verify PROT_READ | PROT_WRITE is allowed */
  401. p = mmap(NULL,
  402. mfd_def_size,
  403. PROT_READ | PROT_WRITE,
  404. MAP_SHARED,
  405. fd,
  406. 0);
  407. if (p == MAP_FAILED) {
  408. printf("mmap() failed: %m\n");
  409. abort();
  410. }
  411. *(char *)p = 0;
  412. munmap(p, mfd_def_size);
  413. /* verify PROT_WRITE is allowed */
  414. p = mmap(NULL,
  415. mfd_def_size,
  416. PROT_WRITE,
  417. MAP_SHARED,
  418. fd,
  419. 0);
  420. if (p == MAP_FAILED) {
  421. printf("mmap() failed: %m\n");
  422. abort();
  423. }
  424. *(char *)p = 0;
  425. munmap(p, mfd_def_size);
  426. /* verify PROT_READ with MAP_SHARED is allowed and a following
  427. * mprotect(PROT_WRITE) allows writing */
  428. p = mmap(NULL,
  429. mfd_def_size,
  430. PROT_READ,
  431. MAP_SHARED,
  432. fd,
  433. 0);
  434. if (p == MAP_FAILED) {
  435. printf("mmap() failed: %m\n");
  436. abort();
  437. }
  438. r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
  439. if (r < 0) {
  440. printf("mprotect() failed: %m\n");
  441. abort();
  442. }
  443. *(char *)p = 0;
  444. munmap(p, mfd_def_size);
  445. /* verify PUNCH_HOLE works */
  446. r = fallocate(fd,
  447. FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
  448. 0,
  449. mfd_def_size);
  450. if (r < 0) {
  451. printf("fallocate(PUNCH_HOLE) failed: %m\n");
  452. abort();
  453. }
  454. }
  455. static void mfd_fail_write(int fd)
  456. {
  457. ssize_t l;
  458. void *p;
  459. int r;
  460. /* verify write() fails */
  461. l = write(fd, "data", 4);
  462. if (l != -EPERM) {
  463. printf("expected EPERM on write(), but got %d: %m\n", (int)l);
  464. abort();
  465. }
  466. /* verify PROT_READ | PROT_WRITE is not allowed */
  467. p = mmap(NULL,
  468. mfd_def_size,
  469. PROT_READ | PROT_WRITE,
  470. MAP_SHARED,
  471. fd,
  472. 0);
  473. if (p != MAP_FAILED) {
  474. printf("mmap() didn't fail as expected\n");
  475. abort();
  476. }
  477. /* verify PROT_WRITE is not allowed */
  478. p = mmap(NULL,
  479. mfd_def_size,
  480. PROT_WRITE,
  481. MAP_SHARED,
  482. fd,
  483. 0);
  484. if (p != MAP_FAILED) {
  485. printf("mmap() didn't fail as expected\n");
  486. abort();
  487. }
  488. /* Verify PROT_READ with MAP_SHARED with a following mprotect is not
  489. * allowed. Note that for r/w the kernel already prevents the mmap. */
  490. p = mmap(NULL,
  491. mfd_def_size,
  492. PROT_READ,
  493. MAP_SHARED,
  494. fd,
  495. 0);
  496. if (p != MAP_FAILED) {
  497. r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
  498. if (r >= 0) {
  499. printf("mmap()+mprotect() didn't fail as expected\n");
  500. abort();
  501. }
  502. munmap(p, mfd_def_size);
  503. }
  504. /* verify PUNCH_HOLE fails */
  505. r = fallocate(fd,
  506. FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
  507. 0,
  508. mfd_def_size);
  509. if (r >= 0) {
  510. printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
  511. abort();
  512. }
  513. }
  514. static void mfd_assert_shrink(int fd)
  515. {
  516. int r, fd2;
  517. r = ftruncate(fd, mfd_def_size / 2);
  518. if (r < 0) {
  519. printf("ftruncate(SHRINK) failed: %m\n");
  520. abort();
  521. }
  522. mfd_assert_size(fd, mfd_def_size / 2);
  523. fd2 = mfd_assert_open(fd,
  524. O_RDWR | O_CREAT | O_TRUNC,
  525. S_IRUSR | S_IWUSR);
  526. close(fd2);
  527. mfd_assert_size(fd, 0);
  528. }
  529. static void mfd_fail_shrink(int fd)
  530. {
  531. int r;
  532. r = ftruncate(fd, mfd_def_size / 2);
  533. if (r >= 0) {
  534. printf("ftruncate(SHRINK) didn't fail as expected\n");
  535. abort();
  536. }
  537. mfd_fail_open(fd,
  538. O_RDWR | O_CREAT | O_TRUNC,
  539. S_IRUSR | S_IWUSR);
  540. }
  541. static void mfd_assert_grow(int fd)
  542. {
  543. int r;
  544. r = ftruncate(fd, mfd_def_size * 2);
  545. if (r < 0) {
  546. printf("ftruncate(GROW) failed: %m\n");
  547. abort();
  548. }
  549. mfd_assert_size(fd, mfd_def_size * 2);
  550. r = fallocate(fd,
  551. 0,
  552. 0,
  553. mfd_def_size * 4);
  554. if (r < 0) {
  555. printf("fallocate(ALLOC) failed: %m\n");
  556. abort();
  557. }
  558. mfd_assert_size(fd, mfd_def_size * 4);
  559. }
  560. static void mfd_fail_grow(int fd)
  561. {
  562. int r;
  563. r = ftruncate(fd, mfd_def_size * 2);
  564. if (r >= 0) {
  565. printf("ftruncate(GROW) didn't fail as expected\n");
  566. abort();
  567. }
  568. r = fallocate(fd,
  569. 0,
  570. 0,
  571. mfd_def_size * 4);
  572. if (r >= 0) {
  573. printf("fallocate(ALLOC) didn't fail as expected\n");
  574. abort();
  575. }
  576. }
  577. static void mfd_assert_grow_write(int fd)
  578. {
  579. static char *buf;
  580. ssize_t l;
  581. /* hugetlbfs does not support write */
  582. if (hugetlbfs_test)
  583. return;
  584. buf = malloc(mfd_def_size * 8);
  585. if (!buf) {
  586. printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
  587. abort();
  588. }
  589. l = pwrite(fd, buf, mfd_def_size * 8, 0);
  590. if (l != (mfd_def_size * 8)) {
  591. printf("pwrite() failed: %m\n");
  592. abort();
  593. }
  594. mfd_assert_size(fd, mfd_def_size * 8);
  595. }
  596. static void mfd_fail_grow_write(int fd)
  597. {
  598. static char *buf;
  599. ssize_t l;
  600. /* hugetlbfs does not support write */
  601. if (hugetlbfs_test)
  602. return;
  603. buf = malloc(mfd_def_size * 8);
  604. if (!buf) {
  605. printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
  606. abort();
  607. }
  608. l = pwrite(fd, buf, mfd_def_size * 8, 0);
  609. if (l == (mfd_def_size * 8)) {
  610. printf("pwrite() didn't fail as expected\n");
  611. abort();
  612. }
  613. }
  614. static void mfd_assert_mode(int fd, int mode)
  615. {
  616. struct stat st;
  617. char buf[PATH_MAX];
  618. fd2name(fd, buf, PATH_MAX);
  619. if (fstat(fd, &st) < 0) {
  620. printf("fstat(%s) failed: %m\n", buf);
  621. abort();
  622. }
  623. if ((st.st_mode & 07777) != mode) {
  624. printf("fstat(%s) wrong file mode 0%04o, but expected 0%04o\n",
  625. buf, (int)st.st_mode & 07777, mode);
  626. abort();
  627. }
  628. }
  629. static void mfd_assert_chmod(int fd, int mode)
  630. {
  631. char buf[PATH_MAX];
  632. fd2name(fd, buf, PATH_MAX);
  633. if (fchmod(fd, mode) < 0) {
  634. printf("fchmod(%s, 0%04o) failed: %m\n", buf, mode);
  635. abort();
  636. }
  637. mfd_assert_mode(fd, mode);
  638. }
  639. static void mfd_fail_chmod(int fd, int mode)
  640. {
  641. struct stat st;
  642. char buf[PATH_MAX];
  643. fd2name(fd, buf, PATH_MAX);
  644. if (fstat(fd, &st) < 0) {
  645. printf("fstat(%s) failed: %m\n", buf);
  646. abort();
  647. }
  648. if (fchmod(fd, mode) == 0) {
  649. printf("fchmod(%s, 0%04o) didn't fail as expected\n",
  650. buf, mode);
  651. abort();
  652. }
  653. /* verify that file mode bits did not change */
  654. mfd_assert_mode(fd, st.st_mode & 07777);
  655. }
  656. static int idle_thread_fn(void *arg)
  657. {
  658. sigset_t set;
  659. int sig;
  660. /* dummy waiter; SIGTERM terminates us anyway */
  661. sigemptyset(&set);
  662. sigaddset(&set, SIGTERM);
  663. sigwait(&set, &sig);
  664. return 0;
  665. }
  666. static pid_t spawn_thread(unsigned int flags, int (*fn)(void *), void *arg)
  667. {
  668. uint8_t *stack;
  669. pid_t pid;
  670. stack = malloc(STACK_SIZE);
  671. if (!stack) {
  672. printf("malloc(STACK_SIZE) failed: %m\n");
  673. abort();
  674. }
  675. pid = clone(fn, stack + STACK_SIZE, SIGCHLD | flags, arg);
  676. if (pid < 0) {
  677. printf("clone() failed: %m\n");
  678. abort();
  679. }
  680. return pid;
  681. }
  682. static void join_thread(pid_t pid)
  683. {
  684. int wstatus;
  685. if (waitpid(pid, &wstatus, 0) < 0) {
  686. printf("newpid thread: waitpid() failed: %m\n");
  687. abort();
  688. }
  689. if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) {
  690. printf("newpid thread: exited with non-zero error code %d\n",
  691. WEXITSTATUS(wstatus));
  692. abort();
  693. }
  694. if (WIFSIGNALED(wstatus)) {
  695. printf("newpid thread: killed by signal %d\n",
  696. WTERMSIG(wstatus));
  697. abort();
  698. }
  699. }
  700. static pid_t spawn_idle_thread(unsigned int flags)
  701. {
  702. return spawn_thread(flags, idle_thread_fn, NULL);
  703. }
  704. static void join_idle_thread(pid_t pid)
  705. {
  706. kill(pid, SIGTERM);
  707. waitpid(pid, NULL, 0);
  708. }
  709. /*
  710. * Test memfd_create() syscall
  711. * Verify syscall-argument validation, including name checks, flag validation
  712. * and more.
  713. */
  714. static void test_create(void)
  715. {
  716. char buf[2048];
  717. int fd;
  718. printf("%s CREATE\n", memfd_str);
  719. /* test NULL name */
  720. mfd_fail_new(NULL, 0);
  721. /* test over-long name (not zero-terminated) */
  722. memset(buf, 0xff, sizeof(buf));
  723. mfd_fail_new(buf, 0);
  724. /* test over-long zero-terminated name */
  725. memset(buf, 0xff, sizeof(buf));
  726. buf[sizeof(buf) - 1] = 0;
  727. mfd_fail_new(buf, 0);
  728. /* verify "" is a valid name */
  729. fd = mfd_assert_new("", 0, 0);
  730. close(fd);
  731. /* verify invalid O_* open flags */
  732. mfd_fail_new("", 0x0100);
  733. mfd_fail_new("", ~MFD_CLOEXEC);
  734. mfd_fail_new("", ~MFD_ALLOW_SEALING);
  735. mfd_fail_new("", ~0);
  736. mfd_fail_new("", 0x80000000U);
  737. /* verify EXEC and NOEXEC_SEAL can't both be set */
  738. mfd_fail_new("", MFD_EXEC | MFD_NOEXEC_SEAL);
  739. /* verify MFD_CLOEXEC is allowed */
  740. fd = mfd_assert_new("", 0, MFD_CLOEXEC);
  741. close(fd);
  742. /* verify MFD_ALLOW_SEALING is allowed */
  743. fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
  744. close(fd);
  745. /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
  746. fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
  747. close(fd);
  748. }
  749. /*
  750. * Test basic sealing
  751. * A very basic sealing test to see whether setting/retrieving seals works.
  752. */
  753. static void test_basic(void)
  754. {
  755. int fd;
  756. printf("%s BASIC\n", memfd_str);
  757. fd = mfd_assert_new("kern_memfd_basic",
  758. mfd_def_size,
  759. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  760. /* add basic seals */
  761. mfd_assert_has_seals(fd, 0);
  762. mfd_assert_add_seals(fd, F_SEAL_SHRINK |
  763. F_SEAL_WRITE);
  764. mfd_assert_has_seals(fd, F_SEAL_SHRINK |
  765. F_SEAL_WRITE);
  766. /* add them again */
  767. mfd_assert_add_seals(fd, F_SEAL_SHRINK |
  768. F_SEAL_WRITE);
  769. mfd_assert_has_seals(fd, F_SEAL_SHRINK |
  770. F_SEAL_WRITE);
  771. /* add more seals and seal against sealing */
  772. mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL);
  773. mfd_assert_has_seals(fd, F_SEAL_SHRINK |
  774. F_SEAL_GROW |
  775. F_SEAL_WRITE |
  776. F_SEAL_SEAL);
  777. /* verify that sealing no longer works */
  778. mfd_fail_add_seals(fd, F_SEAL_GROW);
  779. mfd_fail_add_seals(fd, 0);
  780. close(fd);
  781. /* verify sealing does not work without MFD_ALLOW_SEALING */
  782. fd = mfd_assert_new("kern_memfd_basic",
  783. mfd_def_size,
  784. MFD_CLOEXEC);
  785. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  786. mfd_fail_add_seals(fd, F_SEAL_SHRINK |
  787. F_SEAL_GROW |
  788. F_SEAL_WRITE);
  789. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  790. close(fd);
  791. }
  792. /*
  793. * Test SEAL_WRITE
  794. * Test whether SEAL_WRITE actually prevents modifications.
  795. */
  796. static void test_seal_write(void)
  797. {
  798. int fd;
  799. printf("%s SEAL-WRITE\n", memfd_str);
  800. fd = mfd_assert_new("kern_memfd_seal_write",
  801. mfd_def_size,
  802. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  803. mfd_assert_has_seals(fd, 0);
  804. mfd_assert_add_seals(fd, F_SEAL_WRITE);
  805. mfd_assert_has_seals(fd, F_SEAL_WRITE);
  806. mfd_assert_read(fd);
  807. mfd_fail_write(fd);
  808. mfd_assert_shrink(fd);
  809. mfd_assert_grow(fd);
  810. mfd_fail_grow_write(fd);
  811. close(fd);
  812. }
  813. /*
  814. * Test SEAL_FUTURE_WRITE
  815. * Test whether SEAL_FUTURE_WRITE actually prevents modifications.
  816. */
  817. static void test_seal_future_write(void)
  818. {
  819. int fd, fd2;
  820. void *p;
  821. printf("%s SEAL-FUTURE-WRITE\n", memfd_str);
  822. fd = mfd_assert_new("kern_memfd_seal_future_write",
  823. mfd_def_size,
  824. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  825. p = mfd_assert_mmap_shared(fd);
  826. mfd_assert_has_seals(fd, 0);
  827. mfd_assert_add_seals(fd, F_SEAL_FUTURE_WRITE);
  828. mfd_assert_has_seals(fd, F_SEAL_FUTURE_WRITE);
  829. /* read should pass, writes should fail */
  830. mfd_assert_read(fd);
  831. mfd_assert_read_shared(fd);
  832. mfd_fail_write(fd);
  833. fd2 = mfd_assert_reopen_fd(fd);
  834. /* read should pass, writes should still fail */
  835. mfd_assert_read(fd2);
  836. mfd_assert_read_shared(fd2);
  837. mfd_fail_write(fd2);
  838. mfd_assert_fork_private_write(fd);
  839. munmap(p, mfd_def_size);
  840. close(fd2);
  841. close(fd);
  842. }
  843. static void test_seal_write_map_read_shared(void)
  844. {
  845. int fd;
  846. void *p;
  847. printf("%s SEAL-WRITE-MAP-READ\n", memfd_str);
  848. fd = mfd_assert_new("kern_memfd_seal_write_map_read",
  849. mfd_def_size,
  850. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  851. mfd_assert_add_seals(fd, F_SEAL_WRITE);
  852. mfd_assert_has_seals(fd, F_SEAL_WRITE);
  853. p = mfd_assert_mmap_read_shared(fd);
  854. mfd_assert_read(fd);
  855. mfd_assert_read_shared(fd);
  856. mfd_fail_write(fd);
  857. munmap(p, mfd_def_size);
  858. close(fd);
  859. }
  860. /*
  861. * Test SEAL_SHRINK
  862. * Test whether SEAL_SHRINK actually prevents shrinking
  863. */
  864. static void test_seal_shrink(void)
  865. {
  866. int fd;
  867. printf("%s SEAL-SHRINK\n", memfd_str);
  868. fd = mfd_assert_new("kern_memfd_seal_shrink",
  869. mfd_def_size,
  870. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  871. mfd_assert_has_seals(fd, 0);
  872. mfd_assert_add_seals(fd, F_SEAL_SHRINK);
  873. mfd_assert_has_seals(fd, F_SEAL_SHRINK);
  874. mfd_assert_read(fd);
  875. mfd_assert_write(fd);
  876. mfd_fail_shrink(fd);
  877. mfd_assert_grow(fd);
  878. mfd_assert_grow_write(fd);
  879. close(fd);
  880. }
  881. /*
  882. * Test SEAL_GROW
  883. * Test whether SEAL_GROW actually prevents growing
  884. */
  885. static void test_seal_grow(void)
  886. {
  887. int fd;
  888. printf("%s SEAL-GROW\n", memfd_str);
  889. fd = mfd_assert_new("kern_memfd_seal_grow",
  890. mfd_def_size,
  891. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  892. mfd_assert_has_seals(fd, 0);
  893. mfd_assert_add_seals(fd, F_SEAL_GROW);
  894. mfd_assert_has_seals(fd, F_SEAL_GROW);
  895. mfd_assert_read(fd);
  896. mfd_assert_write(fd);
  897. mfd_assert_shrink(fd);
  898. mfd_fail_grow(fd);
  899. mfd_fail_grow_write(fd);
  900. close(fd);
  901. }
  902. /*
  903. * Test SEAL_SHRINK | SEAL_GROW
  904. * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
  905. */
  906. static void test_seal_resize(void)
  907. {
  908. int fd;
  909. printf("%s SEAL-RESIZE\n", memfd_str);
  910. fd = mfd_assert_new("kern_memfd_seal_resize",
  911. mfd_def_size,
  912. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  913. mfd_assert_has_seals(fd, 0);
  914. mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
  915. mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
  916. mfd_assert_read(fd);
  917. mfd_assert_write(fd);
  918. mfd_fail_shrink(fd);
  919. mfd_fail_grow(fd);
  920. mfd_fail_grow_write(fd);
  921. close(fd);
  922. }
  923. /*
  924. * Test SEAL_EXEC
  925. * Test fd is created with exec and allow sealing.
  926. * chmod() cannot change x bits after sealing.
  927. */
  928. static void test_exec_seal(void)
  929. {
  930. int fd;
  931. printf("%s SEAL-EXEC\n", memfd_str);
  932. printf("%s Apply SEAL_EXEC\n", memfd_str);
  933. fd = mfd_assert_new("kern_memfd_seal_exec",
  934. mfd_def_size,
  935. MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_EXEC);
  936. mfd_assert_mode(fd, 0777);
  937. mfd_assert_chmod(fd, 0644);
  938. mfd_assert_has_seals(fd, 0);
  939. mfd_assert_add_seals(fd, F_SEAL_EXEC);
  940. mfd_assert_has_seals(fd, F_SEAL_EXEC);
  941. mfd_assert_chmod(fd, 0600);
  942. mfd_fail_chmod(fd, 0777);
  943. mfd_fail_chmod(fd, 0670);
  944. mfd_fail_chmod(fd, 0605);
  945. mfd_fail_chmod(fd, 0700);
  946. mfd_fail_chmod(fd, 0100);
  947. mfd_assert_chmod(fd, 0666);
  948. mfd_assert_write(fd);
  949. close(fd);
  950. printf("%s Apply ALL_SEALS\n", memfd_str);
  951. fd = mfd_assert_new("kern_memfd_seal_exec",
  952. mfd_def_size,
  953. MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_EXEC);
  954. mfd_assert_mode(fd, 0777);
  955. mfd_assert_chmod(fd, 0700);
  956. mfd_assert_has_seals(fd, 0);
  957. mfd_assert_add_seals(fd, F_SEAL_EXEC);
  958. mfd_assert_has_seals(fd, F_WX_SEALS);
  959. mfd_fail_chmod(fd, 0711);
  960. mfd_fail_chmod(fd, 0600);
  961. mfd_fail_write(fd);
  962. close(fd);
  963. }
  964. /*
  965. * Test EXEC_NO_SEAL
  966. * Test fd is created with exec and not allow sealing.
  967. */
  968. static void test_exec_no_seal(void)
  969. {
  970. int fd;
  971. printf("%s EXEC_NO_SEAL\n", memfd_str);
  972. /* Create with EXEC but without ALLOW_SEALING */
  973. fd = mfd_assert_new("kern_memfd_exec_no_sealing",
  974. mfd_def_size,
  975. MFD_CLOEXEC | MFD_EXEC);
  976. mfd_assert_mode(fd, 0777);
  977. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  978. mfd_assert_chmod(fd, 0666);
  979. close(fd);
  980. }
  981. /*
  982. * Test memfd_create with MFD_NOEXEC flag
  983. */
  984. static void test_noexec_seal(void)
  985. {
  986. int fd;
  987. printf("%s NOEXEC_SEAL\n", memfd_str);
  988. /* Create with NOEXEC and ALLOW_SEALING */
  989. fd = mfd_assert_new("kern_memfd_noexec",
  990. mfd_def_size,
  991. MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL);
  992. mfd_assert_mode(fd, 0666);
  993. mfd_assert_has_seals(fd, F_SEAL_EXEC);
  994. mfd_fail_chmod(fd, 0777);
  995. close(fd);
  996. /* Create with NOEXEC but without ALLOW_SEALING */
  997. fd = mfd_assert_new("kern_memfd_noexec",
  998. mfd_def_size,
  999. MFD_CLOEXEC | MFD_NOEXEC_SEAL);
  1000. mfd_assert_mode(fd, 0666);
  1001. mfd_assert_has_seals(fd, F_SEAL_EXEC);
  1002. mfd_fail_chmod(fd, 0777);
  1003. close(fd);
  1004. }
  1005. static void test_sysctl_sysctl0(void)
  1006. {
  1007. int fd;
  1008. sysctl_assert_equal("0");
  1009. fd = mfd_assert_new("kern_memfd_sysctl_0_dfl",
  1010. mfd_def_size,
  1011. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  1012. mfd_assert_mode(fd, 0777);
  1013. mfd_assert_has_seals(fd, 0);
  1014. mfd_assert_chmod(fd, 0644);
  1015. close(fd);
  1016. }
  1017. static void test_sysctl_set_sysctl0(void)
  1018. {
  1019. sysctl_assert_write("0");
  1020. test_sysctl_sysctl0();
  1021. }
  1022. static void test_sysctl_sysctl1(void)
  1023. {
  1024. int fd;
  1025. sysctl_assert_equal("1");
  1026. fd = mfd_assert_new("kern_memfd_sysctl_1_dfl",
  1027. mfd_def_size,
  1028. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  1029. mfd_assert_mode(fd, 0666);
  1030. mfd_assert_has_seals(fd, F_SEAL_EXEC);
  1031. mfd_fail_chmod(fd, 0777);
  1032. close(fd);
  1033. fd = mfd_assert_new("kern_memfd_sysctl_1_exec",
  1034. mfd_def_size,
  1035. MFD_CLOEXEC | MFD_EXEC | MFD_ALLOW_SEALING);
  1036. mfd_assert_mode(fd, 0777);
  1037. mfd_assert_has_seals(fd, 0);
  1038. mfd_assert_chmod(fd, 0644);
  1039. close(fd);
  1040. fd = mfd_assert_new("kern_memfd_sysctl_1_noexec",
  1041. mfd_def_size,
  1042. MFD_CLOEXEC | MFD_NOEXEC_SEAL | MFD_ALLOW_SEALING);
  1043. mfd_assert_mode(fd, 0666);
  1044. mfd_assert_has_seals(fd, F_SEAL_EXEC);
  1045. mfd_fail_chmod(fd, 0777);
  1046. close(fd);
  1047. }
  1048. static void test_sysctl_set_sysctl1(void)
  1049. {
  1050. sysctl_assert_write("1");
  1051. test_sysctl_sysctl1();
  1052. }
  1053. static void test_sysctl_sysctl2(void)
  1054. {
  1055. int fd;
  1056. sysctl_assert_equal("2");
  1057. fd = mfd_assert_new("kern_memfd_sysctl_2_dfl",
  1058. mfd_def_size,
  1059. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  1060. mfd_assert_mode(fd, 0666);
  1061. mfd_assert_has_seals(fd, F_SEAL_EXEC);
  1062. mfd_fail_chmod(fd, 0777);
  1063. close(fd);
  1064. mfd_fail_new("kern_memfd_sysctl_2_exec",
  1065. MFD_CLOEXEC | MFD_EXEC | MFD_ALLOW_SEALING);
  1066. fd = mfd_assert_new("kern_memfd_sysctl_2_noexec",
  1067. mfd_def_size,
  1068. MFD_CLOEXEC | MFD_NOEXEC_SEAL | MFD_ALLOW_SEALING);
  1069. mfd_assert_mode(fd, 0666);
  1070. mfd_assert_has_seals(fd, F_SEAL_EXEC);
  1071. mfd_fail_chmod(fd, 0777);
  1072. close(fd);
  1073. }
  1074. static void test_sysctl_set_sysctl2(void)
  1075. {
  1076. sysctl_assert_write("2");
  1077. test_sysctl_sysctl2();
  1078. }
  1079. static int sysctl_simple_child(void *arg)
  1080. {
  1081. printf("%s sysctl 0\n", memfd_str);
  1082. test_sysctl_set_sysctl0();
  1083. printf("%s sysctl 1\n", memfd_str);
  1084. test_sysctl_set_sysctl1();
  1085. printf("%s sysctl 0\n", memfd_str);
  1086. test_sysctl_set_sysctl0();
  1087. printf("%s sysctl 2\n", memfd_str);
  1088. test_sysctl_set_sysctl2();
  1089. printf("%s sysctl 1\n", memfd_str);
  1090. test_sysctl_set_sysctl1();
  1091. printf("%s sysctl 0\n", memfd_str);
  1092. test_sysctl_set_sysctl0();
  1093. return 0;
  1094. }
  1095. /*
  1096. * Test sysctl
  1097. * A very basic test to make sure the core sysctl semantics work.
  1098. */
  1099. static void test_sysctl_simple(void)
  1100. {
  1101. int pid = spawn_thread(CLONE_NEWPID, sysctl_simple_child, NULL);
  1102. join_thread(pid);
  1103. }
  1104. static int sysctl_nested(void *arg)
  1105. {
  1106. void (*fn)(void) = arg;
  1107. fn();
  1108. return 0;
  1109. }
  1110. static int sysctl_nested_wait(void *arg)
  1111. {
  1112. int sem = semget(SEM_KEY, 1, 0600);
  1113. struct sembuf sembuf;
  1114. if (sem < 0) {
  1115. perror("semget:");
  1116. abort();
  1117. }
  1118. sembuf.sem_num = 0;
  1119. sembuf.sem_flg = 0;
  1120. sembuf.sem_op = 0;
  1121. if (semop(sem, &sembuf, 1) < 0) {
  1122. perror("semop:");
  1123. abort();
  1124. }
  1125. return sysctl_nested(arg);
  1126. }
  1127. static void test_sysctl_sysctl1_failset(void)
  1128. {
  1129. sysctl_fail_write("0");
  1130. test_sysctl_sysctl1();
  1131. }
  1132. static void test_sysctl_sysctl2_failset(void)
  1133. {
  1134. sysctl_fail_write("1");
  1135. test_sysctl_sysctl2();
  1136. sysctl_fail_write("0");
  1137. test_sysctl_sysctl2();
  1138. }
  1139. static int sysctl_nested_child(void *arg)
  1140. {
  1141. int pid, sem;
  1142. union semun semun;
  1143. struct sembuf sembuf;
  1144. printf("%s nested sysctl 0\n", memfd_str);
  1145. sysctl_assert_write("0");
  1146. /* A further nested pidns works the same. */
  1147. pid = spawn_thread(CLONE_NEWPID, sysctl_simple_child, NULL);
  1148. join_thread(pid);
  1149. printf("%s nested sysctl 1\n", memfd_str);
  1150. sysctl_assert_write("1");
  1151. /* Child inherits our setting. */
  1152. pid = spawn_thread(CLONE_NEWPID, sysctl_nested, test_sysctl_sysctl1);
  1153. join_thread(pid);
  1154. /* Child cannot raise the setting. */
  1155. pid = spawn_thread(CLONE_NEWPID, sysctl_nested,
  1156. test_sysctl_sysctl1_failset);
  1157. join_thread(pid);
  1158. /* Child can lower the setting. */
  1159. pid = spawn_thread(CLONE_NEWPID, sysctl_nested,
  1160. test_sysctl_set_sysctl2);
  1161. join_thread(pid);
  1162. /* Child lowering the setting has no effect on our setting. */
  1163. test_sysctl_sysctl1();
  1164. printf("%s nested sysctl 2\n", memfd_str);
  1165. sysctl_assert_write("2");
  1166. /* Child inherits our setting. */
  1167. pid = spawn_thread(CLONE_NEWPID, sysctl_nested, test_sysctl_sysctl2);
  1168. join_thread(pid);
  1169. /* Child cannot raise the setting. */
  1170. pid = spawn_thread(CLONE_NEWPID, sysctl_nested,
  1171. test_sysctl_sysctl2_failset);
  1172. join_thread(pid);
  1173. sem = semget(SEM_KEY, 1, IPC_CREAT | 0600);
  1174. if (sem < 0) {
  1175. perror("semget:");
  1176. return 1;
  1177. }
  1178. semun.val = 1;
  1179. sembuf.sem_op = -1;
  1180. sembuf.sem_flg = 0;
  1181. sembuf.sem_num = 0;
  1182. /* Verify that the rules are actually inherited after fork. */
  1183. printf("%s nested sysctl 0 -> 1 after fork\n", memfd_str);
  1184. sysctl_assert_write("0");
  1185. if (semctl(sem, 0, SETVAL, semun) < 0) {
  1186. perror("semctl:");
  1187. return 1;
  1188. }
  1189. pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait,
  1190. test_sysctl_sysctl1_failset);
  1191. sysctl_assert_write("1");
  1192. /* Allow child to continue */
  1193. if (semop(sem, &sembuf, 1) < 0) {
  1194. perror("semop:");
  1195. return 1;
  1196. }
  1197. join_thread(pid);
  1198. printf("%s nested sysctl 0 -> 2 after fork\n", memfd_str);
  1199. sysctl_assert_write("0");
  1200. if (semctl(sem, 0, SETVAL, semun) < 0) {
  1201. perror("semctl:");
  1202. return 1;
  1203. }
  1204. pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait,
  1205. test_sysctl_sysctl2_failset);
  1206. sysctl_assert_write("2");
  1207. /* Allow child to continue */
  1208. if (semop(sem, &sembuf, 1) < 0) {
  1209. perror("semop:");
  1210. return 1;
  1211. }
  1212. join_thread(pid);
  1213. /*
  1214. * Verify that the current effective setting is saved on fork, meaning
  1215. * that the parent lowering the sysctl doesn't affect already-forked
  1216. * children.
  1217. */
  1218. printf("%s nested sysctl 2 -> 1 after fork\n", memfd_str);
  1219. sysctl_assert_write("2");
  1220. if (semctl(sem, 0, SETVAL, semun) < 0) {
  1221. perror("semctl:");
  1222. return 1;
  1223. }
  1224. pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait,
  1225. test_sysctl_sysctl2);
  1226. sysctl_assert_write("1");
  1227. /* Allow child to continue */
  1228. if (semop(sem, &sembuf, 1) < 0) {
  1229. perror("semop:");
  1230. return 1;
  1231. }
  1232. join_thread(pid);
  1233. printf("%s nested sysctl 2 -> 0 after fork\n", memfd_str);
  1234. sysctl_assert_write("2");
  1235. if (semctl(sem, 0, SETVAL, semun) < 0) {
  1236. perror("semctl:");
  1237. return 1;
  1238. }
  1239. pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait,
  1240. test_sysctl_sysctl2);
  1241. sysctl_assert_write("0");
  1242. /* Allow child to continue */
  1243. if (semop(sem, &sembuf, 1) < 0) {
  1244. perror("semop:");
  1245. return 1;
  1246. }
  1247. join_thread(pid);
  1248. printf("%s nested sysctl 1 -> 0 after fork\n", memfd_str);
  1249. sysctl_assert_write("1");
  1250. if (semctl(sem, 0, SETVAL, semun) < 0) {
  1251. perror("semctl:");
  1252. return 1;
  1253. }
  1254. pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait,
  1255. test_sysctl_sysctl1);
  1256. sysctl_assert_write("0");
  1257. /* Allow child to continue */
  1258. if (semop(sem, &sembuf, 1) < 0) {
  1259. perror("semop:");
  1260. return 1;
  1261. }
  1262. join_thread(pid);
  1263. semctl(sem, 0, IPC_RMID);
  1264. return 0;
  1265. }
  1266. /*
  1267. * Test sysctl with nested pid namespaces
  1268. * Make sure that the sysctl nesting semantics work correctly.
  1269. */
  1270. static void test_sysctl_nested(void)
  1271. {
  1272. int pid = spawn_thread(CLONE_NEWPID, sysctl_nested_child, NULL);
  1273. join_thread(pid);
  1274. }
  1275. /*
  1276. * Test sharing via dup()
  1277. * Test that seals are shared between dupped FDs and they're all equal.
  1278. */
  1279. static void test_share_dup(char *banner, char *b_suffix)
  1280. {
  1281. int fd, fd2;
  1282. printf("%s %s %s\n", memfd_str, banner, b_suffix);
  1283. fd = mfd_assert_new("kern_memfd_share_dup",
  1284. mfd_def_size,
  1285. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  1286. mfd_assert_has_seals(fd, 0);
  1287. fd2 = mfd_assert_dup(fd);
  1288. mfd_assert_has_seals(fd2, 0);
  1289. mfd_assert_add_seals(fd, F_SEAL_WRITE);
  1290. mfd_assert_has_seals(fd, F_SEAL_WRITE);
  1291. mfd_assert_has_seals(fd2, F_SEAL_WRITE);
  1292. mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
  1293. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
  1294. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
  1295. mfd_assert_add_seals(fd, F_SEAL_SEAL);
  1296. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
  1297. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
  1298. mfd_fail_add_seals(fd, F_SEAL_GROW);
  1299. mfd_fail_add_seals(fd2, F_SEAL_GROW);
  1300. mfd_fail_add_seals(fd, F_SEAL_SEAL);
  1301. mfd_fail_add_seals(fd2, F_SEAL_SEAL);
  1302. close(fd2);
  1303. mfd_fail_add_seals(fd, F_SEAL_GROW);
  1304. close(fd);
  1305. }
  1306. /*
  1307. * Test sealing with active mmap()s
  1308. * Modifying seals is only allowed if no other mmap() refs exist.
  1309. */
  1310. static void test_share_mmap(char *banner, char *b_suffix)
  1311. {
  1312. int fd;
  1313. void *p;
  1314. printf("%s %s %s\n", memfd_str, banner, b_suffix);
  1315. fd = mfd_assert_new("kern_memfd_share_mmap",
  1316. mfd_def_size,
  1317. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  1318. mfd_assert_has_seals(fd, 0);
  1319. /* shared/writable ref prevents sealing WRITE, but allows others */
  1320. p = mfd_assert_mmap_shared(fd);
  1321. mfd_fail_add_seals(fd, F_SEAL_WRITE);
  1322. mfd_assert_has_seals(fd, 0);
  1323. mfd_assert_add_seals(fd, F_SEAL_SHRINK);
  1324. mfd_assert_has_seals(fd, F_SEAL_SHRINK);
  1325. munmap(p, mfd_def_size);
  1326. /* readable ref allows sealing */
  1327. p = mfd_assert_mmap_private(fd);
  1328. mfd_assert_add_seals(fd, F_SEAL_WRITE);
  1329. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
  1330. munmap(p, mfd_def_size);
  1331. close(fd);
  1332. }
  1333. /*
  1334. * Test sealing with open(/proc/self/fd/%d)
  1335. * Via /proc we can get access to a separate file-context for the same memfd.
  1336. * This is *not* like dup(), but like a real separate open(). Make sure the
  1337. * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
  1338. */
  1339. static void test_share_open(char *banner, char *b_suffix)
  1340. {
  1341. int fd, fd2;
  1342. printf("%s %s %s\n", memfd_str, banner, b_suffix);
  1343. fd = mfd_assert_new("kern_memfd_share_open",
  1344. mfd_def_size,
  1345. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  1346. mfd_assert_has_seals(fd, 0);
  1347. fd2 = mfd_assert_open(fd, O_RDWR, 0);
  1348. mfd_assert_add_seals(fd, F_SEAL_WRITE);
  1349. mfd_assert_has_seals(fd, F_SEAL_WRITE);
  1350. mfd_assert_has_seals(fd2, F_SEAL_WRITE);
  1351. mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
  1352. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
  1353. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
  1354. close(fd);
  1355. fd = mfd_assert_open(fd2, O_RDONLY, 0);
  1356. mfd_fail_add_seals(fd, F_SEAL_SEAL);
  1357. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
  1358. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
  1359. close(fd2);
  1360. fd2 = mfd_assert_open(fd, O_RDWR, 0);
  1361. mfd_assert_add_seals(fd2, F_SEAL_SEAL);
  1362. mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
  1363. mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
  1364. close(fd2);
  1365. close(fd);
  1366. }
  1367. /*
  1368. * Test sharing via fork()
  1369. * Test whether seal-modifications work as expected with forked children.
  1370. */
  1371. static void test_share_fork(char *banner, char *b_suffix)
  1372. {
  1373. int fd;
  1374. pid_t pid;
  1375. printf("%s %s %s\n", memfd_str, banner, b_suffix);
  1376. fd = mfd_assert_new("kern_memfd_share_fork",
  1377. mfd_def_size,
  1378. MFD_CLOEXEC | MFD_ALLOW_SEALING);
  1379. mfd_assert_has_seals(fd, 0);
  1380. pid = spawn_idle_thread(0);
  1381. mfd_assert_add_seals(fd, F_SEAL_SEAL);
  1382. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  1383. mfd_fail_add_seals(fd, F_SEAL_WRITE);
  1384. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  1385. join_idle_thread(pid);
  1386. mfd_fail_add_seals(fd, F_SEAL_WRITE);
  1387. mfd_assert_has_seals(fd, F_SEAL_SEAL);
  1388. close(fd);
  1389. }
  1390. static bool pid_ns_supported(void)
  1391. {
  1392. return access("/proc/self/ns/pid", F_OK) == 0;
  1393. }
  1394. int main(int argc, char **argv)
  1395. {
  1396. pid_t pid;
  1397. if (argc == 2) {
  1398. if (!strcmp(argv[1], "hugetlbfs")) {
  1399. unsigned long hpage_size = default_huge_page_size();
  1400. if (!hpage_size) {
  1401. printf("Unable to determine huge page size\n");
  1402. abort();
  1403. }
  1404. hugetlbfs_test = 1;
  1405. memfd_str = MEMFD_HUGE_STR;
  1406. mfd_def_size = hpage_size * 2;
  1407. } else {
  1408. printf("Unknown option: %s\n", argv[1]);
  1409. abort();
  1410. }
  1411. }
  1412. test_create();
  1413. test_basic();
  1414. test_exec_seal();
  1415. test_exec_no_seal();
  1416. test_noexec_seal();
  1417. test_seal_write();
  1418. test_seal_future_write();
  1419. test_seal_write_map_read_shared();
  1420. test_seal_shrink();
  1421. test_seal_grow();
  1422. test_seal_resize();
  1423. if (pid_ns_supported()) {
  1424. test_sysctl_simple();
  1425. test_sysctl_nested();
  1426. } else {
  1427. printf("PID namespaces are not supported; skipping sysctl tests\n");
  1428. }
  1429. test_share_dup("SHARE-DUP", "");
  1430. test_share_mmap("SHARE-MMAP", "");
  1431. test_share_open("SHARE-OPEN", "");
  1432. test_share_fork("SHARE-FORK", "");
  1433. /* Run test-suite in a multi-threaded environment with a shared
  1434. * file-table. */
  1435. pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
  1436. test_share_dup("SHARE-DUP", SHARED_FT_STR);
  1437. test_share_mmap("SHARE-MMAP", SHARED_FT_STR);
  1438. test_share_open("SHARE-OPEN", SHARED_FT_STR);
  1439. test_share_fork("SHARE-FORK", SHARED_FT_STR);
  1440. join_idle_thread(pid);
  1441. printf("memfd: DONE\n");
  1442. return 0;
  1443. }