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