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