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