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