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