Linux Audio

Check our new training course

Loading...
   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;
  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	else
 227		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 to
 430	 * 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 following
 470	 * 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 not
 540	 * 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() syscall
 815 * Verify syscall-argument validation, including name checks, flag validation
 816 * 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 sealing
 866 * 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_WRITE
 918 * 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_WRITE
 944 * 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_SHRINK
 984 * Test whether SEAL_SHRINK actually prevents shrinking
 985 */
 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_GROW
1010 * Test whether SEAL_GROW actually prevents growing
1011 */
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_GROW
1036 * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
1037 */
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_EXEC
1062 * 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_SEAL
1113 * 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 flag
1133 */
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 sysctl
1274 * 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, meaning
1370	 * that the parent lowering the sysctl doesn't affect already-forked
1371	 * 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 namespaces
1402 * 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()s
1454 * 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 the
1489 * 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 childs.
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 shared
1603	 * 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}