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