Linux Audio

Check our new training course

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