8static int replacement_charge(
void) {
10 struct rp_file file = {.fd = -1};
11 unsigned char* mapping = MAP_FAILED;
12 void* extra = MAP_FAILED;
13 CHECK(rp_create(&file, RP_MEMFD) == 0);
14 mapping = mmap(NULL, 2 * rp_page, PROT_READ, MAP_SHARED, file.fd, 0);
15 extra = mmap(NULL, 2 * rp_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
16 CHECK(mapping != MAP_FAILED && extra != MAP_FAILED);
17 CHECK(rp_limit(2 * rp_page) == 0 && mlock(mapping, 2 * rp_page) == 0);
19 CHECK(remap_file_pages(mapping, 2 * rp_page, 0, 4, MAP_NONBLOCK) == -1 && errno == EAGAIN);
20 CHECK(rp_matches(mapping, 0, 2 * rp_page, 0));
21 CHECK(rp_limit(4 * rp_page) == 0);
22 CHECK(remap_file_pages(mapping, 2 * rp_page, 0, 4, MAP_NONBLOCK) == 0);
23 CHECK(rp_matches(mapping, 4 * rp_page, 2 * rp_page, 0));
25 CHECK(mlock(extra, 2 * rp_page) == 0);
27 CHECK(msync(mapping, 2 * rp_page, MS_SYNC | MS_INVALIDATE) == -1 && errno == EBUSY);
28 CHECK(munlock(extra, 2 * rp_page) == 0 && rp_limit(0) == 0);
30 CHECK(remap_file_pages(mapping, 2 * rp_page, 0, 0, 0) == -1 && errno == EPERM);
31 CHECK(rp_matches(mapping, 4 * rp_page, 2 * rp_page, 0));
32 CHECK(munlock(mapping, 2 * rp_page) == 0);
33 CHECK(msync(mapping, 2 * rp_page, MS_SYNC | MS_INVALIDATE) == 0);
34 CHECK(rp_limit(2 * rp_page) == 0 && mlock(extra, 2 * rp_page) == 0);
37 if (extra != MAP_FAILED)
38 munmap(extra, 2 * rp_page);
39 if (mapping != MAP_FAILED)
40 munmap(mapping, 2 * rp_page);
45static int future_zero_limit(
void) {
47 struct rp_file file = {.fd = -1};
48 unsigned char* mapping = MAP_FAILED;
49 CHECK(rp_create(&file, RP_MEMFD) == 0);
50 mapping = mmap(NULL, rp_page, PROT_READ, MAP_SHARED, file.fd, 0);
51 CHECK(mapping != MAP_FAILED && rp_matches(mapping, 0, rp_page, 0));
52 CHECK(rp_limit(2 * rp_page) == 0 && mlockall(MCL_FUTURE | MCL_ONFAULT) == 0);
53 CHECK(rp_limit(0) == 0);
55 CHECK(remap_file_pages(mapping, rp_page, 0, 4, 0) == -1 && errno == EAGAIN);
56 CHECK(rp_matches(mapping, 0, rp_page, 0));
57 CHECK(munlockall() == 0);
58 CHECK(remap_file_pages(mapping, rp_page, 0, 4, MAP_NONBLOCK) == 0);
59 CHECK(rp_matches(mapping, 4 * rp_page, rp_page, 0));
62 if (mapping != MAP_FAILED)
63 munmap(mapping, rp_page);
68static int lock_mode_conversion(
void) {
70 struct rp_file file = {.fd = -1};
71 unsigned char* mapping = MAP_FAILED;
72 CHECK(rp_create(&file, RP_MEMFD) == 0 && rp_limit(8 * rp_page) == 0);
73 mapping = mmap(NULL, 2 * rp_page, PROT_READ, MAP_SHARED, file.fd, 0);
74 CHECK(mapping != MAP_FAILED);
75 CHECK(mlock2(mapping, rp_page, MLOCK_ONFAULT) == 0);
76 CHECK(mlock(mapping + rp_page, rp_page) == 0);
78 CHECK(remap_file_pages(mapping, 2 * rp_page, 0, 4, 0) == -1 && errno == EINVAL);
79 CHECK(rp_matches(mapping, 0, 2 * rp_page, 0));
80 CHECK(remap_file_pages(mapping, rp_page, 0, 4, MAP_NONBLOCK) == 0);
81 CHECK(rp_matches(mapping, 4 * rp_page, rp_page, 0));
83 CHECK(remap_file_pages(mapping, 2 * rp_page, 0, 2, 0) == 0);
84 CHECK(rp_matches(mapping, 2 * rp_page, 2 * rp_page, 0));
86 CHECK(msync(mapping, 2 * rp_page, MS_SYNC | MS_INVALIDATE) == -1 && errno == EBUSY);
87 CHECK(rp_fault(mapping, SIGSEGV, 1) == 0);
88 CHECK(mprotect(mapping, rp_page, PROT_NONE) == 0);
89 CHECK(rp_fault(mapping, SIGSEGV, 0) == 0);
90 CHECK(mprotect(mapping, rp_page, PROT_READ) == 0);
91 CHECK(rp_matches(mapping, 2 * rp_page, rp_page, 0));
92 CHECK(munlock(mapping, rp_page) == 0);
93 CHECK(msync(mapping, rp_page, MS_SYNC | MS_INVALIDATE) == 0);
95 CHECK(msync(mapping + rp_page, rp_page, MS_SYNC | MS_INVALIDATE) == -1 && errno == EBUSY);
96 CHECK(munlock(mapping + rp_page, rp_page) == 0);
97 CHECK(msync(mapping + rp_page, rp_page, MS_SYNC | MS_INVALIDATE) == 0);
100 if (mapping != MAP_FAILED)
101 munmap(mapping, 2 * rp_page);
106static int future_onfault_mode(
void) {
108 struct rp_file file = {.fd = -1};
109 unsigned char* mapping = MAP_FAILED;
110 CHECK(rp_create(&file, RP_MEMFD) == 0 && rp_limit(8 * rp_page) == 0);
111 mapping = mmap(NULL, 2 * rp_page, PROT_READ, MAP_SHARED, file.fd, 0);
112 CHECK(mapping != MAP_FAILED && mlock2(mapping, 2 * rp_page, MLOCK_ONFAULT) == 0);
113 CHECK(mlockall(MCL_FUTURE | MCL_ONFAULT) == 0);
114 CHECK(remap_file_pages(mapping, rp_page, 0, 4, 0) == 0);
116 CHECK(remap_file_pages(mapping, 2 * rp_page, 0, 2, 0) == 0);
117 CHECK(rp_matches(mapping, 2 * rp_page, 2 * rp_page, 0));
119 CHECK(msync(mapping, 2 * rp_page, MS_SYNC | MS_INVALIDATE) == -1 && errno == EBUSY);
120 CHECK(munlockall() == 0);
121 CHECK(msync(mapping, 2 * rp_page, MS_SYNC | MS_INVALIDATE) == 0);
124 if (mapping != MAP_FAILED)
125 munmap(mapping, 2 * rp_page);
131 if (rp_unprivileged())
133 return replacement_charge() || future_zero_limit() || lock_mode_conversion() ||
134 future_onfault_mode();