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