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