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