brintos

brintos / linux-shallow public Read only

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