1*0f4c859eSApple OSS Distributions /* Mach vm map miscellaneous unit tests
2*0f4c859eSApple OSS Distributions *
3*0f4c859eSApple OSS Distributions * This test program serves to be a regression test suite for legacy
4*0f4c859eSApple OSS Distributions * vm issues, ideally each test will be linked to a radar number and
5*0f4c859eSApple OSS Distributions * perform a set of certain validations.
6*0f4c859eSApple OSS Distributions *
7*0f4c859eSApple OSS Distributions */
8*0f4c859eSApple OSS Distributions #include <darwintest.h>
9*0f4c859eSApple OSS Distributions
10*0f4c859eSApple OSS Distributions #include <dlfcn.h>
11*0f4c859eSApple OSS Distributions #include <errno.h>
12*0f4c859eSApple OSS Distributions #include <ptrauth.h>
13*0f4c859eSApple OSS Distributions #include <stdio.h>
14*0f4c859eSApple OSS Distributions #include <stdlib.h>
15*0f4c859eSApple OSS Distributions #include <string.h>
16*0f4c859eSApple OSS Distributions #include <time.h>
17*0f4c859eSApple OSS Distributions
18*0f4c859eSApple OSS Distributions #include <sys/mman.h>
19*0f4c859eSApple OSS Distributions
20*0f4c859eSApple OSS Distributions #include <mach/mach_error.h>
21*0f4c859eSApple OSS Distributions #include <mach/mach_init.h>
22*0f4c859eSApple OSS Distributions #include <mach/mach_port.h>
23*0f4c859eSApple OSS Distributions #include <mach/mach_vm.h>
24*0f4c859eSApple OSS Distributions #include <mach/vm_map.h>
25*0f4c859eSApple OSS Distributions #include <mach/task.h>
26*0f4c859eSApple OSS Distributions #include <mach/task_info.h>
27*0f4c859eSApple OSS Distributions #include <mach/shared_region.h>
28*0f4c859eSApple OSS Distributions #include <machine/cpu_capabilities.h>
29*0f4c859eSApple OSS Distributions
30*0f4c859eSApple OSS Distributions T_GLOBAL_META(
31*0f4c859eSApple OSS Distributions T_META_NAMESPACE("xnu.vm"),
32*0f4c859eSApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
33*0f4c859eSApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("VM"),
34*0f4c859eSApple OSS Distributions T_META_RUN_CONCURRENTLY(true));
35*0f4c859eSApple OSS Distributions
36*0f4c859eSApple OSS Distributions static void
test_memory_entry_tagging(int override_tag)37*0f4c859eSApple OSS Distributions test_memory_entry_tagging(int override_tag)
38*0f4c859eSApple OSS Distributions {
39*0f4c859eSApple OSS Distributions int pass;
40*0f4c859eSApple OSS Distributions int do_copy;
41*0f4c859eSApple OSS Distributions kern_return_t kr;
42*0f4c859eSApple OSS Distributions mach_vm_address_t vmaddr_orig, vmaddr_shared, vmaddr_copied;
43*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize_orig, vmsize_shared, vmsize_copied;
44*0f4c859eSApple OSS Distributions mach_vm_address_t *vmaddr_ptr;
45*0f4c859eSApple OSS Distributions mach_vm_size_t *vmsize_ptr;
46*0f4c859eSApple OSS Distributions mach_vm_address_t vmaddr_chunk;
47*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize_chunk;
48*0f4c859eSApple OSS Distributions mach_vm_offset_t vmoff;
49*0f4c859eSApple OSS Distributions mach_port_t mem_entry_copied, mem_entry_shared;
50*0f4c859eSApple OSS Distributions mach_port_t *mem_entry_ptr;
51*0f4c859eSApple OSS Distributions int i;
52*0f4c859eSApple OSS Distributions vm_region_submap_short_info_data_64_t ri;
53*0f4c859eSApple OSS Distributions mach_msg_type_number_t ri_count;
54*0f4c859eSApple OSS Distributions unsigned int depth;
55*0f4c859eSApple OSS Distributions int vm_flags;
56*0f4c859eSApple OSS Distributions int expected_tag;
57*0f4c859eSApple OSS Distributions
58*0f4c859eSApple OSS Distributions vmaddr_copied = 0;
59*0f4c859eSApple OSS Distributions vmaddr_shared = 0;
60*0f4c859eSApple OSS Distributions vmsize_copied = 0;
61*0f4c859eSApple OSS Distributions vmsize_shared = 0;
62*0f4c859eSApple OSS Distributions vmaddr_chunk = 0;
63*0f4c859eSApple OSS Distributions vmsize_chunk = 16 * 1024;
64*0f4c859eSApple OSS Distributions vmaddr_orig = 0;
65*0f4c859eSApple OSS Distributions vmsize_orig = 3 * vmsize_chunk;
66*0f4c859eSApple OSS Distributions mem_entry_copied = MACH_PORT_NULL;
67*0f4c859eSApple OSS Distributions mem_entry_shared = MACH_PORT_NULL;
68*0f4c859eSApple OSS Distributions pass = 0;
69*0f4c859eSApple OSS Distributions
70*0f4c859eSApple OSS Distributions vmaddr_orig = 0;
71*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(),
72*0f4c859eSApple OSS Distributions &vmaddr_orig,
73*0f4c859eSApple OSS Distributions vmsize_orig,
74*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE);
75*0f4c859eSApple OSS Distributions T_QUIET;
76*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d] vm_allocate(%lld)",
77*0f4c859eSApple OSS Distributions override_tag, vmsize_orig);
78*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
79*0f4c859eSApple OSS Distributions goto done;
80*0f4c859eSApple OSS Distributions }
81*0f4c859eSApple OSS Distributions
82*0f4c859eSApple OSS Distributions for (i = 0; i < vmsize_orig / vmsize_chunk; i++) {
83*0f4c859eSApple OSS Distributions vmaddr_chunk = vmaddr_orig + (i * vmsize_chunk);
84*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(),
85*0f4c859eSApple OSS Distributions &vmaddr_chunk,
86*0f4c859eSApple OSS Distributions vmsize_chunk,
87*0f4c859eSApple OSS Distributions (VM_FLAGS_FIXED |
88*0f4c859eSApple OSS Distributions VM_FLAGS_OVERWRITE |
89*0f4c859eSApple OSS Distributions VM_MAKE_TAG(100 + i)));
90*0f4c859eSApple OSS Distributions T_QUIET;
91*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d] vm_allocate(%lld)",
92*0f4c859eSApple OSS Distributions override_tag, vmsize_chunk);
93*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
94*0f4c859eSApple OSS Distributions goto done;
95*0f4c859eSApple OSS Distributions }
96*0f4c859eSApple OSS Distributions }
97*0f4c859eSApple OSS Distributions
98*0f4c859eSApple OSS Distributions for (vmoff = 0;
99*0f4c859eSApple OSS Distributions vmoff < vmsize_orig;
100*0f4c859eSApple OSS Distributions vmoff += PAGE_SIZE) {
101*0f4c859eSApple OSS Distributions *((unsigned char *)(uintptr_t)(vmaddr_orig + vmoff)) = 'x';
102*0f4c859eSApple OSS Distributions }
103*0f4c859eSApple OSS Distributions
104*0f4c859eSApple OSS Distributions do_copy = time(NULL) & 1;
105*0f4c859eSApple OSS Distributions again:
106*0f4c859eSApple OSS Distributions *((unsigned char *)(uintptr_t)vmaddr_orig) = 'x';
107*0f4c859eSApple OSS Distributions if (do_copy) {
108*0f4c859eSApple OSS Distributions mem_entry_ptr = &mem_entry_copied;
109*0f4c859eSApple OSS Distributions vmsize_copied = vmsize_orig;
110*0f4c859eSApple OSS Distributions vmsize_ptr = &vmsize_copied;
111*0f4c859eSApple OSS Distributions vmaddr_copied = 0;
112*0f4c859eSApple OSS Distributions vmaddr_ptr = &vmaddr_copied;
113*0f4c859eSApple OSS Distributions vm_flags = MAP_MEM_VM_COPY;
114*0f4c859eSApple OSS Distributions } else {
115*0f4c859eSApple OSS Distributions mem_entry_ptr = &mem_entry_shared;
116*0f4c859eSApple OSS Distributions vmsize_shared = vmsize_orig;
117*0f4c859eSApple OSS Distributions vmsize_ptr = &vmsize_shared;
118*0f4c859eSApple OSS Distributions vmaddr_shared = 0;
119*0f4c859eSApple OSS Distributions vmaddr_ptr = &vmaddr_shared;
120*0f4c859eSApple OSS Distributions vm_flags = MAP_MEM_VM_SHARE;
121*0f4c859eSApple OSS Distributions }
122*0f4c859eSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
123*0f4c859eSApple OSS Distributions vmsize_ptr,
124*0f4c859eSApple OSS Distributions vmaddr_orig, /* offset */
125*0f4c859eSApple OSS Distributions (vm_flags |
126*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE),
127*0f4c859eSApple OSS Distributions mem_entry_ptr,
128*0f4c859eSApple OSS Distributions MACH_PORT_NULL);
129*0f4c859eSApple OSS Distributions T_QUIET;
130*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d][do_copy:%d] mach_make_memory_entry()",
131*0f4c859eSApple OSS Distributions override_tag, do_copy);
132*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
133*0f4c859eSApple OSS Distributions goto done;
134*0f4c859eSApple OSS Distributions }
135*0f4c859eSApple OSS Distributions T_QUIET;
136*0f4c859eSApple OSS Distributions T_EXPECT_EQ(*vmsize_ptr, vmsize_orig, "[override_tag:%d][do_copy:%d] vmsize (0x%llx) != vmsize_orig (0x%llx)",
137*0f4c859eSApple OSS Distributions override_tag, do_copy, (uint64_t) *vmsize_ptr, (uint64_t) vmsize_orig);
138*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
139*0f4c859eSApple OSS Distributions goto done;
140*0f4c859eSApple OSS Distributions }
141*0f4c859eSApple OSS Distributions T_QUIET;
142*0f4c859eSApple OSS Distributions T_EXPECT_NOTNULL(*mem_entry_ptr, "[override_tag:%d][do_copy:%d] mem_entry == 0x%x",
143*0f4c859eSApple OSS Distributions override_tag, do_copy, *mem_entry_ptr);
144*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
145*0f4c859eSApple OSS Distributions goto done;
146*0f4c859eSApple OSS Distributions }
147*0f4c859eSApple OSS Distributions
148*0f4c859eSApple OSS Distributions *vmaddr_ptr = 0;
149*0f4c859eSApple OSS Distributions if (override_tag) {
150*0f4c859eSApple OSS Distributions vm_flags = VM_MAKE_TAG(200);
151*0f4c859eSApple OSS Distributions } else {
152*0f4c859eSApple OSS Distributions vm_flags = 0;
153*0f4c859eSApple OSS Distributions }
154*0f4c859eSApple OSS Distributions kr = mach_vm_map(mach_task_self(),
155*0f4c859eSApple OSS Distributions vmaddr_ptr,
156*0f4c859eSApple OSS Distributions vmsize_orig,
157*0f4c859eSApple OSS Distributions 0, /* mask */
158*0f4c859eSApple OSS Distributions vm_flags | VM_FLAGS_ANYWHERE,
159*0f4c859eSApple OSS Distributions *mem_entry_ptr,
160*0f4c859eSApple OSS Distributions 0, /* offset */
161*0f4c859eSApple OSS Distributions FALSE, /* copy */
162*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
163*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
164*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
165*0f4c859eSApple OSS Distributions T_QUIET;
166*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d][do_copy:%d] mach_vm_map()",
167*0f4c859eSApple OSS Distributions override_tag, do_copy);
168*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
169*0f4c859eSApple OSS Distributions goto done;
170*0f4c859eSApple OSS Distributions }
171*0f4c859eSApple OSS Distributions
172*0f4c859eSApple OSS Distributions *((unsigned char *)(uintptr_t)vmaddr_orig) = 'X';
173*0f4c859eSApple OSS Distributions if (*(unsigned char *)(uintptr_t)*vmaddr_ptr == 'X') {
174*0f4c859eSApple OSS Distributions T_QUIET;
175*0f4c859eSApple OSS Distributions T_EXPECT_EQ(do_copy, 0, "[override_tag:%d][do_copy:%d] memory shared instead of copied",
176*0f4c859eSApple OSS Distributions override_tag, do_copy);
177*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
178*0f4c859eSApple OSS Distributions goto done;
179*0f4c859eSApple OSS Distributions }
180*0f4c859eSApple OSS Distributions } else {
181*0f4c859eSApple OSS Distributions T_QUIET;
182*0f4c859eSApple OSS Distributions T_EXPECT_NE(do_copy, 0, "[override_tag:%d][do_copy:%d] memory copied instead of shared",
183*0f4c859eSApple OSS Distributions override_tag, do_copy);
184*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
185*0f4c859eSApple OSS Distributions goto done;
186*0f4c859eSApple OSS Distributions }
187*0f4c859eSApple OSS Distributions }
188*0f4c859eSApple OSS Distributions
189*0f4c859eSApple OSS Distributions for (i = 0; i < vmsize_orig / vmsize_chunk; i++) {
190*0f4c859eSApple OSS Distributions mach_vm_address_t vmaddr_info;
191*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize_info;
192*0f4c859eSApple OSS Distributions
193*0f4c859eSApple OSS Distributions vmaddr_info = *vmaddr_ptr + (i * vmsize_chunk);
194*0f4c859eSApple OSS Distributions vmsize_info = 0;
195*0f4c859eSApple OSS Distributions depth = 1;
196*0f4c859eSApple OSS Distributions ri_count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
197*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
198*0f4c859eSApple OSS Distributions &vmaddr_info,
199*0f4c859eSApple OSS Distributions &vmsize_info,
200*0f4c859eSApple OSS Distributions &depth,
201*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t) &ri,
202*0f4c859eSApple OSS Distributions &ri_count);
203*0f4c859eSApple OSS Distributions T_QUIET;
204*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d][do_copy:%d] mach_vm_region_recurse(0x%llx+0x%llx)",
205*0f4c859eSApple OSS Distributions override_tag, do_copy, *vmaddr_ptr, i * vmsize_chunk);
206*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
207*0f4c859eSApple OSS Distributions goto done;
208*0f4c859eSApple OSS Distributions }
209*0f4c859eSApple OSS Distributions T_QUIET;
210*0f4c859eSApple OSS Distributions T_EXPECT_EQ(vmaddr_info, *vmaddr_ptr + (i * vmsize_chunk), "[override_tag:%d][do_copy:%d] mach_vm_region_recurse(0x%llx+0x%llx) returned addr 0x%llx",
211*0f4c859eSApple OSS Distributions override_tag, do_copy, *vmaddr_ptr, i * vmsize_chunk, vmaddr_info);
212*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
213*0f4c859eSApple OSS Distributions goto done;
214*0f4c859eSApple OSS Distributions }
215*0f4c859eSApple OSS Distributions T_QUIET;
216*0f4c859eSApple OSS Distributions T_EXPECT_EQ(vmsize_info, vmsize_chunk, "[override_tag:%d][do_copy:%d] mach_vm_region_recurse(0x%llx+0x%llx) returned size 0x%llx expected 0x%llx",
217*0f4c859eSApple OSS Distributions override_tag, do_copy, *vmaddr_ptr, i * vmsize_chunk, vmsize_info, vmsize_chunk);
218*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
219*0f4c859eSApple OSS Distributions goto done;
220*0f4c859eSApple OSS Distributions }
221*0f4c859eSApple OSS Distributions if (override_tag) {
222*0f4c859eSApple OSS Distributions expected_tag = 200;
223*0f4c859eSApple OSS Distributions } else {
224*0f4c859eSApple OSS Distributions expected_tag = 100 + i;
225*0f4c859eSApple OSS Distributions }
226*0f4c859eSApple OSS Distributions T_QUIET;
227*0f4c859eSApple OSS Distributions T_EXPECT_EQ(ri.user_tag, expected_tag, "[override_tag:%d][do_copy:%d] i=%d tag=%d expected %d",
228*0f4c859eSApple OSS Distributions override_tag, do_copy, i, ri.user_tag, expected_tag);
229*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
230*0f4c859eSApple OSS Distributions goto done;
231*0f4c859eSApple OSS Distributions }
232*0f4c859eSApple OSS Distributions }
233*0f4c859eSApple OSS Distributions
234*0f4c859eSApple OSS Distributions if (++pass < 2) {
235*0f4c859eSApple OSS Distributions do_copy = !do_copy;
236*0f4c859eSApple OSS Distributions goto again;
237*0f4c859eSApple OSS Distributions }
238*0f4c859eSApple OSS Distributions
239*0f4c859eSApple OSS Distributions done:
240*0f4c859eSApple OSS Distributions if (vmaddr_orig != 0) {
241*0f4c859eSApple OSS Distributions mach_vm_deallocate(mach_task_self(),
242*0f4c859eSApple OSS Distributions vmaddr_orig,
243*0f4c859eSApple OSS Distributions vmsize_orig);
244*0f4c859eSApple OSS Distributions vmaddr_orig = 0;
245*0f4c859eSApple OSS Distributions vmsize_orig = 0;
246*0f4c859eSApple OSS Distributions }
247*0f4c859eSApple OSS Distributions if (vmaddr_copied != 0) {
248*0f4c859eSApple OSS Distributions mach_vm_deallocate(mach_task_self(),
249*0f4c859eSApple OSS Distributions vmaddr_copied,
250*0f4c859eSApple OSS Distributions vmsize_copied);
251*0f4c859eSApple OSS Distributions vmaddr_copied = 0;
252*0f4c859eSApple OSS Distributions vmsize_copied = 0;
253*0f4c859eSApple OSS Distributions }
254*0f4c859eSApple OSS Distributions if (vmaddr_shared != 0) {
255*0f4c859eSApple OSS Distributions mach_vm_deallocate(mach_task_self(),
256*0f4c859eSApple OSS Distributions vmaddr_shared,
257*0f4c859eSApple OSS Distributions vmsize_shared);
258*0f4c859eSApple OSS Distributions vmaddr_shared = 0;
259*0f4c859eSApple OSS Distributions vmsize_shared = 0;
260*0f4c859eSApple OSS Distributions }
261*0f4c859eSApple OSS Distributions if (mem_entry_copied != MACH_PORT_NULL) {
262*0f4c859eSApple OSS Distributions mach_port_deallocate(mach_task_self(), mem_entry_copied);
263*0f4c859eSApple OSS Distributions mem_entry_copied = MACH_PORT_NULL;
264*0f4c859eSApple OSS Distributions }
265*0f4c859eSApple OSS Distributions if (mem_entry_shared != MACH_PORT_NULL) {
266*0f4c859eSApple OSS Distributions mach_port_deallocate(mach_task_self(), mem_entry_shared);
267*0f4c859eSApple OSS Distributions mem_entry_shared = MACH_PORT_NULL;
268*0f4c859eSApple OSS Distributions }
269*0f4c859eSApple OSS Distributions
270*0f4c859eSApple OSS Distributions return;
271*0f4c859eSApple OSS Distributions }
272*0f4c859eSApple OSS Distributions
273*0f4c859eSApple OSS Distributions static void
test_map_memory_entry(void)274*0f4c859eSApple OSS Distributions test_map_memory_entry(void)
275*0f4c859eSApple OSS Distributions {
276*0f4c859eSApple OSS Distributions kern_return_t kr;
277*0f4c859eSApple OSS Distributions mach_vm_address_t vmaddr1, vmaddr2;
278*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize1, vmsize2;
279*0f4c859eSApple OSS Distributions mach_port_t mem_entry;
280*0f4c859eSApple OSS Distributions unsigned char *cp1, *cp2;
281*0f4c859eSApple OSS Distributions
282*0f4c859eSApple OSS Distributions vmaddr1 = 0;
283*0f4c859eSApple OSS Distributions vmsize1 = 0;
284*0f4c859eSApple OSS Distributions vmaddr2 = 0;
285*0f4c859eSApple OSS Distributions vmsize2 = 0;
286*0f4c859eSApple OSS Distributions mem_entry = MACH_PORT_NULL;
287*0f4c859eSApple OSS Distributions
288*0f4c859eSApple OSS Distributions vmsize1 = 1;
289*0f4c859eSApple OSS Distributions vmaddr1 = 0;
290*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(),
291*0f4c859eSApple OSS Distributions &vmaddr1,
292*0f4c859eSApple OSS Distributions vmsize1,
293*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE);
294*0f4c859eSApple OSS Distributions T_QUIET;
295*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "vm_allocate(%lld)", vmsize1);
296*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
297*0f4c859eSApple OSS Distributions goto done;
298*0f4c859eSApple OSS Distributions }
299*0f4c859eSApple OSS Distributions
300*0f4c859eSApple OSS Distributions cp1 = (unsigned char *)(uintptr_t)vmaddr1;
301*0f4c859eSApple OSS Distributions *cp1 = '1';
302*0f4c859eSApple OSS Distributions
303*0f4c859eSApple OSS Distributions vmsize2 = 1;
304*0f4c859eSApple OSS Distributions mem_entry = MACH_PORT_NULL;
305*0f4c859eSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
306*0f4c859eSApple OSS Distributions &vmsize2,
307*0f4c859eSApple OSS Distributions vmaddr1, /* offset */
308*0f4c859eSApple OSS Distributions (MAP_MEM_VM_COPY |
309*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE),
310*0f4c859eSApple OSS Distributions &mem_entry,
311*0f4c859eSApple OSS Distributions MACH_PORT_NULL);
312*0f4c859eSApple OSS Distributions T_QUIET;
313*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "mach_make_memory_entry()");
314*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
315*0f4c859eSApple OSS Distributions goto done;
316*0f4c859eSApple OSS Distributions }
317*0f4c859eSApple OSS Distributions T_QUIET;
318*0f4c859eSApple OSS Distributions T_EXPECT_GE(vmsize2, vmsize1, "vmsize2 (0x%llx) < vmsize1 (0x%llx)",
319*0f4c859eSApple OSS Distributions (uint64_t) vmsize2, (uint64_t) vmsize1);
320*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
321*0f4c859eSApple OSS Distributions goto done;
322*0f4c859eSApple OSS Distributions }
323*0f4c859eSApple OSS Distributions T_QUIET;
324*0f4c859eSApple OSS Distributions T_EXPECT_NOTNULL(mem_entry, "mem_entry == 0x%x", mem_entry);
325*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
326*0f4c859eSApple OSS Distributions goto done;
327*0f4c859eSApple OSS Distributions }
328*0f4c859eSApple OSS Distributions
329*0f4c859eSApple OSS Distributions vmaddr2 = 0;
330*0f4c859eSApple OSS Distributions kr = mach_vm_map(mach_task_self(),
331*0f4c859eSApple OSS Distributions &vmaddr2,
332*0f4c859eSApple OSS Distributions vmsize2,
333*0f4c859eSApple OSS Distributions 0, /* mask */
334*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
335*0f4c859eSApple OSS Distributions mem_entry,
336*0f4c859eSApple OSS Distributions 0, /* offset */
337*0f4c859eSApple OSS Distributions TRUE, /* copy */
338*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
339*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
340*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
341*0f4c859eSApple OSS Distributions T_QUIET;
342*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "mach_vm_map()");
343*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
344*0f4c859eSApple OSS Distributions goto done;
345*0f4c859eSApple OSS Distributions }
346*0f4c859eSApple OSS Distributions
347*0f4c859eSApple OSS Distributions cp2 = (unsigned char *)(uintptr_t)vmaddr2;
348*0f4c859eSApple OSS Distributions T_QUIET;
349*0f4c859eSApple OSS Distributions T_EXPECT_TRUE(((*cp1 == '1') && (*cp2 == '1')), "*cp1/*cp2 0x%x/0x%x expected 0x%x/0x%x",
350*0f4c859eSApple OSS Distributions *cp1, *cp2, '1', '1');
351*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
352*0f4c859eSApple OSS Distributions goto done;
353*0f4c859eSApple OSS Distributions }
354*0f4c859eSApple OSS Distributions
355*0f4c859eSApple OSS Distributions *cp2 = '2';
356*0f4c859eSApple OSS Distributions T_QUIET;
357*0f4c859eSApple OSS Distributions T_EXPECT_TRUE(((*cp1 == '1') && (*cp2 == '2')), "*cp1/*cp2 0x%x/0x%x expected 0x%x/0x%x",
358*0f4c859eSApple OSS Distributions *cp1, *cp2, '1', '2');
359*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
360*0f4c859eSApple OSS Distributions goto done;
361*0f4c859eSApple OSS Distributions }
362*0f4c859eSApple OSS Distributions
363*0f4c859eSApple OSS Distributions done:
364*0f4c859eSApple OSS Distributions if (vmaddr1 != 0) {
365*0f4c859eSApple OSS Distributions mach_vm_deallocate(mach_task_self(), vmaddr1, vmsize1);
366*0f4c859eSApple OSS Distributions vmaddr1 = 0;
367*0f4c859eSApple OSS Distributions vmsize1 = 0;
368*0f4c859eSApple OSS Distributions }
369*0f4c859eSApple OSS Distributions if (vmaddr2 != 0) {
370*0f4c859eSApple OSS Distributions mach_vm_deallocate(mach_task_self(), vmaddr2, vmsize2);
371*0f4c859eSApple OSS Distributions vmaddr2 = 0;
372*0f4c859eSApple OSS Distributions vmsize2 = 0;
373*0f4c859eSApple OSS Distributions }
374*0f4c859eSApple OSS Distributions if (mem_entry != MACH_PORT_NULL) {
375*0f4c859eSApple OSS Distributions mach_port_deallocate(mach_task_self(), mem_entry);
376*0f4c859eSApple OSS Distributions mem_entry = MACH_PORT_NULL;
377*0f4c859eSApple OSS Distributions }
378*0f4c859eSApple OSS Distributions
379*0f4c859eSApple OSS Distributions return;
380*0f4c859eSApple OSS Distributions }
381*0f4c859eSApple OSS Distributions
382*0f4c859eSApple OSS Distributions T_DECL(memory_entry_tagging, "test mem entry tag for rdar://problem/23334087 \
383*0f4c859eSApple OSS Distributions VM memory tags should be propagated through memory entries",
384*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
385*0f4c859eSApple OSS Distributions {
386*0f4c859eSApple OSS Distributions test_memory_entry_tagging(0);
387*0f4c859eSApple OSS Distributions test_memory_entry_tagging(1);
388*0f4c859eSApple OSS Distributions }
389*0f4c859eSApple OSS Distributions
390*0f4c859eSApple OSS Distributions T_DECL(map_memory_entry, "test mapping mem entry for rdar://problem/22611816 \
391*0f4c859eSApple OSS Distributions mach_make_memory_entry(MAP_MEM_VM_COPY) should never use a KERNEL_BUFFER \
392*0f4c859eSApple OSS Distributions copy", T_META_ALL_VALID_ARCHS(true))
393*0f4c859eSApple OSS Distributions {
394*0f4c859eSApple OSS Distributions test_map_memory_entry();
395*0f4c859eSApple OSS Distributions }
396*0f4c859eSApple OSS Distributions
397*0f4c859eSApple OSS Distributions static char *vm_purgable_state[4] = { "NONVOLATILE", "VOLATILE", "EMPTY", "DENY" };
398*0f4c859eSApple OSS Distributions
399*0f4c859eSApple OSS Distributions static uint64_t
task_footprint(void)400*0f4c859eSApple OSS Distributions task_footprint(void)
401*0f4c859eSApple OSS Distributions {
402*0f4c859eSApple OSS Distributions task_vm_info_data_t ti;
403*0f4c859eSApple OSS Distributions kern_return_t kr;
404*0f4c859eSApple OSS Distributions mach_msg_type_number_t count;
405*0f4c859eSApple OSS Distributions
406*0f4c859eSApple OSS Distributions count = TASK_VM_INFO_COUNT;
407*0f4c859eSApple OSS Distributions kr = task_info(mach_task_self(),
408*0f4c859eSApple OSS Distributions TASK_VM_INFO,
409*0f4c859eSApple OSS Distributions (task_info_t) &ti,
410*0f4c859eSApple OSS Distributions &count);
411*0f4c859eSApple OSS Distributions T_QUIET;
412*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "task_info()");
413*0f4c859eSApple OSS Distributions #if defined(__arm64__)
414*0f4c859eSApple OSS Distributions T_QUIET;
415*0f4c859eSApple OSS Distributions T_ASSERT_EQ(count, TASK_VM_INFO_COUNT, "task_info() count = %d (expected %d)",
416*0f4c859eSApple OSS Distributions count, TASK_VM_INFO_COUNT);
417*0f4c859eSApple OSS Distributions #endif /* defined(__arm64__) */
418*0f4c859eSApple OSS Distributions return ti.phys_footprint;
419*0f4c859eSApple OSS Distributions }
420*0f4c859eSApple OSS Distributions
421*0f4c859eSApple OSS Distributions T_DECL(purgeable_empty_to_volatile, "test task physical footprint when \
422*0f4c859eSApple OSS Distributions emptying, volatilizing purgeable vm")
423*0f4c859eSApple OSS Distributions {
424*0f4c859eSApple OSS Distributions kern_return_t kr;
425*0f4c859eSApple OSS Distributions mach_vm_address_t vm_addr;
426*0f4c859eSApple OSS Distributions mach_vm_size_t vm_size;
427*0f4c859eSApple OSS Distributions char *cp;
428*0f4c859eSApple OSS Distributions int ret;
429*0f4c859eSApple OSS Distributions vm_purgable_t state;
430*0f4c859eSApple OSS Distributions uint64_t footprint[8];
431*0f4c859eSApple OSS Distributions
432*0f4c859eSApple OSS Distributions vm_addr = 0;
433*0f4c859eSApple OSS Distributions vm_size = 1 * 1024 * 1024;
434*0f4c859eSApple OSS Distributions T_LOG("--> allocate %llu bytes", vm_size);
435*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(),
436*0f4c859eSApple OSS Distributions &vm_addr,
437*0f4c859eSApple OSS Distributions vm_size,
438*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
439*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
440*0f4c859eSApple OSS Distributions
441*0f4c859eSApple OSS Distributions /* footprint0 */
442*0f4c859eSApple OSS Distributions footprint[0] = task_footprint();
443*0f4c859eSApple OSS Distributions T_LOG(" footprint[0] = %llu", footprint[0]);
444*0f4c859eSApple OSS Distributions
445*0f4c859eSApple OSS Distributions T_LOG("--> access %llu bytes", vm_size);
446*0f4c859eSApple OSS Distributions for (cp = (char *) vm_addr;
447*0f4c859eSApple OSS Distributions cp < (char *) (vm_addr + vm_size);
448*0f4c859eSApple OSS Distributions cp += vm_kernel_page_size) {
449*0f4c859eSApple OSS Distributions *cp = 'x';
450*0f4c859eSApple OSS Distributions }
451*0f4c859eSApple OSS Distributions /* footprint1 == footprint0 + vm_size */
452*0f4c859eSApple OSS Distributions footprint[1] = task_footprint();
453*0f4c859eSApple OSS Distributions T_LOG(" footprint[1] = %llu", footprint[1]);
454*0f4c859eSApple OSS Distributions if (footprint[1] != footprint[0] + vm_size) {
455*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[1] != footprint[0] + vm_size");
456*0f4c859eSApple OSS Distributions }
457*0f4c859eSApple OSS Distributions
458*0f4c859eSApple OSS Distributions T_LOG("--> wire %llu bytes", vm_size / 2);
459*0f4c859eSApple OSS Distributions ret = mlock((char *)vm_addr, (size_t) (vm_size / 2));
460*0f4c859eSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "mlock()");
461*0f4c859eSApple OSS Distributions
462*0f4c859eSApple OSS Distributions /* footprint2 == footprint1 */
463*0f4c859eSApple OSS Distributions footprint[2] = task_footprint();
464*0f4c859eSApple OSS Distributions T_LOG(" footprint[2] = %llu", footprint[2]);
465*0f4c859eSApple OSS Distributions if (footprint[2] != footprint[1]) {
466*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[2] != footprint[1]");
467*0f4c859eSApple OSS Distributions }
468*0f4c859eSApple OSS Distributions
469*0f4c859eSApple OSS Distributions T_LOG("--> VOLATILE");
470*0f4c859eSApple OSS Distributions state = VM_PURGABLE_VOLATILE;
471*0f4c859eSApple OSS Distributions kr = mach_vm_purgable_control(mach_task_self(),
472*0f4c859eSApple OSS Distributions vm_addr,
473*0f4c859eSApple OSS Distributions VM_PURGABLE_SET_STATE,
474*0f4c859eSApple OSS Distributions &state);
475*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_purgable_control(VOLATILE)");
476*0f4c859eSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_NONVOLATILE, "NONVOLATILE->VOLATILE: state was %s",
477*0f4c859eSApple OSS Distributions vm_purgable_state[state]);
478*0f4c859eSApple OSS Distributions /* footprint3 == footprint2 - (vm_size / 2) */
479*0f4c859eSApple OSS Distributions footprint[3] = task_footprint();
480*0f4c859eSApple OSS Distributions T_LOG(" footprint[3] = %llu", footprint[3]);
481*0f4c859eSApple OSS Distributions if (footprint[3] != footprint[2] - (vm_size / 2)) {
482*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[3] != footprint[2] - (vm_size / 2)");
483*0f4c859eSApple OSS Distributions }
484*0f4c859eSApple OSS Distributions
485*0f4c859eSApple OSS Distributions T_LOG("--> EMPTY");
486*0f4c859eSApple OSS Distributions state = VM_PURGABLE_EMPTY;
487*0f4c859eSApple OSS Distributions kr = mach_vm_purgable_control(mach_task_self(),
488*0f4c859eSApple OSS Distributions vm_addr,
489*0f4c859eSApple OSS Distributions VM_PURGABLE_SET_STATE,
490*0f4c859eSApple OSS Distributions &state);
491*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_purgable_control(EMPTY)");
492*0f4c859eSApple OSS Distributions if (state != VM_PURGABLE_VOLATILE &&
493*0f4c859eSApple OSS Distributions state != VM_PURGABLE_EMPTY) {
494*0f4c859eSApple OSS Distributions T_ASSERT_FAIL("VOLATILE->EMPTY: state was %s",
495*0f4c859eSApple OSS Distributions vm_purgable_state[state]);
496*0f4c859eSApple OSS Distributions }
497*0f4c859eSApple OSS Distributions /* footprint4 == footprint3 */
498*0f4c859eSApple OSS Distributions footprint[4] = task_footprint();
499*0f4c859eSApple OSS Distributions T_LOG(" footprint[4] = %llu", footprint[4]);
500*0f4c859eSApple OSS Distributions if (footprint[4] != footprint[3]) {
501*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[4] != footprint[3]");
502*0f4c859eSApple OSS Distributions }
503*0f4c859eSApple OSS Distributions
504*0f4c859eSApple OSS Distributions T_LOG("--> unwire %llu bytes", vm_size / 2);
505*0f4c859eSApple OSS Distributions ret = munlock((char *)vm_addr, (size_t) (vm_size / 2));
506*0f4c859eSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "munlock()");
507*0f4c859eSApple OSS Distributions
508*0f4c859eSApple OSS Distributions /* footprint5 == footprint4 - (vm_size/2) (unless memory pressure) */
509*0f4c859eSApple OSS Distributions /* footprint5 == footprint0 */
510*0f4c859eSApple OSS Distributions footprint[5] = task_footprint();
511*0f4c859eSApple OSS Distributions T_LOG(" footprint[5] = %llu", footprint[5]);
512*0f4c859eSApple OSS Distributions if (footprint[5] != footprint[4] - (vm_size / 2)) {
513*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[5] != footprint[4] - (vm_size/2)");
514*0f4c859eSApple OSS Distributions }
515*0f4c859eSApple OSS Distributions if (footprint[5] != footprint[0]) {
516*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[5] != footprint[0]");
517*0f4c859eSApple OSS Distributions }
518*0f4c859eSApple OSS Distributions
519*0f4c859eSApple OSS Distributions T_LOG("--> VOLATILE");
520*0f4c859eSApple OSS Distributions state = VM_PURGABLE_VOLATILE;
521*0f4c859eSApple OSS Distributions kr = mach_vm_purgable_control(mach_task_self(),
522*0f4c859eSApple OSS Distributions vm_addr,
523*0f4c859eSApple OSS Distributions VM_PURGABLE_SET_STATE,
524*0f4c859eSApple OSS Distributions &state);
525*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_purgable_control(VOLATILE)");
526*0f4c859eSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_EMPTY, "EMPTY->VOLATILE: state == %s",
527*0f4c859eSApple OSS Distributions vm_purgable_state[state]);
528*0f4c859eSApple OSS Distributions /* footprint6 == footprint5 */
529*0f4c859eSApple OSS Distributions /* footprint6 == footprint0 */
530*0f4c859eSApple OSS Distributions footprint[6] = task_footprint();
531*0f4c859eSApple OSS Distributions T_LOG(" footprint[6] = %llu", footprint[6]);
532*0f4c859eSApple OSS Distributions if (footprint[6] != footprint[5]) {
533*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[6] != footprint[5]");
534*0f4c859eSApple OSS Distributions }
535*0f4c859eSApple OSS Distributions if (footprint[6] != footprint[0]) {
536*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[6] != footprint[0]");
537*0f4c859eSApple OSS Distributions }
538*0f4c859eSApple OSS Distributions
539*0f4c859eSApple OSS Distributions T_LOG("--> NONVOLATILE");
540*0f4c859eSApple OSS Distributions state = VM_PURGABLE_NONVOLATILE;
541*0f4c859eSApple OSS Distributions kr = mach_vm_purgable_control(mach_task_self(),
542*0f4c859eSApple OSS Distributions vm_addr,
543*0f4c859eSApple OSS Distributions VM_PURGABLE_SET_STATE,
544*0f4c859eSApple OSS Distributions &state);
545*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_purgable_control(NONVOLATILE)");
546*0f4c859eSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_EMPTY, "EMPTY->NONVOLATILE: state == %s",
547*0f4c859eSApple OSS Distributions vm_purgable_state[state]);
548*0f4c859eSApple OSS Distributions /* footprint7 == footprint6 */
549*0f4c859eSApple OSS Distributions /* footprint7 == footprint0 */
550*0f4c859eSApple OSS Distributions footprint[7] = task_footprint();
551*0f4c859eSApple OSS Distributions T_LOG(" footprint[7] = %llu", footprint[7]);
552*0f4c859eSApple OSS Distributions if (footprint[7] != footprint[6]) {
553*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[7] != footprint[6]");
554*0f4c859eSApple OSS Distributions }
555*0f4c859eSApple OSS Distributions if (footprint[7] != footprint[0]) {
556*0f4c859eSApple OSS Distributions T_LOG("WARN: footprint[7] != footprint[0]");
557*0f4c859eSApple OSS Distributions }
558*0f4c859eSApple OSS Distributions }
559*0f4c859eSApple OSS Distributions
560*0f4c859eSApple OSS Distributions T_DECL(madvise_shared, "test madvise shared for rdar://problem/2295713 logging \
561*0f4c859eSApple OSS Distributions rethink needs madvise(MADV_FREE_HARDER)",
562*0f4c859eSApple OSS Distributions T_META_RUN_CONCURRENTLY(false),
563*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
564*0f4c859eSApple OSS Distributions {
565*0f4c859eSApple OSS Distributions vm_address_t vmaddr = 0, vmaddr2 = 0;
566*0f4c859eSApple OSS Distributions vm_size_t vmsize, vmsize1, vmsize2;
567*0f4c859eSApple OSS Distributions kern_return_t kr;
568*0f4c859eSApple OSS Distributions char *cp;
569*0f4c859eSApple OSS Distributions vm_prot_t curprot, maxprot;
570*0f4c859eSApple OSS Distributions int ret;
571*0f4c859eSApple OSS Distributions task_vm_info_data_t ti;
572*0f4c859eSApple OSS Distributions mach_msg_type_number_t ti_count;
573*0f4c859eSApple OSS Distributions int vmflags;
574*0f4c859eSApple OSS Distributions uint64_t footprint_before, footprint_after;
575*0f4c859eSApple OSS Distributions
576*0f4c859eSApple OSS Distributions vmsize1 = 64 * 1024; /* 64KB to madvise() */
577*0f4c859eSApple OSS Distributions vmsize2 = 32 * 1024; /* 32KB to mlock() */
578*0f4c859eSApple OSS Distributions vmsize = vmsize1 + vmsize2;
579*0f4c859eSApple OSS Distributions vmflags = VM_FLAGS_ANYWHERE;
580*0f4c859eSApple OSS Distributions VM_SET_FLAGS_ALIAS(vmflags, VM_MEMORY_MALLOC);
581*0f4c859eSApple OSS Distributions kr = vm_allocate(mach_task_self(),
582*0f4c859eSApple OSS Distributions &vmaddr,
583*0f4c859eSApple OSS Distributions vmsize,
584*0f4c859eSApple OSS Distributions vmflags);
585*0f4c859eSApple OSS Distributions T_QUIET;
586*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "vm_allocate()");
587*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
588*0f4c859eSApple OSS Distributions goto done;
589*0f4c859eSApple OSS Distributions }
590*0f4c859eSApple OSS Distributions
591*0f4c859eSApple OSS Distributions for (cp = (char *)(uintptr_t)vmaddr;
592*0f4c859eSApple OSS Distributions cp < (char *)(uintptr_t)(vmaddr + vmsize);
593*0f4c859eSApple OSS Distributions cp++) {
594*0f4c859eSApple OSS Distributions *cp = 'x';
595*0f4c859eSApple OSS Distributions }
596*0f4c859eSApple OSS Distributions
597*0f4c859eSApple OSS Distributions kr = vm_remap(mach_task_self(),
598*0f4c859eSApple OSS Distributions &vmaddr2,
599*0f4c859eSApple OSS Distributions vmsize,
600*0f4c859eSApple OSS Distributions 0, /* mask */
601*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
602*0f4c859eSApple OSS Distributions mach_task_self(),
603*0f4c859eSApple OSS Distributions vmaddr,
604*0f4c859eSApple OSS Distributions FALSE, /* copy */
605*0f4c859eSApple OSS Distributions &curprot,
606*0f4c859eSApple OSS Distributions &maxprot,
607*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
608*0f4c859eSApple OSS Distributions T_QUIET;
609*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "vm_remap()");
610*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
611*0f4c859eSApple OSS Distributions goto done;
612*0f4c859eSApple OSS Distributions }
613*0f4c859eSApple OSS Distributions
614*0f4c859eSApple OSS Distributions for (cp = (char *)(uintptr_t)vmaddr2;
615*0f4c859eSApple OSS Distributions cp < (char *)(uintptr_t)(vmaddr2 + vmsize);
616*0f4c859eSApple OSS Distributions cp++) {
617*0f4c859eSApple OSS Distributions T_QUIET;
618*0f4c859eSApple OSS Distributions T_EXPECT_EQ(*cp, 'x', "vmaddr=%p vmaddr2=%p %p:0x%x",
619*0f4c859eSApple OSS Distributions (void *)(uintptr_t)vmaddr,
620*0f4c859eSApple OSS Distributions (void *)(uintptr_t)vmaddr2,
621*0f4c859eSApple OSS Distributions (void *)cp,
622*0f4c859eSApple OSS Distributions (unsigned char)*cp);
623*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
624*0f4c859eSApple OSS Distributions goto done;
625*0f4c859eSApple OSS Distributions }
626*0f4c859eSApple OSS Distributions }
627*0f4c859eSApple OSS Distributions cp = (char *)(uintptr_t)vmaddr;
628*0f4c859eSApple OSS Distributions *cp = 'X';
629*0f4c859eSApple OSS Distributions cp = (char *)(uintptr_t)vmaddr2;
630*0f4c859eSApple OSS Distributions T_QUIET;
631*0f4c859eSApple OSS Distributions T_EXPECT_EQ(*cp, 'X', "memory was not properly shared");
632*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
633*0f4c859eSApple OSS Distributions goto done;
634*0f4c859eSApple OSS Distributions }
635*0f4c859eSApple OSS Distributions
636*0f4c859eSApple OSS Distributions #if defined(__x86_64__) || defined(__i386__)
637*0f4c859eSApple OSS Distributions if (COMM_PAGE_READ(uint64_t, CPU_CAPABILITIES64) & kIsTranslated) {
638*0f4c859eSApple OSS Distributions T_LOG("Skipping madvise reusable tests because we're running under translation.");
639*0f4c859eSApple OSS Distributions goto done;
640*0f4c859eSApple OSS Distributions }
641*0f4c859eSApple OSS Distributions #endif /* defined(__x86_64__) || defined(__i386__) */
642*0f4c859eSApple OSS Distributions
643*0f4c859eSApple OSS Distributions ret = mlock((char *)(uintptr_t)(vmaddr2 + vmsize1),
644*0f4c859eSApple OSS Distributions vmsize2);
645*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_POSIX_SUCCESS(ret, "mlock()");
646*0f4c859eSApple OSS Distributions
647*0f4c859eSApple OSS Distributions footprint_before = task_footprint();
648*0f4c859eSApple OSS Distributions
649*0f4c859eSApple OSS Distributions ret = madvise((char *)(uintptr_t)vmaddr,
650*0f4c859eSApple OSS Distributions vmsize1,
651*0f4c859eSApple OSS Distributions MADV_FREE_REUSABLE);
652*0f4c859eSApple OSS Distributions T_QUIET;
653*0f4c859eSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(ret, "madvise()");
654*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
655*0f4c859eSApple OSS Distributions goto done;
656*0f4c859eSApple OSS Distributions }
657*0f4c859eSApple OSS Distributions
658*0f4c859eSApple OSS Distributions footprint_after = task_footprint();
659*0f4c859eSApple OSS Distributions T_ASSERT_EQ(footprint_after, footprint_before - 2 * vmsize1, NULL);
660*0f4c859eSApple OSS Distributions
661*0f4c859eSApple OSS Distributions ti_count = TASK_VM_INFO_COUNT;
662*0f4c859eSApple OSS Distributions kr = task_info(mach_task_self(),
663*0f4c859eSApple OSS Distributions TASK_VM_INFO,
664*0f4c859eSApple OSS Distributions (task_info_t) &ti,
665*0f4c859eSApple OSS Distributions &ti_count);
666*0f4c859eSApple OSS Distributions T_QUIET;
667*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "task_info()");
668*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
669*0f4c859eSApple OSS Distributions goto done;
670*0f4c859eSApple OSS Distributions }
671*0f4c859eSApple OSS Distributions
672*0f4c859eSApple OSS Distributions T_QUIET;
673*0f4c859eSApple OSS Distributions T_EXPECT_EQ(ti.reusable, 2ULL * vmsize1, "ti.reusable=%lld expected %lld",
674*0f4c859eSApple OSS Distributions ti.reusable, (uint64_t)(2 * vmsize1));
675*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
676*0f4c859eSApple OSS Distributions goto done;
677*0f4c859eSApple OSS Distributions }
678*0f4c859eSApple OSS Distributions
679*0f4c859eSApple OSS Distributions done:
680*0f4c859eSApple OSS Distributions if (vmaddr != 0) {
681*0f4c859eSApple OSS Distributions vm_deallocate(mach_task_self(), vmaddr, vmsize);
682*0f4c859eSApple OSS Distributions vmaddr = 0;
683*0f4c859eSApple OSS Distributions }
684*0f4c859eSApple OSS Distributions if (vmaddr2 != 0) {
685*0f4c859eSApple OSS Distributions vm_deallocate(mach_task_self(), vmaddr2, vmsize);
686*0f4c859eSApple OSS Distributions vmaddr2 = 0;
687*0f4c859eSApple OSS Distributions }
688*0f4c859eSApple OSS Distributions }
689*0f4c859eSApple OSS Distributions
690*0f4c859eSApple OSS Distributions T_DECL(madvise_purgeable_can_reuse, "test madvise purgeable can reuse for \
691*0f4c859eSApple OSS Distributions rdar://problem/37476183 Preview Footprint memory regressions ~100MB \
692*0f4c859eSApple OSS Distributions [ purgeable_malloc became eligible for reuse ]",
693*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
694*0f4c859eSApple OSS Distributions {
695*0f4c859eSApple OSS Distributions #if defined(__x86_64__) || defined(__i386__)
696*0f4c859eSApple OSS Distributions if (COMM_PAGE_READ(uint64_t, CPU_CAPABILITIES64) & kIsTranslated) {
697*0f4c859eSApple OSS Distributions T_SKIP("madvise reusable is not supported under Rosetta translation. Skipping.)");
698*0f4c859eSApple OSS Distributions }
699*0f4c859eSApple OSS Distributions #endif /* defined(__x86_64__) || defined(__i386__) */
700*0f4c859eSApple OSS Distributions vm_address_t vmaddr = 0;
701*0f4c859eSApple OSS Distributions vm_size_t vmsize;
702*0f4c859eSApple OSS Distributions kern_return_t kr;
703*0f4c859eSApple OSS Distributions char *cp;
704*0f4c859eSApple OSS Distributions int ret;
705*0f4c859eSApple OSS Distributions
706*0f4c859eSApple OSS Distributions vmsize = 10 * 1024 * 1024; /* 10MB */
707*0f4c859eSApple OSS Distributions kr = vm_allocate(mach_task_self(),
708*0f4c859eSApple OSS Distributions &vmaddr,
709*0f4c859eSApple OSS Distributions vmsize,
710*0f4c859eSApple OSS Distributions (VM_FLAGS_ANYWHERE |
711*0f4c859eSApple OSS Distributions VM_FLAGS_PURGABLE |
712*0f4c859eSApple OSS Distributions VM_MAKE_TAG(VM_MEMORY_MALLOC)));
713*0f4c859eSApple OSS Distributions T_QUIET;
714*0f4c859eSApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "vm_allocate()");
715*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
716*0f4c859eSApple OSS Distributions goto done;
717*0f4c859eSApple OSS Distributions }
718*0f4c859eSApple OSS Distributions
719*0f4c859eSApple OSS Distributions for (cp = (char *)(uintptr_t)vmaddr;
720*0f4c859eSApple OSS Distributions cp < (char *)(uintptr_t)(vmaddr + vmsize);
721*0f4c859eSApple OSS Distributions cp++) {
722*0f4c859eSApple OSS Distributions *cp = 'x';
723*0f4c859eSApple OSS Distributions }
724*0f4c859eSApple OSS Distributions
725*0f4c859eSApple OSS Distributions ret = madvise((char *)(uintptr_t)vmaddr,
726*0f4c859eSApple OSS Distributions vmsize,
727*0f4c859eSApple OSS Distributions MADV_CAN_REUSE);
728*0f4c859eSApple OSS Distributions T_QUIET;
729*0f4c859eSApple OSS Distributions T_EXPECT_TRUE(((ret == -1) && (errno == EINVAL)), "madvise(): purgeable vm can't be adviced to reuse");
730*0f4c859eSApple OSS Distributions if (T_RESULT == T_RESULT_FAIL) {
731*0f4c859eSApple OSS Distributions goto done;
732*0f4c859eSApple OSS Distributions }
733*0f4c859eSApple OSS Distributions
734*0f4c859eSApple OSS Distributions done:
735*0f4c859eSApple OSS Distributions if (vmaddr != 0) {
736*0f4c859eSApple OSS Distributions vm_deallocate(mach_task_self(), vmaddr, vmsize);
737*0f4c859eSApple OSS Distributions vmaddr = 0;
738*0f4c859eSApple OSS Distributions }
739*0f4c859eSApple OSS Distributions }
740*0f4c859eSApple OSS Distributions
741*0f4c859eSApple OSS Distributions #define DEST_PATTERN 0xFEDCBA98
742*0f4c859eSApple OSS Distributions
743*0f4c859eSApple OSS Distributions T_DECL(map_read_overwrite, "test overwriting vm map from other map - \
744*0f4c859eSApple OSS Distributions rdar://31075370",
745*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
746*0f4c859eSApple OSS Distributions {
747*0f4c859eSApple OSS Distributions kern_return_t kr;
748*0f4c859eSApple OSS Distributions mach_vm_address_t vmaddr1, vmaddr2;
749*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize1, vmsize2;
750*0f4c859eSApple OSS Distributions int *ip;
751*0f4c859eSApple OSS Distributions int i;
752*0f4c859eSApple OSS Distributions
753*0f4c859eSApple OSS Distributions vmaddr1 = 0;
754*0f4c859eSApple OSS Distributions vmsize1 = 4 * 4096;
755*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(),
756*0f4c859eSApple OSS Distributions &vmaddr1,
757*0f4c859eSApple OSS Distributions vmsize1,
758*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE);
759*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
760*0f4c859eSApple OSS Distributions
761*0f4c859eSApple OSS Distributions ip = (int *)(uintptr_t)vmaddr1;
762*0f4c859eSApple OSS Distributions for (i = 0; i < vmsize1 / sizeof(*ip); i++) {
763*0f4c859eSApple OSS Distributions ip[i] = i;
764*0f4c859eSApple OSS Distributions }
765*0f4c859eSApple OSS Distributions
766*0f4c859eSApple OSS Distributions vmaddr2 = 0;
767*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(),
768*0f4c859eSApple OSS Distributions &vmaddr2,
769*0f4c859eSApple OSS Distributions vmsize1,
770*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE);
771*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
772*0f4c859eSApple OSS Distributions
773*0f4c859eSApple OSS Distributions ip = (int *)(uintptr_t)vmaddr2;
774*0f4c859eSApple OSS Distributions for (i = 0; i < vmsize1 / sizeof(*ip); i++) {
775*0f4c859eSApple OSS Distributions ip[i] = DEST_PATTERN;
776*0f4c859eSApple OSS Distributions }
777*0f4c859eSApple OSS Distributions
778*0f4c859eSApple OSS Distributions vmsize2 = vmsize1 - 2 * (sizeof(*ip));
779*0f4c859eSApple OSS Distributions kr = mach_vm_read_overwrite(mach_task_self(),
780*0f4c859eSApple OSS Distributions vmaddr1 + sizeof(*ip),
781*0f4c859eSApple OSS Distributions vmsize2,
782*0f4c859eSApple OSS Distributions vmaddr2 + sizeof(*ip),
783*0f4c859eSApple OSS Distributions &vmsize2);
784*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_read_overwrite()");
785*0f4c859eSApple OSS Distributions
786*0f4c859eSApple OSS Distributions ip = (int *)(uintptr_t)vmaddr2;
787*0f4c859eSApple OSS Distributions for (i = 0; i < 1; i++) {
788*0f4c859eSApple OSS Distributions T_QUIET;
789*0f4c859eSApple OSS Distributions T_ASSERT_EQ(ip[i], DEST_PATTERN, "vmaddr2[%d] = 0x%x instead of 0x%x",
790*0f4c859eSApple OSS Distributions i, ip[i], DEST_PATTERN);
791*0f4c859eSApple OSS Distributions }
792*0f4c859eSApple OSS Distributions for (; i < (vmsize1 - 2) / sizeof(*ip); i++) {
793*0f4c859eSApple OSS Distributions T_QUIET;
794*0f4c859eSApple OSS Distributions T_ASSERT_EQ(ip[i], i, "vmaddr2[%d] = 0x%x instead of 0x%x",
795*0f4c859eSApple OSS Distributions i, ip[i], i);
796*0f4c859eSApple OSS Distributions }
797*0f4c859eSApple OSS Distributions for (; i < vmsize1 / sizeof(*ip); i++) {
798*0f4c859eSApple OSS Distributions T_QUIET;
799*0f4c859eSApple OSS Distributions T_ASSERT_EQ(ip[i], DEST_PATTERN, "vmaddr2[%d] = 0x%x instead of 0x%x",
800*0f4c859eSApple OSS Distributions i, ip[i], DEST_PATTERN);
801*0f4c859eSApple OSS Distributions }
802*0f4c859eSApple OSS Distributions }
803*0f4c859eSApple OSS Distributions
804*0f4c859eSApple OSS Distributions T_DECL(copy_none_use_pmap, "test copy-on-write remapping of COPY_NONE vm \
805*0f4c859eSApple OSS Distributions objects - rdar://35610377",
806*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
807*0f4c859eSApple OSS Distributions {
808*0f4c859eSApple OSS Distributions kern_return_t kr;
809*0f4c859eSApple OSS Distributions mach_vm_address_t vmaddr1, vmaddr2, vmaddr3;
810*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize;
811*0f4c859eSApple OSS Distributions vm_prot_t curprot, maxprot;
812*0f4c859eSApple OSS Distributions
813*0f4c859eSApple OSS Distributions vmsize = 32 * 1024 * 1024;
814*0f4c859eSApple OSS Distributions
815*0f4c859eSApple OSS Distributions vmaddr1 = 0;
816*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(),
817*0f4c859eSApple OSS Distributions &vmaddr1,
818*0f4c859eSApple OSS Distributions vmsize,
819*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
820*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
821*0f4c859eSApple OSS Distributions
822*0f4c859eSApple OSS Distributions memset((void *)(uintptr_t)vmaddr1, 'x', vmsize);
823*0f4c859eSApple OSS Distributions
824*0f4c859eSApple OSS Distributions vmaddr2 = 0;
825*0f4c859eSApple OSS Distributions kr = mach_vm_remap(mach_task_self(),
826*0f4c859eSApple OSS Distributions &vmaddr2,
827*0f4c859eSApple OSS Distributions vmsize,
828*0f4c859eSApple OSS Distributions 0, /* mask */
829*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
830*0f4c859eSApple OSS Distributions mach_task_self(),
831*0f4c859eSApple OSS Distributions vmaddr1,
832*0f4c859eSApple OSS Distributions TRUE, /* copy */
833*0f4c859eSApple OSS Distributions &curprot,
834*0f4c859eSApple OSS Distributions &maxprot,
835*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
836*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_remap() #1");
837*0f4c859eSApple OSS Distributions
838*0f4c859eSApple OSS Distributions vmaddr3 = 0;
839*0f4c859eSApple OSS Distributions kr = mach_vm_remap(mach_task_self(),
840*0f4c859eSApple OSS Distributions &vmaddr3,
841*0f4c859eSApple OSS Distributions vmsize,
842*0f4c859eSApple OSS Distributions 0, /* mask */
843*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
844*0f4c859eSApple OSS Distributions mach_task_self(),
845*0f4c859eSApple OSS Distributions vmaddr2,
846*0f4c859eSApple OSS Distributions TRUE, /* copy */
847*0f4c859eSApple OSS Distributions &curprot,
848*0f4c859eSApple OSS Distributions &maxprot,
849*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
850*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_remap() #2");
851*0f4c859eSApple OSS Distributions }
852*0f4c859eSApple OSS Distributions
853*0f4c859eSApple OSS Distributions T_DECL(purgable_deny, "test purgeable memory is not allowed to be converted to \
854*0f4c859eSApple OSS Distributions non-purgeable - rdar://31990033",
855*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
856*0f4c859eSApple OSS Distributions {
857*0f4c859eSApple OSS Distributions kern_return_t kr;
858*0f4c859eSApple OSS Distributions vm_address_t vmaddr;
859*0f4c859eSApple OSS Distributions vm_purgable_t state;
860*0f4c859eSApple OSS Distributions
861*0f4c859eSApple OSS Distributions vmaddr = 0;
862*0f4c859eSApple OSS Distributions kr = vm_allocate(mach_task_self(), &vmaddr, 1,
863*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
864*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
865*0f4c859eSApple OSS Distributions
866*0f4c859eSApple OSS Distributions state = VM_PURGABLE_DENY;
867*0f4c859eSApple OSS Distributions kr = vm_purgable_control(mach_task_self(), vmaddr,
868*0f4c859eSApple OSS Distributions VM_PURGABLE_SET_STATE, &state);
869*0f4c859eSApple OSS Distributions T_ASSERT_EQ(kr, KERN_INVALID_ARGUMENT,
870*0f4c859eSApple OSS Distributions "vm_purgable_control(VM_PURGABLE_DENY) -> 0x%x (%s)",
871*0f4c859eSApple OSS Distributions kr, mach_error_string(kr));
872*0f4c859eSApple OSS Distributions
873*0f4c859eSApple OSS Distributions kr = vm_deallocate(mach_task_self(), vmaddr, 1);
874*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate()");
875*0f4c859eSApple OSS Distributions }
876*0f4c859eSApple OSS Distributions
877*0f4c859eSApple OSS Distributions #define VMSIZE 0x10000
878*0f4c859eSApple OSS Distributions
879*0f4c859eSApple OSS Distributions T_DECL(vm_remap_zero, "test vm map of zero size - rdar://33114981",
880*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
881*0f4c859eSApple OSS Distributions {
882*0f4c859eSApple OSS Distributions kern_return_t kr;
883*0f4c859eSApple OSS Distributions mach_vm_address_t vmaddr1, vmaddr2;
884*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize;
885*0f4c859eSApple OSS Distributions vm_prot_t curprot, maxprot;
886*0f4c859eSApple OSS Distributions
887*0f4c859eSApple OSS Distributions vmaddr1 = 0;
888*0f4c859eSApple OSS Distributions vmsize = VMSIZE;
889*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(),
890*0f4c859eSApple OSS Distributions &vmaddr1,
891*0f4c859eSApple OSS Distributions vmsize,
892*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE);
893*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
894*0f4c859eSApple OSS Distributions
895*0f4c859eSApple OSS Distributions vmaddr2 = 0;
896*0f4c859eSApple OSS Distributions vmsize = 0;
897*0f4c859eSApple OSS Distributions kr = mach_vm_remap(mach_task_self(),
898*0f4c859eSApple OSS Distributions &vmaddr2,
899*0f4c859eSApple OSS Distributions vmsize,
900*0f4c859eSApple OSS Distributions 0,
901*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
902*0f4c859eSApple OSS Distributions mach_task_self(),
903*0f4c859eSApple OSS Distributions vmaddr1,
904*0f4c859eSApple OSS Distributions FALSE,
905*0f4c859eSApple OSS Distributions &curprot,
906*0f4c859eSApple OSS Distributions &maxprot,
907*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
908*0f4c859eSApple OSS Distributions T_ASSERT_EQ(kr, KERN_INVALID_ARGUMENT, "vm_remap(size=0x%llx) 0x%x (%s)",
909*0f4c859eSApple OSS Distributions vmsize, kr, mach_error_string(kr));
910*0f4c859eSApple OSS Distributions
911*0f4c859eSApple OSS Distributions vmaddr2 = 0;
912*0f4c859eSApple OSS Distributions vmsize = (mach_vm_size_t)-2;
913*0f4c859eSApple OSS Distributions kr = mach_vm_remap(mach_task_self(),
914*0f4c859eSApple OSS Distributions &vmaddr2,
915*0f4c859eSApple OSS Distributions vmsize,
916*0f4c859eSApple OSS Distributions 0,
917*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
918*0f4c859eSApple OSS Distributions mach_task_self(),
919*0f4c859eSApple OSS Distributions vmaddr1,
920*0f4c859eSApple OSS Distributions FALSE,
921*0f4c859eSApple OSS Distributions &curprot,
922*0f4c859eSApple OSS Distributions &maxprot,
923*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
924*0f4c859eSApple OSS Distributions T_ASSERT_EQ(kr, KERN_INVALID_ARGUMENT, "vm_remap(size=0x%llx) 0x%x (%s)",
925*0f4c859eSApple OSS Distributions vmsize, kr, mach_error_string(kr));
926*0f4c859eSApple OSS Distributions }
927*0f4c859eSApple OSS Distributions
928*0f4c859eSApple OSS Distributions extern int __shared_region_check_np(uint64_t *);
929*0f4c859eSApple OSS Distributions
930*0f4c859eSApple OSS Distributions T_DECL(nested_pmap_trigger, "nested pmap should only be triggered from kernel \
931*0f4c859eSApple OSS Distributions - rdar://problem/41481703",
932*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
933*0f4c859eSApple OSS Distributions {
934*0f4c859eSApple OSS Distributions int ret;
935*0f4c859eSApple OSS Distributions kern_return_t kr;
936*0f4c859eSApple OSS Distributions mach_vm_address_t sr_start;
937*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize;
938*0f4c859eSApple OSS Distributions mach_vm_address_t vmaddr;
939*0f4c859eSApple OSS Distributions mach_port_t mem_entry;
940*0f4c859eSApple OSS Distributions
941*0f4c859eSApple OSS Distributions ret = __shared_region_check_np(&sr_start);
942*0f4c859eSApple OSS Distributions if (ret != 0) {
943*0f4c859eSApple OSS Distributions int saved_errno;
944*0f4c859eSApple OSS Distributions saved_errno = errno;
945*0f4c859eSApple OSS Distributions
946*0f4c859eSApple OSS Distributions T_ASSERT_EQ(saved_errno, ENOMEM, "__shared_region_check_np() %d (%s)",
947*0f4c859eSApple OSS Distributions saved_errno, strerror(saved_errno));
948*0f4c859eSApple OSS Distributions T_END;
949*0f4c859eSApple OSS Distributions }
950*0f4c859eSApple OSS Distributions
951*0f4c859eSApple OSS Distributions vmsize = PAGE_SIZE;
952*0f4c859eSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
953*0f4c859eSApple OSS Distributions &vmsize,
954*0f4c859eSApple OSS Distributions sr_start,
955*0f4c859eSApple OSS Distributions MAP_MEM_VM_SHARE | VM_PROT_READ,
956*0f4c859eSApple OSS Distributions &mem_entry,
957*0f4c859eSApple OSS Distributions MACH_PORT_NULL);
958*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "make_memory_entry(0x%llx)", sr_start);
959*0f4c859eSApple OSS Distributions
960*0f4c859eSApple OSS Distributions vmaddr = 0;
961*0f4c859eSApple OSS Distributions kr = mach_vm_map(mach_task_self(),
962*0f4c859eSApple OSS Distributions &vmaddr,
963*0f4c859eSApple OSS Distributions vmsize,
964*0f4c859eSApple OSS Distributions 0,
965*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
966*0f4c859eSApple OSS Distributions mem_entry,
967*0f4c859eSApple OSS Distributions 0,
968*0f4c859eSApple OSS Distributions FALSE,
969*0f4c859eSApple OSS Distributions VM_PROT_READ,
970*0f4c859eSApple OSS Distributions VM_PROT_READ,
971*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
972*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_map()");
973*0f4c859eSApple OSS Distributions }
974*0f4c859eSApple OSS Distributions
975*0f4c859eSApple OSS Distributions static const char *prot_str[] = { "---", "r--", "-w-", "rw-", "--x", "r-x", "-wx", "rwx" };
976*0f4c859eSApple OSS Distributions static const char *share_mode_str[] = { "---", "COW", "PRIVATE", "EMPTY", "SHARED", "TRUESHARED", "PRIVATE_ALIASED", "SHARED_ALIASED", "LARGE_PAGE" };
977*0f4c859eSApple OSS Distributions
978*0f4c859eSApple OSS Distributions T_DECL(shared_region_share_writable, "sharing a writable mapping of the shared region shoudl not give write access to shared region - rdar://problem/74469953",
979*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
980*0f4c859eSApple OSS Distributions {
981*0f4c859eSApple OSS Distributions int ret;
982*0f4c859eSApple OSS Distributions uint64_t sr_start;
983*0f4c859eSApple OSS Distributions kern_return_t kr;
984*0f4c859eSApple OSS Distributions mach_vm_address_t address, tmp_address, remap_address;
985*0f4c859eSApple OSS Distributions mach_vm_size_t size, tmp_size, remap_size;
986*0f4c859eSApple OSS Distributions uint32_t depth;
987*0f4c859eSApple OSS Distributions mach_msg_type_number_t count;
988*0f4c859eSApple OSS Distributions vm_region_submap_info_data_64_t info;
989*0f4c859eSApple OSS Distributions vm_prot_t cur_prot, max_prot;
990*0f4c859eSApple OSS Distributions uint32_t before, after, remap;
991*0f4c859eSApple OSS Distributions mach_port_t mem_entry;
992*0f4c859eSApple OSS Distributions
993*0f4c859eSApple OSS Distributions ret = __shared_region_check_np(&sr_start);
994*0f4c859eSApple OSS Distributions if (ret != 0) {
995*0f4c859eSApple OSS Distributions int saved_errno;
996*0f4c859eSApple OSS Distributions saved_errno = errno;
997*0f4c859eSApple OSS Distributions
998*0f4c859eSApple OSS Distributions T_ASSERT_EQ(saved_errno, ENOMEM, "__shared_region_check_np() %d (%s)",
999*0f4c859eSApple OSS Distributions saved_errno, strerror(saved_errno));
1000*0f4c859eSApple OSS Distributions T_END;
1001*0f4c859eSApple OSS Distributions }
1002*0f4c859eSApple OSS Distributions T_LOG("SHARED_REGION_BASE 0x%llx", SHARED_REGION_BASE);
1003*0f4c859eSApple OSS Distributions T_LOG("SHARED_REGION_SIZE 0x%llx", SHARED_REGION_SIZE);
1004*0f4c859eSApple OSS Distributions T_LOG("shared region starts at 0x%llx", sr_start);
1005*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_GE(sr_start, SHARED_REGION_BASE,
1006*0f4c859eSApple OSS Distributions "shared region starts below BASE");
1007*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_LT(sr_start, SHARED_REGION_BASE + SHARED_REGION_SIZE,
1008*0f4c859eSApple OSS Distributions "shared region starts above BASE+SIZE");
1009*0f4c859eSApple OSS Distributions
1010*0f4c859eSApple OSS Distributions /*
1011*0f4c859eSApple OSS Distributions * Step 1 - check that one can not get write access to a read-only
1012*0f4c859eSApple OSS Distributions * mapping in the shared region.
1013*0f4c859eSApple OSS Distributions */
1014*0f4c859eSApple OSS Distributions size = 0;
1015*0f4c859eSApple OSS Distributions for (address = SHARED_REGION_BASE;
1016*0f4c859eSApple OSS Distributions address < SHARED_REGION_BASE + SHARED_REGION_SIZE;
1017*0f4c859eSApple OSS Distributions address += size) {
1018*0f4c859eSApple OSS Distributions size = 0;
1019*0f4c859eSApple OSS Distributions depth = 99;
1020*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1021*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1022*0f4c859eSApple OSS Distributions &address,
1023*0f4c859eSApple OSS Distributions &size,
1024*0f4c859eSApple OSS Distributions &depth,
1025*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1026*0f4c859eSApple OSS Distributions &count);
1027*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_region_recurse()");
1028*0f4c859eSApple OSS Distributions if (kr == KERN_INVALID_ADDRESS) {
1029*0f4c859eSApple OSS Distributions T_SKIP("could not find read-only nested mapping");
1030*0f4c859eSApple OSS Distributions T_END;
1031*0f4c859eSApple OSS Distributions }
1032*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1033*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1034*0f4c859eSApple OSS Distributions address, address + size, depth,
1035*0f4c859eSApple OSS Distributions prot_str[info.protection],
1036*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1037*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1038*0f4c859eSApple OSS Distributions info.object_id);
1039*0f4c859eSApple OSS Distributions if (depth > 0 &&
1040*0f4c859eSApple OSS Distributions (info.protection == VM_PROT_READ) &&
1041*0f4c859eSApple OSS Distributions (info.max_protection == VM_PROT_READ)) {
1042*0f4c859eSApple OSS Distributions /* nested and read-only: bingo! */
1043*0f4c859eSApple OSS Distributions break;
1044*0f4c859eSApple OSS Distributions }
1045*0f4c859eSApple OSS Distributions }
1046*0f4c859eSApple OSS Distributions if (address >= SHARED_REGION_BASE + SHARED_REGION_SIZE) {
1047*0f4c859eSApple OSS Distributions T_SKIP("could not find read-only nested mapping");
1048*0f4c859eSApple OSS Distributions T_END;
1049*0f4c859eSApple OSS Distributions }
1050*0f4c859eSApple OSS Distributions
1051*0f4c859eSApple OSS Distributions /* test vm_remap() of RO */
1052*0f4c859eSApple OSS Distributions before = *(uint32_t *)(uintptr_t)address;
1053*0f4c859eSApple OSS Distributions remap_address = 0;
1054*0f4c859eSApple OSS Distributions remap_size = size;
1055*0f4c859eSApple OSS Distributions kr = mach_vm_remap(mach_task_self(),
1056*0f4c859eSApple OSS Distributions &remap_address,
1057*0f4c859eSApple OSS Distributions remap_size,
1058*0f4c859eSApple OSS Distributions 0,
1059*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
1060*0f4c859eSApple OSS Distributions mach_task_self(),
1061*0f4c859eSApple OSS Distributions address,
1062*0f4c859eSApple OSS Distributions FALSE,
1063*0f4c859eSApple OSS Distributions &cur_prot,
1064*0f4c859eSApple OSS Distributions &max_prot,
1065*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
1066*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_remap()");
1067*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(cur_prot, VM_PROT_READ, "cur_prot is read-only");
1068*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(max_prot, VM_PROT_READ, "max_prot is read-only");
1069*0f4c859eSApple OSS Distributions /* check that region is still nested */
1070*0f4c859eSApple OSS Distributions tmp_address = address;
1071*0f4c859eSApple OSS Distributions tmp_size = 0;
1072*0f4c859eSApple OSS Distributions depth = 99;
1073*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1074*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1075*0f4c859eSApple OSS Distributions &tmp_address,
1076*0f4c859eSApple OSS Distributions &tmp_size,
1077*0f4c859eSApple OSS Distributions &depth,
1078*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1079*0f4c859eSApple OSS Distributions &count);
1080*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1081*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1082*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1083*0f4c859eSApple OSS Distributions prot_str[info.protection],
1084*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1085*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1086*0f4c859eSApple OSS Distributions info.object_id);
1087*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1088*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1089*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1090*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "cur_prot still read-only");
1091*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "max_prot still read-only");
1092*0f4c859eSApple OSS Distributions /* check that new mapping is read-only */
1093*0f4c859eSApple OSS Distributions tmp_address = remap_address;
1094*0f4c859eSApple OSS Distributions tmp_size = 0;
1095*0f4c859eSApple OSS Distributions depth = 99;
1096*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1097*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1098*0f4c859eSApple OSS Distributions &tmp_address,
1099*0f4c859eSApple OSS Distributions &tmp_size,
1100*0f4c859eSApple OSS Distributions &depth,
1101*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1102*0f4c859eSApple OSS Distributions &count);
1103*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1104*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1105*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1106*0f4c859eSApple OSS Distributions prot_str[info.protection],
1107*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1108*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1109*0f4c859eSApple OSS Distributions info.object_id);
1110*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, remap_address, "address hasn't changed");
1111*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1112*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "new cur_prot read-only");
1113*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "new max_prot read-only");
1114*0f4c859eSApple OSS Distributions remap = *(uint32_t *)(uintptr_t)remap_address;
1115*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1116*0f4c859eSApple OSS Distributions // this would crash if actually read-only:
1117*0f4c859eSApple OSS Distributions // *(uint32_t *)(uintptr_t)remap_address = before + 1;
1118*0f4c859eSApple OSS Distributions after = *(uint32_t *)(uintptr_t)address;
1119*0f4c859eSApple OSS Distributions T_LOG("vm_remap(): 0x%llx 0x%x -> 0x%x", address, before, after);
1120*0f4c859eSApple OSS Distributions // *(uint32_t *)(uintptr_t)remap_address = before;
1121*0f4c859eSApple OSS Distributions if (before != after) {
1122*0f4c859eSApple OSS Distributions T_FAIL("vm_remap() bypassed copy-on-write");
1123*0f4c859eSApple OSS Distributions } else {
1124*0f4c859eSApple OSS Distributions T_PASS("vm_remap() did not bypass copy-on-write");
1125*0f4c859eSApple OSS Distributions }
1126*0f4c859eSApple OSS Distributions /* cleanup */
1127*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1128*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1129*0f4c859eSApple OSS Distributions T_PASS("vm_remap() read-only");
1130*0f4c859eSApple OSS Distributions
1131*0f4c859eSApple OSS Distributions #if defined(VM_MEMORY_ROSETTA)
1132*0f4c859eSApple OSS Distributions if (dlsym(RTLD_DEFAULT, "mach_vm_remap_new") == NULL) {
1133*0f4c859eSApple OSS Distributions T_PASS("vm_remap_new() is not present");
1134*0f4c859eSApple OSS Distributions goto skip_vm_remap_new_ro;
1135*0f4c859eSApple OSS Distributions }
1136*0f4c859eSApple OSS Distributions /* test vm_remap_new() of RO */
1137*0f4c859eSApple OSS Distributions before = *(uint32_t *)(uintptr_t)address;
1138*0f4c859eSApple OSS Distributions remap_address = 0;
1139*0f4c859eSApple OSS Distributions remap_size = size;
1140*0f4c859eSApple OSS Distributions cur_prot = VM_PROT_READ | VM_PROT_WRITE;
1141*0f4c859eSApple OSS Distributions max_prot = VM_PROT_READ | VM_PROT_WRITE;
1142*0f4c859eSApple OSS Distributions kr = mach_vm_remap_new(mach_task_self(),
1143*0f4c859eSApple OSS Distributions &remap_address,
1144*0f4c859eSApple OSS Distributions remap_size,
1145*0f4c859eSApple OSS Distributions 0,
1146*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
1147*0f4c859eSApple OSS Distributions mach_task_self(),
1148*0f4c859eSApple OSS Distributions address,
1149*0f4c859eSApple OSS Distributions FALSE,
1150*0f4c859eSApple OSS Distributions &cur_prot,
1151*0f4c859eSApple OSS Distributions &max_prot,
1152*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
1153*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_remap_new()");
1154*0f4c859eSApple OSS Distributions if (kr == KERN_PROTECTION_FAILURE) {
1155*0f4c859eSApple OSS Distributions /* wrong but not a security issue... */
1156*0f4c859eSApple OSS Distributions goto skip_vm_remap_new_ro;
1157*0f4c859eSApple OSS Distributions }
1158*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_remap_new()");
1159*0f4c859eSApple OSS Distributions remap = *(uint32_t *)(uintptr_t)remap_address;
1160*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1161*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before + 1;
1162*0f4c859eSApple OSS Distributions after = *(uint32_t *)(uintptr_t)address;
1163*0f4c859eSApple OSS Distributions T_LOG("vm_remap_new(): 0x%llx 0x%x -> 0x%x", address, before, after);
1164*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before;
1165*0f4c859eSApple OSS Distributions if (before != after) {
1166*0f4c859eSApple OSS Distributions T_FAIL("vm_remap_new() bypassed copy-on-write");
1167*0f4c859eSApple OSS Distributions } else {
1168*0f4c859eSApple OSS Distributions T_PASS("vm_remap_new() did not bypass copy-on-write");
1169*0f4c859eSApple OSS Distributions }
1170*0f4c859eSApple OSS Distributions /* check that region is still nested */
1171*0f4c859eSApple OSS Distributions tmp_address = address;
1172*0f4c859eSApple OSS Distributions tmp_size = 0;
1173*0f4c859eSApple OSS Distributions depth = 99;
1174*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1175*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1176*0f4c859eSApple OSS Distributions &tmp_address,
1177*0f4c859eSApple OSS Distributions &tmp_size,
1178*0f4c859eSApple OSS Distributions &depth,
1179*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1180*0f4c859eSApple OSS Distributions &count);
1181*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1182*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1183*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1184*0f4c859eSApple OSS Distributions prot_str[info.protection],
1185*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1186*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1187*0f4c859eSApple OSS Distributions info.object_id);
1188*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1189*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1190*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1191*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "cur_prot still read-only");
1192*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "max_prot still read-only");
1193*0f4c859eSApple OSS Distributions T_PASS("vm_remap_new() read-only");
1194*0f4c859eSApple OSS Distributions skip_vm_remap_new_ro:
1195*0f4c859eSApple OSS Distributions #else /* defined(VM_MEMORY_ROSETTA) */
1196*0f4c859eSApple OSS Distributions /* pre-BigSur SDK: no vm_remap_new() */
1197*0f4c859eSApple OSS Distributions T_LOG("No vm_remap_new() to test");
1198*0f4c859eSApple OSS Distributions #endif /* defined(VM_MEMORY_ROSETTA) */
1199*0f4c859eSApple OSS Distributions
1200*0f4c859eSApple OSS Distributions /* test mach_make_memory_entry_64(VM_SHARE) of RO */
1201*0f4c859eSApple OSS Distributions before = *(uint32_t *)(uintptr_t)address;
1202*0f4c859eSApple OSS Distributions remap_size = size;
1203*0f4c859eSApple OSS Distributions mem_entry = MACH_PORT_NULL;
1204*0f4c859eSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
1205*0f4c859eSApple OSS Distributions &remap_size,
1206*0f4c859eSApple OSS Distributions address,
1207*0f4c859eSApple OSS Distributions MAP_MEM_VM_SHARE | VM_PROT_READ | VM_PROT_WRITE,
1208*0f4c859eSApple OSS Distributions &mem_entry,
1209*0f4c859eSApple OSS Distributions MACH_PORT_NULL);
1210*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "mach_make_memory_entry_64(VM_SHARE)");
1211*0f4c859eSApple OSS Distributions if (kr == KERN_PROTECTION_FAILURE) {
1212*0f4c859eSApple OSS Distributions /* wrong but not a security issue... */
1213*0f4c859eSApple OSS Distributions goto skip_mem_entry_vm_share_ro;
1214*0f4c859eSApple OSS Distributions }
1215*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_make_memory_entry_64(VM_SHARE)");
1216*0f4c859eSApple OSS Distributions remap_address = 0;
1217*0f4c859eSApple OSS Distributions kr = mach_vm_map(mach_task_self(),
1218*0f4c859eSApple OSS Distributions &remap_address,
1219*0f4c859eSApple OSS Distributions remap_size,
1220*0f4c859eSApple OSS Distributions 0, /* mask */
1221*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
1222*0f4c859eSApple OSS Distributions mem_entry,
1223*0f4c859eSApple OSS Distributions 0, /* offset */
1224*0f4c859eSApple OSS Distributions FALSE, /* copy */
1225*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1226*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1227*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
1228*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_map()");
1229*0f4c859eSApple OSS Distributions remap = *(uint32_t *)(uintptr_t)remap_address;
1230*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1231*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before + 1;
1232*0f4c859eSApple OSS Distributions after = *(uint32_t *)(uintptr_t)address;
1233*0f4c859eSApple OSS Distributions T_LOG("mem_entry(VM_SHARE): 0x%llx 0x%x -> 0x%x", address, before, after);
1234*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before;
1235*0f4c859eSApple OSS Distributions if (before != after) {
1236*0f4c859eSApple OSS Distributions T_FAIL("mem_entry(VM_SHARE) bypassed copy-on-write");
1237*0f4c859eSApple OSS Distributions } else {
1238*0f4c859eSApple OSS Distributions T_PASS("mem_entry(VM_SHARE) did not bypass copy-on-write");
1239*0f4c859eSApple OSS Distributions }
1240*0f4c859eSApple OSS Distributions /* check that region is still nested */
1241*0f4c859eSApple OSS Distributions tmp_address = address;
1242*0f4c859eSApple OSS Distributions tmp_size = 0;
1243*0f4c859eSApple OSS Distributions depth = 99;
1244*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1245*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1246*0f4c859eSApple OSS Distributions &tmp_address,
1247*0f4c859eSApple OSS Distributions &tmp_size,
1248*0f4c859eSApple OSS Distributions &depth,
1249*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1250*0f4c859eSApple OSS Distributions &count);
1251*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1252*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1253*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1254*0f4c859eSApple OSS Distributions prot_str[info.protection],
1255*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1256*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1257*0f4c859eSApple OSS Distributions info.object_id);
1258*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1259*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1260*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1261*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "cur_prot still read-only");
1262*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "max_prot still read-only");
1263*0f4c859eSApple OSS Distributions /* check that new mapping is a copy */
1264*0f4c859eSApple OSS Distributions tmp_address = remap_address;
1265*0f4c859eSApple OSS Distributions tmp_size = 0;
1266*0f4c859eSApple OSS Distributions depth = 99;
1267*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1268*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1269*0f4c859eSApple OSS Distributions &tmp_address,
1270*0f4c859eSApple OSS Distributions &tmp_size,
1271*0f4c859eSApple OSS Distributions &depth,
1272*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1273*0f4c859eSApple OSS Distributions &count);
1274*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1275*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1276*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1277*0f4c859eSApple OSS Distributions prot_str[info.protection],
1278*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1279*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1280*0f4c859eSApple OSS Distributions info.object_id);
1281*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, remap_address, "address hasn't changed");
1282*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1283*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(depth, 0, "new mapping is unnested");
1284*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "new cur_prot read-only");
1285*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "new max_prot read-only");
1286*0f4c859eSApple OSS Distributions /* cleanup */
1287*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1288*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1289*0f4c859eSApple OSS Distributions T_PASS("mem_entry(VM_SHARE) read-only");
1290*0f4c859eSApple OSS Distributions skip_mem_entry_vm_share_ro:
1291*0f4c859eSApple OSS Distributions
1292*0f4c859eSApple OSS Distributions /* test mach_make_memory_entry_64() of RO */
1293*0f4c859eSApple OSS Distributions before = *(uint32_t *)(uintptr_t)address;
1294*0f4c859eSApple OSS Distributions remap_size = size;
1295*0f4c859eSApple OSS Distributions mem_entry = MACH_PORT_NULL;
1296*0f4c859eSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
1297*0f4c859eSApple OSS Distributions &remap_size,
1298*0f4c859eSApple OSS Distributions address,
1299*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1300*0f4c859eSApple OSS Distributions &mem_entry,
1301*0f4c859eSApple OSS Distributions MACH_PORT_NULL);
1302*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(kr, KERN_PROTECTION_FAILURE, "mach_make_memory_entry_64()");
1303*0f4c859eSApple OSS Distributions /* check that region is still nested */
1304*0f4c859eSApple OSS Distributions tmp_address = address;
1305*0f4c859eSApple OSS Distributions tmp_size = 0;
1306*0f4c859eSApple OSS Distributions depth = 99;
1307*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1308*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1309*0f4c859eSApple OSS Distributions &tmp_address,
1310*0f4c859eSApple OSS Distributions &tmp_size,
1311*0f4c859eSApple OSS Distributions &depth,
1312*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1313*0f4c859eSApple OSS Distributions &count);
1314*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1315*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1316*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1317*0f4c859eSApple OSS Distributions prot_str[info.protection],
1318*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1319*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1320*0f4c859eSApple OSS Distributions info.object_id);
1321*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1322*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1323*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1324*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "cur_prot still read-only");
1325*0f4c859eSApple OSS Distributions if (depth > 0) {
1326*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "max_prot still read-only");
1327*0f4c859eSApple OSS Distributions }
1328*0f4c859eSApple OSS Distributions T_PASS("mem_entry() read-only");
1329*0f4c859eSApple OSS Distributions
1330*0f4c859eSApple OSS Distributions
1331*0f4c859eSApple OSS Distributions /*
1332*0f4c859eSApple OSS Distributions * Step 2 - check that one can not share write access with a writable
1333*0f4c859eSApple OSS Distributions * mapping in the shared region.
1334*0f4c859eSApple OSS Distributions */
1335*0f4c859eSApple OSS Distributions size = 0;
1336*0f4c859eSApple OSS Distributions for (address = SHARED_REGION_BASE;
1337*0f4c859eSApple OSS Distributions address < SHARED_REGION_BASE + SHARED_REGION_SIZE;
1338*0f4c859eSApple OSS Distributions address += size) {
1339*0f4c859eSApple OSS Distributions size = 0;
1340*0f4c859eSApple OSS Distributions depth = 99;
1341*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1342*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1343*0f4c859eSApple OSS Distributions &address,
1344*0f4c859eSApple OSS Distributions &size,
1345*0f4c859eSApple OSS Distributions &depth,
1346*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1347*0f4c859eSApple OSS Distributions &count);
1348*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_region_recurse()");
1349*0f4c859eSApple OSS Distributions if (kr == KERN_INVALID_ADDRESS) {
1350*0f4c859eSApple OSS Distributions T_SKIP("could not find writable nested mapping");
1351*0f4c859eSApple OSS Distributions T_END;
1352*0f4c859eSApple OSS Distributions }
1353*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1354*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1355*0f4c859eSApple OSS Distributions address, address + size, depth,
1356*0f4c859eSApple OSS Distributions prot_str[info.protection],
1357*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1358*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1359*0f4c859eSApple OSS Distributions info.object_id);
1360*0f4c859eSApple OSS Distributions if (depth > 0 && (info.protection & VM_PROT_WRITE)) {
1361*0f4c859eSApple OSS Distributions /* nested and writable: bingo! */
1362*0f4c859eSApple OSS Distributions break;
1363*0f4c859eSApple OSS Distributions }
1364*0f4c859eSApple OSS Distributions }
1365*0f4c859eSApple OSS Distributions if (address >= SHARED_REGION_BASE + SHARED_REGION_SIZE) {
1366*0f4c859eSApple OSS Distributions T_SKIP("could not find writable nested mapping");
1367*0f4c859eSApple OSS Distributions T_END;
1368*0f4c859eSApple OSS Distributions }
1369*0f4c859eSApple OSS Distributions
1370*0f4c859eSApple OSS Distributions /* test vm_remap() of RW */
1371*0f4c859eSApple OSS Distributions before = *(uint32_t *)(uintptr_t)address;
1372*0f4c859eSApple OSS Distributions remap_address = 0;
1373*0f4c859eSApple OSS Distributions remap_size = size;
1374*0f4c859eSApple OSS Distributions kr = mach_vm_remap(mach_task_self(),
1375*0f4c859eSApple OSS Distributions &remap_address,
1376*0f4c859eSApple OSS Distributions remap_size,
1377*0f4c859eSApple OSS Distributions 0,
1378*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
1379*0f4c859eSApple OSS Distributions mach_task_self(),
1380*0f4c859eSApple OSS Distributions address,
1381*0f4c859eSApple OSS Distributions FALSE,
1382*0f4c859eSApple OSS Distributions &cur_prot,
1383*0f4c859eSApple OSS Distributions &max_prot,
1384*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
1385*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_remap()");
1386*0f4c859eSApple OSS Distributions if (!(cur_prot & VM_PROT_WRITE)) {
1387*0f4c859eSApple OSS Distributions T_LOG("vm_remap(): 0x%llx not writable %s/%s",
1388*0f4c859eSApple OSS Distributions remap_address, prot_str[cur_prot], prot_str[max_prot]);
1389*0f4c859eSApple OSS Distributions T_ASSERT_FAIL("vm_remap() remapping not writable");
1390*0f4c859eSApple OSS Distributions }
1391*0f4c859eSApple OSS Distributions remap = *(uint32_t *)(uintptr_t)remap_address;
1392*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1393*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before + 1;
1394*0f4c859eSApple OSS Distributions after = *(uint32_t *)(uintptr_t)address;
1395*0f4c859eSApple OSS Distributions T_LOG("vm_remap(): 0x%llx 0x%x -> 0x%x", address, before, after);
1396*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before;
1397*0f4c859eSApple OSS Distributions if (before != after) {
1398*0f4c859eSApple OSS Distributions T_FAIL("vm_remap() bypassed copy-on-write");
1399*0f4c859eSApple OSS Distributions } else {
1400*0f4c859eSApple OSS Distributions T_PASS("vm_remap() did not bypass copy-on-write");
1401*0f4c859eSApple OSS Distributions }
1402*0f4c859eSApple OSS Distributions /* check that region is still nested */
1403*0f4c859eSApple OSS Distributions tmp_address = address;
1404*0f4c859eSApple OSS Distributions tmp_size = 0;
1405*0f4c859eSApple OSS Distributions depth = 99;
1406*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1407*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1408*0f4c859eSApple OSS Distributions &tmp_address,
1409*0f4c859eSApple OSS Distributions &tmp_size,
1410*0f4c859eSApple OSS Distributions &depth,
1411*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1412*0f4c859eSApple OSS Distributions &count);
1413*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1414*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1415*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1416*0f4c859eSApple OSS Distributions prot_str[info.protection],
1417*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1418*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1419*0f4c859eSApple OSS Distributions info.object_id);
1420*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1421*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1422*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1423*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_DEFAULT, "cur_prot still writable");
1424*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ((info.max_protection & VM_PROT_WRITE), VM_PROT_WRITE, "max_prot still writable");
1425*0f4c859eSApple OSS Distributions /* cleanup */
1426*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1427*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1428*0f4c859eSApple OSS Distributions
1429*0f4c859eSApple OSS Distributions #if defined(VM_MEMORY_ROSETTA)
1430*0f4c859eSApple OSS Distributions if (dlsym(RTLD_DEFAULT, "mach_vm_remap_new") == NULL) {
1431*0f4c859eSApple OSS Distributions T_PASS("vm_remap_new() is not present");
1432*0f4c859eSApple OSS Distributions goto skip_vm_remap_new_rw;
1433*0f4c859eSApple OSS Distributions }
1434*0f4c859eSApple OSS Distributions /* test vm_remap_new() of RW */
1435*0f4c859eSApple OSS Distributions before = *(uint32_t *)(uintptr_t)address;
1436*0f4c859eSApple OSS Distributions remap_address = 0;
1437*0f4c859eSApple OSS Distributions remap_size = size;
1438*0f4c859eSApple OSS Distributions cur_prot = VM_PROT_READ | VM_PROT_WRITE;
1439*0f4c859eSApple OSS Distributions max_prot = VM_PROT_READ | VM_PROT_WRITE;
1440*0f4c859eSApple OSS Distributions kr = mach_vm_remap_new(mach_task_self(),
1441*0f4c859eSApple OSS Distributions &remap_address,
1442*0f4c859eSApple OSS Distributions remap_size,
1443*0f4c859eSApple OSS Distributions 0,
1444*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
1445*0f4c859eSApple OSS Distributions mach_task_self(),
1446*0f4c859eSApple OSS Distributions address,
1447*0f4c859eSApple OSS Distributions FALSE,
1448*0f4c859eSApple OSS Distributions &cur_prot,
1449*0f4c859eSApple OSS Distributions &max_prot,
1450*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
1451*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_remap_new()");
1452*0f4c859eSApple OSS Distributions if (kr == KERN_PROTECTION_FAILURE) {
1453*0f4c859eSApple OSS Distributions /* wrong but not a security issue... */
1454*0f4c859eSApple OSS Distributions goto skip_vm_remap_new_rw;
1455*0f4c859eSApple OSS Distributions }
1456*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_remap_new()");
1457*0f4c859eSApple OSS Distributions if (!(cur_prot & VM_PROT_WRITE)) {
1458*0f4c859eSApple OSS Distributions T_LOG("vm_remap_new(): 0x%llx not writable %s/%s",
1459*0f4c859eSApple OSS Distributions remap_address, prot_str[cur_prot], prot_str[max_prot]);
1460*0f4c859eSApple OSS Distributions T_ASSERT_FAIL("vm_remap_new() remapping not writable");
1461*0f4c859eSApple OSS Distributions }
1462*0f4c859eSApple OSS Distributions remap = *(uint32_t *)(uintptr_t)remap_address;
1463*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1464*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before + 1;
1465*0f4c859eSApple OSS Distributions after = *(uint32_t *)(uintptr_t)address;
1466*0f4c859eSApple OSS Distributions T_LOG("vm_remap_new(): 0x%llx 0x%x -> 0x%x", address, before, after);
1467*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before;
1468*0f4c859eSApple OSS Distributions if (before != after) {
1469*0f4c859eSApple OSS Distributions T_FAIL("vm_remap_new() bypassed copy-on-write");
1470*0f4c859eSApple OSS Distributions } else {
1471*0f4c859eSApple OSS Distributions T_PASS("vm_remap_new() did not bypass copy-on-write");
1472*0f4c859eSApple OSS Distributions }
1473*0f4c859eSApple OSS Distributions /* check that region is still nested */
1474*0f4c859eSApple OSS Distributions tmp_address = address;
1475*0f4c859eSApple OSS Distributions tmp_size = 0;
1476*0f4c859eSApple OSS Distributions depth = 99;
1477*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1478*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1479*0f4c859eSApple OSS Distributions &tmp_address,
1480*0f4c859eSApple OSS Distributions &tmp_size,
1481*0f4c859eSApple OSS Distributions &depth,
1482*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1483*0f4c859eSApple OSS Distributions &count);
1484*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1485*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1486*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1487*0f4c859eSApple OSS Distributions prot_str[info.protection],
1488*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1489*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1490*0f4c859eSApple OSS Distributions info.object_id);
1491*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1492*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1493*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1494*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_DEFAULT, "cur_prot still writable");
1495*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ((info.max_protection & VM_PROT_WRITE), VM_PROT_WRITE, "max_prot still writable");
1496*0f4c859eSApple OSS Distributions /* cleanup */
1497*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1498*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1499*0f4c859eSApple OSS Distributions skip_vm_remap_new_rw:
1500*0f4c859eSApple OSS Distributions #else /* defined(VM_MEMORY_ROSETTA) */
1501*0f4c859eSApple OSS Distributions /* pre-BigSur SDK: no vm_remap_new() */
1502*0f4c859eSApple OSS Distributions T_LOG("No vm_remap_new() to test");
1503*0f4c859eSApple OSS Distributions #endif /* defined(VM_MEMORY_ROSETTA) */
1504*0f4c859eSApple OSS Distributions
1505*0f4c859eSApple OSS Distributions /* test mach_make_memory_entry_64(VM_SHARE) of RW */
1506*0f4c859eSApple OSS Distributions before = *(uint32_t *)(uintptr_t)address;
1507*0f4c859eSApple OSS Distributions remap_size = size;
1508*0f4c859eSApple OSS Distributions mem_entry = MACH_PORT_NULL;
1509*0f4c859eSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
1510*0f4c859eSApple OSS Distributions &remap_size,
1511*0f4c859eSApple OSS Distributions address,
1512*0f4c859eSApple OSS Distributions MAP_MEM_VM_SHARE | VM_PROT_READ | VM_PROT_WRITE,
1513*0f4c859eSApple OSS Distributions &mem_entry,
1514*0f4c859eSApple OSS Distributions MACH_PORT_NULL);
1515*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "mach_make_memory_entry_64(VM_SHARE)");
1516*0f4c859eSApple OSS Distributions if (kr == KERN_PROTECTION_FAILURE) {
1517*0f4c859eSApple OSS Distributions /* wrong but not a security issue... */
1518*0f4c859eSApple OSS Distributions goto skip_mem_entry_vm_share_rw;
1519*0f4c859eSApple OSS Distributions }
1520*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_make_memory_entry_64(VM_SHARE)");
1521*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(remap_size, size, "mem_entry(VM_SHARE) should cover whole mapping");
1522*0f4c859eSApple OSS Distributions // T_LOG("AFTER MAKE_MEM_ENTRY(VM_SHARE) 0x%llx...", address); fflush(stdout); fflush(stderr); getchar();
1523*0f4c859eSApple OSS Distributions remap_address = 0;
1524*0f4c859eSApple OSS Distributions kr = mach_vm_map(mach_task_self(),
1525*0f4c859eSApple OSS Distributions &remap_address,
1526*0f4c859eSApple OSS Distributions remap_size,
1527*0f4c859eSApple OSS Distributions 0, /* mask */
1528*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
1529*0f4c859eSApple OSS Distributions mem_entry,
1530*0f4c859eSApple OSS Distributions 0, /* offset */
1531*0f4c859eSApple OSS Distributions FALSE, /* copy */
1532*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1533*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1534*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
1535*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_map()");
1536*0f4c859eSApple OSS Distributions remap = *(uint32_t *)(uintptr_t)remap_address;
1537*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1538*0f4c859eSApple OSS Distributions // T_LOG("AFTER VM_MAP 0x%llx...", remap_address); fflush(stdout); fflush(stderr); getchar();
1539*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before + 1;
1540*0f4c859eSApple OSS Distributions // T_LOG("AFTER WRITE 0x%llx...", remap_address); fflush(stdout); fflush(stderr); getchar();
1541*0f4c859eSApple OSS Distributions after = *(uint32_t *)(uintptr_t)address;
1542*0f4c859eSApple OSS Distributions T_LOG("mem_entry(VM_SHARE): 0x%llx 0x%x -> 0x%x", address, before, after);
1543*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before;
1544*0f4c859eSApple OSS Distributions if (before != after) {
1545*0f4c859eSApple OSS Distributions T_FAIL("mem_entry(VM_SHARE) bypassed copy-on-write");
1546*0f4c859eSApple OSS Distributions } else {
1547*0f4c859eSApple OSS Distributions T_PASS("mem_entry(VM_SHARE) did not bypass copy-on-write");
1548*0f4c859eSApple OSS Distributions }
1549*0f4c859eSApple OSS Distributions /* check that region is still nested */
1550*0f4c859eSApple OSS Distributions tmp_address = address;
1551*0f4c859eSApple OSS Distributions tmp_size = 0;
1552*0f4c859eSApple OSS Distributions depth = 99;
1553*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1554*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1555*0f4c859eSApple OSS Distributions &tmp_address,
1556*0f4c859eSApple OSS Distributions &tmp_size,
1557*0f4c859eSApple OSS Distributions &depth,
1558*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1559*0f4c859eSApple OSS Distributions &count);
1560*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1561*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1562*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1563*0f4c859eSApple OSS Distributions prot_str[info.protection],
1564*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1565*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1566*0f4c859eSApple OSS Distributions info.object_id);
1567*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1568*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1569*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1570*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_DEFAULT, "cur_prot still writable");
1571*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ((info.max_protection & VM_PROT_WRITE), VM_PROT_WRITE, "max_prot still writable");
1572*0f4c859eSApple OSS Distributions /* cleanup */
1573*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1574*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1575*0f4c859eSApple OSS Distributions mach_port_deallocate(mach_task_self(), mem_entry);
1576*0f4c859eSApple OSS Distributions skip_mem_entry_vm_share_rw:
1577*0f4c859eSApple OSS Distributions
1578*0f4c859eSApple OSS Distributions /* test mach_make_memory_entry_64() of RW */
1579*0f4c859eSApple OSS Distributions before = *(uint32_t *)(uintptr_t)address;
1580*0f4c859eSApple OSS Distributions remap_size = size;
1581*0f4c859eSApple OSS Distributions mem_entry = MACH_PORT_NULL;
1582*0f4c859eSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
1583*0f4c859eSApple OSS Distributions &remap_size,
1584*0f4c859eSApple OSS Distributions address,
1585*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1586*0f4c859eSApple OSS Distributions &mem_entry,
1587*0f4c859eSApple OSS Distributions MACH_PORT_NULL);
1588*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_make_memory_entry_64()");
1589*0f4c859eSApple OSS Distributions remap_address = 0;
1590*0f4c859eSApple OSS Distributions kr = mach_vm_map(mach_task_self(),
1591*0f4c859eSApple OSS Distributions &remap_address,
1592*0f4c859eSApple OSS Distributions remap_size,
1593*0f4c859eSApple OSS Distributions 0, /* mask */
1594*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
1595*0f4c859eSApple OSS Distributions mem_entry,
1596*0f4c859eSApple OSS Distributions 0, /* offset */
1597*0f4c859eSApple OSS Distributions FALSE, /* copy */
1598*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1599*0f4c859eSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1600*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
1601*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_map()");
1602*0f4c859eSApple OSS Distributions remap = *(uint32_t *)(uintptr_t)remap_address;
1603*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1604*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before + 1;
1605*0f4c859eSApple OSS Distributions after = *(uint32_t *)(uintptr_t)address;
1606*0f4c859eSApple OSS Distributions T_LOG("mem_entry(): 0x%llx 0x%x -> 0x%x", address, before, after);
1607*0f4c859eSApple OSS Distributions *(uint32_t *)(uintptr_t)remap_address = before;
1608*0f4c859eSApple OSS Distributions /* check that region is no longer nested */
1609*0f4c859eSApple OSS Distributions tmp_address = address;
1610*0f4c859eSApple OSS Distributions tmp_size = 0;
1611*0f4c859eSApple OSS Distributions depth = 99;
1612*0f4c859eSApple OSS Distributions count = VM_REGION_SUBMAP_INFO_COUNT_64;
1613*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1614*0f4c859eSApple OSS Distributions &tmp_address,
1615*0f4c859eSApple OSS Distributions &tmp_size,
1616*0f4c859eSApple OSS Distributions &depth,
1617*0f4c859eSApple OSS Distributions (vm_region_recurse_info_t)&info,
1618*0f4c859eSApple OSS Distributions &count);
1619*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1620*0f4c859eSApple OSS Distributions T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1621*0f4c859eSApple OSS Distributions tmp_address, tmp_address + tmp_size, depth,
1622*0f4c859eSApple OSS Distributions prot_str[info.protection],
1623*0f4c859eSApple OSS Distributions prot_str[info.max_protection],
1624*0f4c859eSApple OSS Distributions share_mode_str[info.share_mode],
1625*0f4c859eSApple OSS Distributions info.object_id);
1626*0f4c859eSApple OSS Distributions if (before != after) {
1627*0f4c859eSApple OSS Distributions if (depth == 0) {
1628*0f4c859eSApple OSS Distributions T_PASS("mem_entry() honored copy-on-write");
1629*0f4c859eSApple OSS Distributions } else {
1630*0f4c859eSApple OSS Distributions T_FAIL("mem_entry() did not trigger copy-on_write");
1631*0f4c859eSApple OSS Distributions }
1632*0f4c859eSApple OSS Distributions } else {
1633*0f4c859eSApple OSS Distributions T_FAIL("mem_entry() did not honor copy-on-write");
1634*0f4c859eSApple OSS Distributions }
1635*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1636*0f4c859eSApple OSS Distributions // T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1637*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(depth, 0, "no longer nested");
1638*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_DEFAULT, "cur_prot still writable");
1639*0f4c859eSApple OSS Distributions T_QUIET; T_ASSERT_EQ((info.max_protection & VM_PROT_WRITE), VM_PROT_WRITE, "max_prot still writable");
1640*0f4c859eSApple OSS Distributions /* cleanup */
1641*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1642*0f4c859eSApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1643*0f4c859eSApple OSS Distributions mach_port_deallocate(mach_task_self(), mem_entry);
1644*0f4c859eSApple OSS Distributions }
1645*0f4c859eSApple OSS Distributions
1646*0f4c859eSApple OSS Distributions T_DECL(copyoverwrite_submap_protection, "test copywrite vm region submap \
1647*0f4c859eSApple OSS Distributions protection", T_META_ALL_VALID_ARCHS(true))
1648*0f4c859eSApple OSS Distributions {
1649*0f4c859eSApple OSS Distributions kern_return_t kr;
1650*0f4c859eSApple OSS Distributions mach_vm_address_t vmaddr;
1651*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize;
1652*0f4c859eSApple OSS Distributions natural_t depth;
1653*0f4c859eSApple OSS Distributions vm_region_submap_short_info_data_64_t region_info;
1654*0f4c859eSApple OSS Distributions mach_msg_type_number_t region_info_count;
1655*0f4c859eSApple OSS Distributions
1656*0f4c859eSApple OSS Distributions for (vmaddr = SHARED_REGION_BASE;
1657*0f4c859eSApple OSS Distributions vmaddr < SHARED_REGION_BASE + SHARED_REGION_SIZE;
1658*0f4c859eSApple OSS Distributions vmaddr += vmsize) {
1659*0f4c859eSApple OSS Distributions depth = 99;
1660*0f4c859eSApple OSS Distributions region_info_count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
1661*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1662*0f4c859eSApple OSS Distributions &vmaddr,
1663*0f4c859eSApple OSS Distributions &vmsize,
1664*0f4c859eSApple OSS Distributions &depth,
1665*0f4c859eSApple OSS Distributions (vm_region_info_t) ®ion_info,
1666*0f4c859eSApple OSS Distributions ®ion_info_count);
1667*0f4c859eSApple OSS Distributions if (kr == KERN_INVALID_ADDRESS) {
1668*0f4c859eSApple OSS Distributions break;
1669*0f4c859eSApple OSS Distributions }
1670*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse(0x%llx)", vmaddr);
1671*0f4c859eSApple OSS Distributions T_ASSERT_EQ(region_info_count,
1672*0f4c859eSApple OSS Distributions VM_REGION_SUBMAP_SHORT_INFO_COUNT_64,
1673*0f4c859eSApple OSS Distributions "vm_region_recurse(0x%llx) count = %d expected %d",
1674*0f4c859eSApple OSS Distributions vmaddr, region_info_count,
1675*0f4c859eSApple OSS Distributions VM_REGION_SUBMAP_SHORT_INFO_COUNT_64);
1676*0f4c859eSApple OSS Distributions
1677*0f4c859eSApple OSS Distributions T_LOG("--> region: vmaddr 0x%llx depth %d prot 0x%x/0x%x",
1678*0f4c859eSApple OSS Distributions vmaddr, depth, region_info.protection,
1679*0f4c859eSApple OSS Distributions region_info.max_protection);
1680*0f4c859eSApple OSS Distributions if (depth == 0) {
1681*0f4c859eSApple OSS Distributions /* not a submap mapping: next mapping */
1682*0f4c859eSApple OSS Distributions continue;
1683*0f4c859eSApple OSS Distributions }
1684*0f4c859eSApple OSS Distributions if (vmaddr >= SHARED_REGION_BASE + SHARED_REGION_SIZE) {
1685*0f4c859eSApple OSS Distributions break;
1686*0f4c859eSApple OSS Distributions }
1687*0f4c859eSApple OSS Distributions kr = mach_vm_copy(mach_task_self(),
1688*0f4c859eSApple OSS Distributions vmaddr,
1689*0f4c859eSApple OSS Distributions vmsize,
1690*0f4c859eSApple OSS Distributions vmaddr);
1691*0f4c859eSApple OSS Distributions if (kr == KERN_PROTECTION_FAILURE ||
1692*0f4c859eSApple OSS Distributions kr == KERN_INVALID_ADDRESS) {
1693*0f4c859eSApple OSS Distributions T_PASS("vm_copy(0x%llx,0x%llx) expected prot error 0x%x (%s)",
1694*0f4c859eSApple OSS Distributions vmaddr, vmsize, kr, mach_error_string(kr));
1695*0f4c859eSApple OSS Distributions continue;
1696*0f4c859eSApple OSS Distributions }
1697*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_copy(0x%llx,0x%llx) prot 0x%x",
1698*0f4c859eSApple OSS Distributions vmaddr, vmsize, region_info.protection);
1699*0f4c859eSApple OSS Distributions depth = 0;
1700*0f4c859eSApple OSS Distributions region_info_count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
1701*0f4c859eSApple OSS Distributions kr = mach_vm_region_recurse(mach_task_self(),
1702*0f4c859eSApple OSS Distributions &vmaddr,
1703*0f4c859eSApple OSS Distributions &vmsize,
1704*0f4c859eSApple OSS Distributions &depth,
1705*0f4c859eSApple OSS Distributions (vm_region_info_t) ®ion_info,
1706*0f4c859eSApple OSS Distributions ®ion_info_count);
1707*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "m_region_recurse(0x%llx)", vmaddr);
1708*0f4c859eSApple OSS Distributions T_ASSERT_EQ(region_info_count,
1709*0f4c859eSApple OSS Distributions VM_REGION_SUBMAP_SHORT_INFO_COUNT_64,
1710*0f4c859eSApple OSS Distributions "vm_region_recurse() count = %d expected %d",
1711*0f4c859eSApple OSS Distributions region_info_count, VM_REGION_SUBMAP_SHORT_INFO_COUNT_64);
1712*0f4c859eSApple OSS Distributions
1713*0f4c859eSApple OSS Distributions T_ASSERT_EQ(depth, 0, "vm_region_recurse(0x%llx): depth = %d expected 0",
1714*0f4c859eSApple OSS Distributions vmaddr, depth);
1715*0f4c859eSApple OSS Distributions T_ASSERT_EQ((region_info.protection & VM_PROT_EXECUTE),
1716*0f4c859eSApple OSS Distributions 0, "vm_region_recurse(0x%llx): prot 0x%x",
1717*0f4c859eSApple OSS Distributions vmaddr, region_info.protection);
1718*0f4c859eSApple OSS Distributions }
1719*0f4c859eSApple OSS Distributions }
1720*0f4c859eSApple OSS Distributions
1721*0f4c859eSApple OSS Distributions T_DECL(wire_text, "test wired text for rdar://problem/16783546 Wiring code in \
1722*0f4c859eSApple OSS Distributions the shared region triggers code-signing violations",
1723*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
1724*0f4c859eSApple OSS Distributions {
1725*0f4c859eSApple OSS Distributions uint32_t *addr, before, after;
1726*0f4c859eSApple OSS Distributions int retval;
1727*0f4c859eSApple OSS Distributions int saved_errno;
1728*0f4c859eSApple OSS Distributions kern_return_t kr;
1729*0f4c859eSApple OSS Distributions vm_address_t map_addr, remap_addr;
1730*0f4c859eSApple OSS Distributions vm_prot_t curprot, maxprot;
1731*0f4c859eSApple OSS Distributions
1732*0f4c859eSApple OSS Distributions addr = (uint32_t *)&printf;
1733*0f4c859eSApple OSS Distributions #if __has_feature(ptrauth_calls)
1734*0f4c859eSApple OSS Distributions map_addr = (vm_address_t)(uintptr_t)ptrauth_strip(addr, ptrauth_key_function_pointer);
1735*0f4c859eSApple OSS Distributions #else /* __has_feature(ptrauth_calls) */
1736*0f4c859eSApple OSS Distributions map_addr = (vm_address_t)(uintptr_t)addr;
1737*0f4c859eSApple OSS Distributions #endif /* __has_feature(ptrauth_calls) */
1738*0f4c859eSApple OSS Distributions remap_addr = 0;
1739*0f4c859eSApple OSS Distributions kr = vm_remap(mach_task_self(), &remap_addr, 4096,
1740*0f4c859eSApple OSS Distributions 0, /* mask */
1741*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
1742*0f4c859eSApple OSS Distributions mach_task_self(), map_addr,
1743*0f4c859eSApple OSS Distributions FALSE, /* copy */
1744*0f4c859eSApple OSS Distributions &curprot, &maxprot,
1745*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
1746*0f4c859eSApple OSS Distributions T_ASSERT_EQ(kr, KERN_SUCCESS, "vm_remap error 0x%x (%s)",
1747*0f4c859eSApple OSS Distributions kr, mach_error_string(kr));
1748*0f4c859eSApple OSS Distributions before = *addr;
1749*0f4c859eSApple OSS Distributions retval = mlock(addr, 4096);
1750*0f4c859eSApple OSS Distributions after = *addr;
1751*0f4c859eSApple OSS Distributions if (retval != 0) {
1752*0f4c859eSApple OSS Distributions saved_errno = errno;
1753*0f4c859eSApple OSS Distributions T_ASSERT_EQ(saved_errno, EACCES, "wire shared text error %d (%s), expected: %d",
1754*0f4c859eSApple OSS Distributions saved_errno, strerror(saved_errno), EACCES);
1755*0f4c859eSApple OSS Distributions } else if (after != before) {
1756*0f4c859eSApple OSS Distributions T_ASSERT_FAIL("shared text changed by wiring at %p 0x%x -> 0x%x", addr, before, after);
1757*0f4c859eSApple OSS Distributions } else {
1758*0f4c859eSApple OSS Distributions T_PASS("wire shared text");
1759*0f4c859eSApple OSS Distributions }
1760*0f4c859eSApple OSS Distributions
1761*0f4c859eSApple OSS Distributions addr = (uint32_t *) &fprintf;
1762*0f4c859eSApple OSS Distributions before = *addr;
1763*0f4c859eSApple OSS Distributions retval = mlock(addr, 4096);
1764*0f4c859eSApple OSS Distributions after = *addr;
1765*0f4c859eSApple OSS Distributions if (retval != 0) {
1766*0f4c859eSApple OSS Distributions saved_errno = errno;
1767*0f4c859eSApple OSS Distributions T_ASSERT_EQ(saved_errno, EACCES, "wire shared text error %d (%s), expected: %d",
1768*0f4c859eSApple OSS Distributions saved_errno, strerror(saved_errno), EACCES);
1769*0f4c859eSApple OSS Distributions } else if (after != before) {
1770*0f4c859eSApple OSS Distributions T_ASSERT_FAIL("shared text changed by wiring at %p 0x%x -> 0x%x", addr, before, after);
1771*0f4c859eSApple OSS Distributions } else {
1772*0f4c859eSApple OSS Distributions T_PASS("wire shared text");
1773*0f4c859eSApple OSS Distributions }
1774*0f4c859eSApple OSS Distributions
1775*0f4c859eSApple OSS Distributions addr = (uint32_t *) &testmain_wire_text;
1776*0f4c859eSApple OSS Distributions before = *addr;
1777*0f4c859eSApple OSS Distributions retval = mlock(addr, 4096);
1778*0f4c859eSApple OSS Distributions after = *addr;
1779*0f4c859eSApple OSS Distributions if (retval != 0) {
1780*0f4c859eSApple OSS Distributions saved_errno = errno;
1781*0f4c859eSApple OSS Distributions T_ASSERT_EQ(saved_errno, EACCES, "wire text error return error %d (%s)",
1782*0f4c859eSApple OSS Distributions saved_errno, strerror(saved_errno));
1783*0f4c859eSApple OSS Distributions } else if (after != before) {
1784*0f4c859eSApple OSS Distributions T_ASSERT_FAIL("text changed by wiring at %p 0x%x -> 0x%x", addr, before, after);
1785*0f4c859eSApple OSS Distributions } else {
1786*0f4c859eSApple OSS Distributions T_PASS("wire text");
1787*0f4c859eSApple OSS Distributions }
1788*0f4c859eSApple OSS Distributions }
1789*0f4c859eSApple OSS Distributions
1790*0f4c859eSApple OSS Distributions T_DECL(remap_comm_page, "test remapping of the commpage - rdar://93177124",
1791*0f4c859eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true))
1792*0f4c859eSApple OSS Distributions {
1793*0f4c859eSApple OSS Distributions kern_return_t kr;
1794*0f4c859eSApple OSS Distributions mach_vm_address_t commpage_addr, remap_addr;
1795*0f4c859eSApple OSS Distributions mach_vm_size_t vmsize;
1796*0f4c859eSApple OSS Distributions vm_prot_t curprot, maxprot;
1797*0f4c859eSApple OSS Distributions
1798*0f4c859eSApple OSS Distributions #if __arm__
1799*0f4c859eSApple OSS Distributions commpage_addr = 0xFFFF4000ULL;
1800*0f4c859eSApple OSS Distributions #elif __arm64__
1801*0f4c859eSApple OSS Distributions commpage_addr = 0x0000000FFFFFC000ULL;
1802*0f4c859eSApple OSS Distributions #elif __x86_64__
1803*0f4c859eSApple OSS Distributions commpage_addr = 0x00007FFFFFE00000ULL;
1804*0f4c859eSApple OSS Distributions #else
1805*0f4c859eSApple OSS Distributions T_FAIL("unknown commpage address for this architecture");
1806*0f4c859eSApple OSS Distributions #endif
1807*0f4c859eSApple OSS Distributions
1808*0f4c859eSApple OSS Distributions T_LOG("Remapping commpage from 0x%llx", commpage_addr);
1809*0f4c859eSApple OSS Distributions vmsize = vm_kernel_page_size;
1810*0f4c859eSApple OSS Distributions remap_addr = 0;
1811*0f4c859eSApple OSS Distributions kr = mach_vm_remap(mach_task_self(),
1812*0f4c859eSApple OSS Distributions &remap_addr,
1813*0f4c859eSApple OSS Distributions vmsize,
1814*0f4c859eSApple OSS Distributions 0, /* mask */
1815*0f4c859eSApple OSS Distributions VM_FLAGS_ANYWHERE,
1816*0f4c859eSApple OSS Distributions mach_task_self(),
1817*0f4c859eSApple OSS Distributions commpage_addr,
1818*0f4c859eSApple OSS Distributions TRUE, /* copy */
1819*0f4c859eSApple OSS Distributions &curprot,
1820*0f4c859eSApple OSS Distributions &maxprot,
1821*0f4c859eSApple OSS Distributions VM_INHERIT_DEFAULT);
1822*0f4c859eSApple OSS Distributions if (kr == KERN_INVALID_ADDRESS) {
1823*0f4c859eSApple OSS Distributions T_SKIP("No mapping found at 0x%llx\n", commpage_addr);
1824*0f4c859eSApple OSS Distributions return;
1825*0f4c859eSApple OSS Distributions }
1826*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_remap() of commpage from 0x%llx", commpage_addr);
1827*0f4c859eSApple OSS Distributions }
1828