8static int write_capability(
int protection) {
9 int failed = 0, fd = -1;
10 const size_t page = sysconf(_SC_PAGESIZE);
11 char* shared = MAP_FAILED;
12 char*
private = MAP_FAILED;
13 unsigned char resident[2];
14 CHECK((fd = mf_make(2 * page)) >= 0);
15 CHECK(pwrite(fd,
"a", 1, 0) == 1);
16 shared = mmap(NULL, 2 * page, protection, MAP_SHARED, fd, 0);
17 CHECK(shared != MAP_FAILED);
19 CHECK(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE | F_SEAL_GROW) == -1 && errno == EBUSY);
20 CHECK(fcntl(fd, F_GET_SEALS) == 0);
21 CHECK(!mprotect(shared, 2 * page, PROT_NONE));
22 CHECK(!madvise(shared, 2 * page, MADV_DONTNEED));
23 CHECK(!mincore(shared, 2 * page, resident));
24 CHECK(!ftruncate(fd, 3 * page));
25 CHECK(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == -1 && errno == EBUSY);
26 CHECK(!munmap(shared, 2 * page));
28 private = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
29 CHECK(
private != MAP_FAILED &&
private[0] ==
'a');
31 CHECK(!fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE));
32 CHECK(
private[0] ==
'p' && !mf_contents(fd, 0,
"a", 1));
33 shared = mmap(NULL, 2 * page, PROT_READ, MAP_SHARED, fd, 0);
34 CHECK(shared != MAP_FAILED && shared[0] ==
'a');
35 CHECK(mprotect(shared, 2 * page, PROT_READ | PROT_WRITE) == -1 && errno == EACCES);
36 CHECK(mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) == MAP_FAILED &&
39 if (
private != MAP_FAILED)
40 munmap(
private, page);
41 if (shared != MAP_FAILED)
42 munmap(shared, 2 * page);
47static int future_mappings(
void) {
48 int failed = 0, fd = -1, split = 0, prefix_moved = 0;
49 const size_t page = sysconf(_SC_PAGESIZE);
50 char *old = MAP_FAILED, *old_read = MAP_FAILED, *new_read = MAP_FAILED;
51 char *
private = MAP_FAILED, *victim = MAP_FAILED, *moved = MAP_FAILED;
52 unsigned char residency;
53 CHECK((fd = mf_make(3 * page)) >= 0);
54 CHECK(pwrite(fd,
"a", 1, 0) == 1 && pwrite(fd,
"c", 1, 2 * page) == 1);
55 old = mmap(NULL, 3 * page, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
56 old_read = mmap(NULL, page, PROT_READ, MAP_SHARED, fd, 0);
57 CHECK(old != MAP_FAILED && old_read != MAP_FAILED);
58 CHECK(!fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE));
60 CHECK(!mf_contents(fd, 0,
"b", 1));
61 CHECK(!mprotect(old_read, page, PROT_READ | PROT_WRITE));
63 CHECK(old[0] ==
'd' && !mf_contents(fd, 0,
"d", 1));
64 CHECK(pwrite(fd,
"x", 1, 0) == -1 && errno == EPERM);
65 CHECK(mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) == MAP_FAILED &&
67 new_read = mmap(NULL, page, PROT_READ, MAP_SHARED, fd, 0);
68 CHECK(new_read != MAP_FAILED && new_read[0] ==
'd');
69 CHECK(mprotect(new_read, page, PROT_READ | PROT_WRITE) == -1 && errno == EACCES);
70 private = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
71 CHECK(
private != MAP_FAILED);
73 CHECK(new_read[0] ==
'd' && !mf_contents(fd, 0,
"d", 1));
74 victim = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
75 CHECK(victim != MAP_FAILED);
76 memset(victim, 0x5a, page);
77 CHECK(mmap(victim, page, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0) == MAP_FAILED &&
79 CHECK(!mincore(victim, page, &residency) && (residency & 1));
80 for (
size_t n = 0; n < page; ++n)
81 CHECK(victim[n] == 0x5a);
82 CHECK(!mprotect(old, 3 * page, PROT_READ));
83 CHECK(!munmap(old + page, page));
85 CHECK(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE | F_SEAL_GROW) == -1 && errno == EBUSY);
86 CHECK(fcntl(fd, F_GET_SEALS) == F_SEAL_FUTURE_WRITE);
87 moved = mremap(old, page, page, MREMAP_MAYMOVE | MREMAP_FIXED, victim);
88 CHECK(moved == victim);
91 CHECK(!madvise(moved, page, MADV_DONTNEED) && moved[0] ==
'd');
92 CHECK(!mprotect(moved, page, PROT_READ | PROT_WRITE));
94 CHECK(new_read[0] ==
'e' && !mf_contents(fd, 0,
"e", 1) &&
private[0] ==
'p');
95 CHECK(!munmap(old_read, page));
96 old_read = MAP_FAILED;
97 CHECK(!munmap(moved, page));
99 CHECK(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == -1 && errno == EBUSY);
101 CHECK(mmap(old + 2 * page, page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
102 -1, 0) == old + 2 * page);
103 CHECK(!fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE));
104 CHECK(fcntl(fd, F_GET_SEALS) == (F_SEAL_WRITE | F_SEAL_FUTURE_WRITE));
105 CHECK(new_read[0] ==
'e' &&
private[0] ==
'p');
107 if (moved != MAP_FAILED)
109 if (victim != MAP_FAILED)
110 munmap(victim, page);
111 if (
private != MAP_FAILED)
112 munmap(
private, page);
113 if (new_read != MAP_FAILED)
114 munmap(new_read, page);
115 if (old_read != MAP_FAILED)
116 munmap(old_read, page);
117 if (old != MAP_FAILED) {
121 munmap(old + 2 * page, page);
123 munmap(old, 3 * page);
129static int resize_nonmutation(
void) {
130 int failed = 0, fd = -1;
131 const size_t page = sysconf(_SC_PAGESIZE);
132 char* mapping = MAP_FAILED;
133 CHECK((fd = mf_make(2 * page)) >= 0);
134 mapping = mmap(NULL, 2 * page, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
135 CHECK(mapping != MAP_FAILED);
138 CHECK(!fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK));
139 CHECK(ftruncate(fd, page) == -1 && errno == EPERM);
140 CHECK(ftruncate(fd, 3 * page) == -1 && errno == EPERM);
141 CHECK(!mf_size(fd, 2 * page));
142 CHECK(mapping[0] ==
'a' && mapping[page] ==
'b');
143 CHECK(!madvise(mapping, 2 * page, MADV_DONTNEED));
144 CHECK(mapping[0] ==
'a' && mapping[page] ==
'b');
146 CHECK(!mf_contents(fd, page,
"c", 1));
148 if (mapping != MAP_FAILED)
149 munmap(mapping, 2 * page);
154int memfd_mappings(
void) {
155 return write_capability(PROT_READ) || write_capability(PROT_NONE) ||
156 write_capability(PROT_READ | PROT_WRITE) || future_mappings() || resize_nonmutation();