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