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