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