1 /*
2 * Copyright (c) 2024 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /*
30 * vm/configurator_test.c
31 *
32 * Test vm_configurator itself.
33 *
34 * Verify that the VM states generated by vm_configurator are correct.
35 * This is intended to catch bugs in vm_configurator's
36 * template and checker system, as well as bugs in individual
37 * configurations used by other tests.
38 */
39
40 #include "configurator/vm_configurator_tests.h"
41
42 T_GLOBAL_META(
43 T_META_NAMESPACE("xnu.vm.configurator"),
44 T_META_RADAR_COMPONENT_NAME("xnu"),
45 T_META_RADAR_COMPONENT_VERSION("VM"),
46 T_META_RUN_CONCURRENTLY(true),
47 T_META_ASROOT(true), /* required for vm submap sysctls */
48 T_META_ALL_VALID_ARCHS(true)
49 );
50
51
52 /*
53 * Return true if [start, start + size) is a VM entry at the given submap depth.
54 */
55 __attribute__((overloadable))
56 static bool
is_entry(mach_vm_address_t start,mach_vm_size_t size,uint32_t submap_depth)57 is_entry(mach_vm_address_t start, mach_vm_size_t size, uint32_t submap_depth)
58 {
59 mach_vm_address_t entry_start = start;
60 mach_vm_size_t entry_size;
61 vm_region_submap_info_data_64_t info;
62
63 if (!get_info_for_address(&entry_start, &entry_size, &info, submap_depth)) {
64 return false; /* not mapped */
65 }
66 if (entry_start != start || entry_size != size) {
67 return false; /* mapped, but wrong extent */
68 }
69
70 return true;
71 }
72
73 /*
74 * Return true if [start, start + size) is a VM entry at submap depth 0.
75 */
76 __attribute__((overloadable, used))
77 static bool
is_entry(mach_vm_address_t start,mach_vm_size_t size)78 is_entry(mach_vm_address_t start, mach_vm_size_t size)
79 {
80 return is_entry(start, size, 0);
81 }
82
83 /*
84 * Return true if [start, start + size) is an unallocated hole
85 * at the given submap depth.
86 */
87 __attribute__((overloadable))
88 static bool
is_hole(mach_vm_address_t start,mach_vm_size_t size,uint32_t submap_depth)89 is_hole(mach_vm_address_t start, mach_vm_size_t size, uint32_t submap_depth)
90 {
91 mach_vm_address_t entry_start = start;
92 mach_vm_size_t entry_size;
93 vm_region_submap_info_data_64_t info;
94
95 if (get_info_for_address(&entry_start, &entry_size, &info, submap_depth)) {
96 /* start address was mapped */
97 return false;
98 } else if (entry_start < start + size) {
99 /* some address before the end of the expected hole was mapped */
100 return false;
101 }
102
103 /* [start, start + size) was entirely unmapped */
104 return true;
105 }
106
107 /*
108 * Return true if [start, start + size) is an unallocated hole at submap depth 0.
109 * Unallocate space inside a submap does not count.
110 */
111 __attribute__((overloadable, used))
112 static bool
is_hole(mach_vm_address_t start,mach_vm_size_t size)113 is_hole(mach_vm_address_t start, mach_vm_size_t size)
114 {
115 return is_hole(start, size, 0 /* submap_depth */);
116 }
117
118 /*
119 * Verify the memory and the checker for an expected hole.
120 */
121 static void
assert_hole_checker_and_entry(vm_entry_checker_t * checker,mach_vm_address_t start,mach_vm_size_t size)122 assert_hole_checker_and_entry(
123 vm_entry_checker_t *checker,
124 mach_vm_address_t start,
125 mach_vm_size_t size)
126 {
127 assert(start % PAGE_SIZE == 0);
128 assert(size % PAGE_SIZE == 0);
129 assert(checker->kind == Hole);
130 assert(checker->address == start);
131 assert(checker->size == size);
132
133 assert(is_hole(start, size, checker->submap_depth));
134 }
135
136 /*
137 * Verify the checker for an expected allocated entry.
138 * Does not verify the actual VM state.
139 */
140 static void
assert_allocation_checker(vm_entry_checker_t * checker,mach_vm_address_t start,mach_vm_size_t size)141 assert_allocation_checker(
142 vm_entry_checker_t *checker,
143 mach_vm_address_t start,
144 mach_vm_size_t size)
145 {
146 assert(start % PAGE_SIZE == 0);
147 assert(size % PAGE_SIZE == 0);
148 assert(checker->kind == Allocation);
149 assert(checker->address == start);
150 assert(checker->size == size);
151 }
152
153 /*
154 * Verify the actual VM state for an expected allocated entry.
155 * Does not verify the matching checker.
156 * Returns the vm_region output for the memory.
157 */
158 static void
assert_allocation_entry(mach_vm_address_t start,mach_vm_size_t size,uint32_t submap_depth,vm_region_submap_info_data_64_t * const out_info)159 assert_allocation_entry(
160 mach_vm_address_t start,
161 mach_vm_size_t size,
162 uint32_t submap_depth,
163 vm_region_submap_info_data_64_t * const out_info)
164 {
165 mach_vm_address_t entry_start = start;
166 mach_vm_size_t entry_size;
167 assert(get_info_for_address(&entry_start, &entry_size, out_info, submap_depth));
168 assert(entry_start == start);
169 assert(entry_size == size);
170 }
171
172 /*
173 * Verify the memory and the checker for an expected allocated entry.
174 * Returns the vm_region output for the memory.
175 */
176 static void
assert_allocation_checker_and_entry(vm_entry_checker_t * checker,mach_vm_address_t start,mach_vm_size_t size,vm_region_submap_info_data_64_t * const out_info)177 assert_allocation_checker_and_entry(
178 vm_entry_checker_t *checker,
179 mach_vm_address_t start,
180 mach_vm_size_t size,
181 vm_region_submap_info_data_64_t * const out_info)
182 {
183 assert_allocation_checker(checker, start, size);
184 assert_allocation_entry(start, size, checker->submap_depth, out_info);
185 }
186
187
188 /*
189 * Verify that checker_list consists of a pattern of entries and holes
190 * Each allocation or hole is assumed to be DEFAULT_ENTRY_SIZE in length.
191 * "##.#..#": allocation, allocation, hole, allocation, hole, hole, allocation
192 */
193 static void
assert_allocation_and_hole_pattern(checker_list_t * checker_list,const char * pattern)194 assert_allocation_and_hole_pattern(
195 checker_list_t *checker_list,
196 const char *pattern)
197 {
198 mach_vm_address_t base = checker_range_start_address(checker_list->entries);
199 assert(checker_range_count(checker_list->entries) == strlen(pattern));
200
201 for (size_t i = 0; i < strlen(pattern); i++) {
202 vm_region_submap_info_data_64_t info;
203 mach_vm_address_t entry_address = base + i * DEFAULT_ENTRY_SIZE;
204 vm_entry_checker_t *checker = checker_list_nth(checker_list, i);
205 switch (pattern[i]) {
206 case '#':
207 assert_allocation_checker_and_entry(checker,
208 entry_address, DEFAULT_ENTRY_SIZE, &info);
209 break;
210 case '.':
211 assert_hole_checker_and_entry(checker,
212 entry_address, DEFAULT_ENTRY_SIZE);
213 break;
214 default:
215 T_ASSERT_FAIL("pattern character '%c' is neither '#' nor '.'", pattern[i]);
216 break;
217 }
218 }
219 }
220
221 static void
assert_checker_and_entry_protection_equals(vm_entry_checker_t * checker,vm_region_submap_info_data_64_t * info,int protection,int max_protection)222 assert_checker_and_entry_protection_equals(
223 vm_entry_checker_t *checker,
224 vm_region_submap_info_data_64_t *info,
225 int protection,
226 int max_protection)
227 {
228 assert(checker->protection == protection);
229 assert(checker->max_protection == max_protection);
230 assert(info->protection == protection);
231 assert(info->max_protection == max_protection);
232 }
233
234 /*
235 * Verify the memory and the checker for an expected permanent entry.
236 * This is destructive because it attempts to deallocate the permanent entry
237 * which makes its memory inaccessible, and updates the checker to match.
238 */
239 static void
destructively_assert_permanent_checker_and_entry(vm_entry_checker_t * checker,mach_vm_address_t start,mach_vm_size_t size)240 destructively_assert_permanent_checker_and_entry(
241 vm_entry_checker_t *checker,
242 mach_vm_address_t start,
243 mach_vm_size_t size)
244 {
245 assert(start % PAGE_SIZE == 0);
246 assert(size % PAGE_SIZE == 0);
247 assert(checker->permanent == true);
248 assert(checker->address == start);
249 assert(checker->size == size);
250
251 /*
252 * Permanent memory is indistinguishable in vm_region output.
253 * We can only try to deallocate it and then see if it is still there.
254 */
255
256 /* check that it exists */
257 assert(is_entry(start, size, checker->submap_depth));
258
259 /* try to deallocate it */
260 kern_return_t kr = mach_vm_deallocate(mach_task_self(), start, size);
261 assert(kr == 0);
262
263 /* check that it still exists */
264 assert(is_entry(start, size, checker->submap_depth));
265
266 /* update the checker because the memory is now inaccessible */
267 checker->protection = VM_PROT_NONE;
268 checker->max_protection = VM_PROT_NONE;
269 }
270
271 /*
272 * Verify the memory and checker for an expected non-permanent allocation.
273 * This is destructive because it deallocates the memory
274 * and updates the checker to match.
275 */
276 static void
destructively_assert_nonpermanent_checker_and_entry(checker_list_t * list,vm_entry_checker_t * checker,mach_vm_address_t start,mach_vm_size_t size)277 destructively_assert_nonpermanent_checker_and_entry(
278 checker_list_t *list,
279 vm_entry_checker_t *checker,
280 mach_vm_address_t start,
281 mach_vm_size_t size)
282 {
283 assert(start % PAGE_SIZE == 0);
284 assert(size % PAGE_SIZE == 0);
285 assert(checker->permanent == false);
286 assert(checker->address == start);
287 assert(checker->size == size);
288
289 /*
290 * Permanent memory is indistinguishable in vm_region output.
291 * We can only try to deallocate it and then see if it is still there.
292 */
293
294 /* check that it exists */
295 assert(is_entry(start, size, checker->submap_depth));
296
297 /* try to deallocate it */
298 kern_return_t kr = mach_vm_deallocate(mach_task_self(), start, size);
299 assert(kr == 0);
300
301 /* check that it no longer exists */
302 assert(!is_entry(start, size, checker->submap_depth));
303 assert(is_hole(start, size, 0 /* submap_depth */));
304
305 /*
306 * Update the checker to match the now-deallocated memory.
307 * The checker should be replaced by a hole checker.
308 *
309 * Save the checker's index first so we can
310 * look up and verify the hole checker after.
311 */
312 unsigned index = 0;
313 while (checker_list_nth(list, index) != checker) {
314 index++;
315 }
316
317 checker_list_free_checker(list, checker);
318 vm_entry_checker_t *new_hole = checker_list_nth(list, index);
319 assert_hole_checker_and_entry(new_hole, start, size);
320 }
321
322 /*
323 * Verify the memory and the checker for an expected submap entry.
324 * Does not examine the contents of the submap.
325 * Returns the vm_region output for the entry in the parent map.
326 */
327 static void
assert_submap_checker_and_entry(vm_entry_checker_t * checker,mach_vm_address_t start,mach_vm_size_t size,vm_region_submap_info_data_64_t * const out_info)328 assert_submap_checker_and_entry(
329 vm_entry_checker_t *checker,
330 mach_vm_address_t start,
331 mach_vm_size_t size,
332 vm_region_submap_info_data_64_t * const out_info)
333 {
334 assert(start % PAGE_SIZE == 0);
335 assert(size % PAGE_SIZE == 0);
336 assert(checker->kind == Submap);
337 assert(checker->address == start);
338 assert(checker->size == size);
339 assert(checker->submap_depth == 0); /* nested submaps not allowed */
340
341 mach_vm_address_t entry_start = start;
342 mach_vm_size_t entry_size;
343 assert(get_info_for_address(&entry_start, &entry_size, out_info, checker->submap_depth));
344 assert(entry_start == start);
345 assert(entry_size == size);
346 }
347
348
349 static test_result_t
test_single_entry_1(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)350 test_single_entry_1(
351 checker_list_t *checker_list,
352 mach_vm_address_t start,
353 mach_vm_size_t size)
354 {
355 /* test range is a single allocation */
356 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
357 vm_region_submap_info_data_64_t info;
358 assert_allocation_checker_and_entry(checker, start, size, &info);
359
360 return TestSucceeded;
361 }
362
363 static test_result_t
test_single_entry_2(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)364 test_single_entry_2(
365 checker_list_t *checker_list,
366 mach_vm_address_t start,
367 mach_vm_size_t size)
368 {
369 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
370 vm_region_submap_info_data_64_t info;
371
372 /* test range excludes the end of the allocation */
373 assert(size == DEFAULT_ENTRY_SIZE - DEFAULT_PARTIAL_ENTRY_SIZE);
374 assert_allocation_checker_and_entry(checker,
375 start, DEFAULT_ENTRY_SIZE, &info);
376
377 return TestSucceeded;
378 }
379
380 static test_result_t
test_single_entry_3(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)381 test_single_entry_3(
382 checker_list_t *checker_list,
383 mach_vm_address_t start,
384 mach_vm_size_t size)
385 {
386 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
387 vm_region_submap_info_data_64_t info;
388
389 /* test range excludes the start of the allocation */
390 assert(size == DEFAULT_ENTRY_SIZE - DEFAULT_PARTIAL_ENTRY_SIZE);
391 assert_allocation_checker_and_entry(checker,
392 start - DEFAULT_PARTIAL_ENTRY_SIZE, DEFAULT_ENTRY_SIZE, &info);
393
394 return TestSucceeded;
395 }
396
397 static test_result_t
test_single_entry_4(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)398 test_single_entry_4(
399 checker_list_t *checker_list,
400 mach_vm_address_t start,
401 mach_vm_size_t size)
402 {
403 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
404 vm_region_submap_info_data_64_t info;
405
406 /* test range excludes the start and end of the allocation */
407 assert(size == DEFAULT_ENTRY_SIZE - DEFAULT_PARTIAL_ENTRY_SIZE);
408 assert_allocation_checker_and_entry(checker,
409 start - DEFAULT_PARTIAL_ENTRY_SIZE / 2, DEFAULT_ENTRY_SIZE, &info);
410
411 return TestSucceeded;
412 }
413
414
415 static test_result_t
test_multiple_entries_1(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)416 test_multiple_entries_1(
417 checker_list_t *checker_list,
418 mach_vm_address_t start,
419 mach_vm_size_t size)
420 {
421 assert_allocation_and_hole_pattern(checker_list, "##");
422 assert(start == checker_range_start_address(checker_list->entries));
423 assert(size == DEFAULT_ENTRY_SIZE * 2);
424 return TestSucceeded;
425 }
426
427 static test_result_t
test_multiple_entries_2(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)428 test_multiple_entries_2(
429 checker_list_t *checker_list,
430 mach_vm_address_t start,
431 mach_vm_size_t size)
432 {
433 assert_allocation_and_hole_pattern(checker_list, "###");
434 assert(start == checker_range_start_address(checker_list->entries));
435 assert(size == DEFAULT_ENTRY_SIZE * 3);
436 return TestSucceeded;
437 }
438
439 static test_result_t
test_multiple_entries_3(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)440 test_multiple_entries_3(
441 checker_list_t *checker_list,
442 mach_vm_address_t start,
443 mach_vm_size_t size)
444 {
445 assert_allocation_and_hole_pattern(checker_list,
446 "############"
447 "############"
448 "############"
449 "############");
450 assert(start == checker_range_start_address(checker_list->entries));
451 assert(size == DEFAULT_ENTRY_SIZE * 4 * 12);
452 return TestSucceeded;
453 }
454
455 static test_result_t
test_multiple_entries_4(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)456 test_multiple_entries_4(
457 checker_list_t *checker_list,
458 mach_vm_address_t start,
459 mach_vm_size_t size)
460 {
461 assert_allocation_and_hole_pattern(checker_list, "###");
462 assert(start == checker_range_start_address(checker_list->entries));
463 assert(size == DEFAULT_ENTRY_SIZE * 3 - DEFAULT_PARTIAL_ENTRY_SIZE);
464 return TestSucceeded;
465 }
466
467 static test_result_t
test_multiple_entries_5(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)468 test_multiple_entries_5(
469 checker_list_t *checker_list,
470 mach_vm_address_t start,
471 mach_vm_size_t size)
472 {
473 assert_allocation_and_hole_pattern(checker_list, "###");
474 assert(start == checker_range_start_address(checker_list->entries) + DEFAULT_PARTIAL_ENTRY_SIZE);
475 assert(size == DEFAULT_ENTRY_SIZE * 3 - DEFAULT_PARTIAL_ENTRY_SIZE);
476 return TestSucceeded;
477 }
478
479 static test_result_t
test_multiple_entries_6(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)480 test_multiple_entries_6(
481 checker_list_t *checker_list,
482 mach_vm_address_t start,
483 mach_vm_size_t size)
484 {
485 assert_allocation_and_hole_pattern(checker_list, "###");
486 assert(start == checker_range_start_address(checker_list->entries) + DEFAULT_PARTIAL_ENTRY_SIZE / 2);
487 assert(size == DEFAULT_ENTRY_SIZE * 3 - DEFAULT_PARTIAL_ENTRY_SIZE);
488 return TestSucceeded;
489 }
490
491
492 static test_result_t
test_some_holes_1(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)493 test_some_holes_1(
494 checker_list_t *checker_list,
495 mach_vm_address_t start,
496 mach_vm_size_t size)
497 {
498 assert_allocation_and_hole_pattern(checker_list, ".#");
499 assert(start == checker_range_start_address(checker_list->entries));
500 assert(size == DEFAULT_ENTRY_SIZE * 2);
501 return TestSucceeded;
502 }
503
504 static test_result_t
test_some_holes_2(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)505 test_some_holes_2(
506 checker_list_t *checker_list,
507 mach_vm_address_t start,
508 mach_vm_size_t size)
509 {
510 assert_allocation_and_hole_pattern(checker_list, ".###");
511 assert(start == checker_range_start_address(checker_list->entries));
512 assert(size == DEFAULT_ENTRY_SIZE * 4);
513 return TestSucceeded;
514 }
515
516 static test_result_t
test_some_holes_3(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)517 test_some_holes_3(
518 checker_list_t *checker_list,
519 mach_vm_address_t start,
520 mach_vm_size_t size)
521 {
522 assert_allocation_and_hole_pattern(checker_list, ".#");
523 assert(start == checker_range_start_address(checker_list->entries));
524 assert(size == DEFAULT_ENTRY_SIZE * 2 - DEFAULT_PARTIAL_ENTRY_SIZE);
525 return TestSucceeded;
526 }
527
528 static test_result_t
test_some_holes_4(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)529 test_some_holes_4(
530 checker_list_t *checker_list,
531 mach_vm_address_t start,
532 mach_vm_size_t size)
533 {
534 assert_allocation_and_hole_pattern(checker_list, ".###");
535 assert(start == checker_range_start_address(checker_list->entries));
536 assert(size == DEFAULT_ENTRY_SIZE * 4 - DEFAULT_PARTIAL_ENTRY_SIZE);
537 return TestSucceeded;
538 }
539
540 static test_result_t
test_some_holes_5(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)541 test_some_holes_5(
542 checker_list_t *checker_list,
543 mach_vm_address_t start,
544 mach_vm_size_t size)
545 {
546 assert_allocation_and_hole_pattern(checker_list, "#.");
547 assert(start == checker_range_start_address(checker_list->entries));
548 assert(size == DEFAULT_ENTRY_SIZE * 2);
549 return TestSucceeded;
550 }
551
552 static test_result_t
test_some_holes_6(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)553 test_some_holes_6(
554 checker_list_t *checker_list,
555 mach_vm_address_t start,
556 mach_vm_size_t size)
557 {
558 assert_allocation_and_hole_pattern(checker_list, "###.");
559 assert(start == checker_range_start_address(checker_list->entries));
560 assert(size == DEFAULT_ENTRY_SIZE * 4);
561 return TestSucceeded;
562 }
563
564 static test_result_t
test_some_holes_7(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)565 test_some_holes_7(
566 checker_list_t *checker_list,
567 mach_vm_address_t start,
568 mach_vm_size_t size)
569 {
570 assert_allocation_and_hole_pattern(checker_list, "#.");
571 assert(start == checker_range_start_address(checker_list->entries) + DEFAULT_PARTIAL_ENTRY_SIZE);
572 assert(size == DEFAULT_ENTRY_SIZE * 2 - DEFAULT_PARTIAL_ENTRY_SIZE);
573 return TestSucceeded;
574 }
575
576 static test_result_t
test_some_holes_8(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)577 test_some_holes_8(
578 checker_list_t *checker_list,
579 mach_vm_address_t start,
580 mach_vm_size_t size)
581 {
582 assert_allocation_and_hole_pattern(checker_list, "###.");
583 assert(start == checker_range_start_address(checker_list->entries) + DEFAULT_PARTIAL_ENTRY_SIZE);
584 assert(size == DEFAULT_ENTRY_SIZE * 4 - DEFAULT_PARTIAL_ENTRY_SIZE);
585 return TestSucceeded;
586 }
587
588 static test_result_t
test_some_holes_9(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)589 test_some_holes_9(
590 checker_list_t *checker_list,
591 mach_vm_address_t start,
592 mach_vm_size_t size)
593 {
594 assert_allocation_and_hole_pattern(checker_list, "#.#");
595 assert(start == checker_range_start_address(checker_list->entries));
596 assert(size == DEFAULT_ENTRY_SIZE * 3);
597 return TestSucceeded;
598 }
599
600 static test_result_t
test_some_holes_10(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)601 test_some_holes_10(
602 checker_list_t *checker_list,
603 mach_vm_address_t start,
604 mach_vm_size_t size)
605 {
606 assert_allocation_and_hole_pattern(checker_list, "#.#.#");
607 assert(start == checker_range_start_address(checker_list->entries));
608 assert(size == DEFAULT_ENTRY_SIZE * 5);
609 return TestSucceeded;
610 }
611
612 static test_result_t
test_some_holes_11(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)613 test_some_holes_11(
614 checker_list_t *checker_list,
615 mach_vm_address_t start,
616 mach_vm_size_t size)
617 {
618 assert_allocation_and_hole_pattern(checker_list, "##.##.##");
619 assert(start == checker_range_start_address(checker_list->entries));
620 assert(size == DEFAULT_ENTRY_SIZE * 8);
621 return TestSucceeded;
622 }
623
624 static test_result_t
test_some_holes_12(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)625 test_some_holes_12(
626 checker_list_t *checker_list,
627 mach_vm_address_t start,
628 mach_vm_size_t size)
629 {
630 assert_allocation_and_hole_pattern(checker_list, "###.###.###");
631 assert(start == checker_range_start_address(checker_list->entries));
632 assert(size == DEFAULT_ENTRY_SIZE * 11);
633 return TestSucceeded;
634 }
635
636
637 static test_result_t
test_all_holes_1(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)638 test_all_holes_1(
639 checker_list_t *checker_list,
640 mach_vm_address_t start,
641 mach_vm_size_t size)
642 {
643 assert_allocation_and_hole_pattern(checker_list, "#.#");
644 assert(start == checker_range_start_address(checker_list->entries) + DEFAULT_ENTRY_SIZE);
645 assert(size == DEFAULT_ENTRY_SIZE);
646 return TestSucceeded;
647 }
648
649 static test_result_t
test_all_holes_2(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)650 test_all_holes_2(
651 checker_list_t *checker_list,
652 mach_vm_address_t start,
653 mach_vm_size_t size)
654 {
655 assert_allocation_and_hole_pattern(checker_list, "#.");
656 assert(start == checker_range_start_address(checker_list->entries) + DEFAULT_ENTRY_SIZE);
657 assert(size == DEFAULT_PARTIAL_ENTRY_SIZE);
658 return TestSucceeded;
659 }
660
661 static test_result_t
test_all_holes_3(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)662 test_all_holes_3(
663 checker_list_t *checker_list,
664 mach_vm_address_t start,
665 mach_vm_size_t size)
666 {
667 assert_allocation_and_hole_pattern(checker_list, ".#");
668 assert(start == checker_range_start_address(checker_list->entries) + DEFAULT_PARTIAL_ENTRY_SIZE);
669 assert(size == DEFAULT_PARTIAL_ENTRY_SIZE);
670 return TestSucceeded;
671 }
672
673 static test_result_t
test_all_holes_4(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)674 test_all_holes_4(
675 checker_list_t *checker_list,
676 mach_vm_address_t start,
677 mach_vm_size_t size)
678 {
679 assert_allocation_and_hole_pattern(checker_list, ".");
680 assert(start == checker_range_start_address(checker_list->entries) + DEFAULT_PARTIAL_ENTRY_SIZE / 2);
681 assert(size == DEFAULT_PARTIAL_ENTRY_SIZE);
682 return TestSucceeded;
683 }
684
685
686 static test_result_t
test_null_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)687 test_null_entry(
688 checker_list_t *checker_list,
689 mach_vm_address_t start,
690 mach_vm_size_t size)
691 {
692 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
693 vm_region_submap_info_data_64_t info;
694 assert_allocation_checker_and_entry(checker, start, size, &info);
695
696 /* entry's object is null */
697 assert(info.object_id_full == 0);
698 assert(checker->object->object_id == 0);
699
700 return TestSucceeded;
701 }
702
703 static test_result_t
test_nonresident_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)704 test_nonresident_entry(
705 checker_list_t *checker_list,
706 mach_vm_address_t start,
707 mach_vm_size_t size)
708 {
709 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
710 vm_region_submap_info_data_64_t info;
711 assert_allocation_checker_and_entry(checker, start, size, &info);
712
713 /* entry has an object, but its pages are not resident */
714 assert(info.object_id_full != 0);
715 assert(info.pages_resident == 0);
716
717 assert(checker->object->object_id != 0);
718 assert(checker->pages_resident == 0);
719
720 return TestSucceeded;
721 }
722
723 static test_result_t
test_resident_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)724 test_resident_entry(
725 checker_list_t *checker_list,
726 mach_vm_address_t start,
727 mach_vm_size_t size)
728 {
729 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
730 vm_region_submap_info_data_64_t info;
731 assert_allocation_checker_and_entry(checker, start, size, &info);
732
733 /* entry has an object and its pages are resident */
734 assert(info.pages_resident == size / PAGE_SIZE);
735 assert(checker->pages_resident == size / PAGE_SIZE);
736 assert(checker->object->object_id != 0);
737
738 return TestSucceeded;
739 }
740
741 /* common code for two-shared-entry tests */
742 static void
test_one_shared_pair(checker_list_t * checker_list,mach_vm_address_t left_entry_start,mach_vm_address_t right_entry_start,mach_vm_size_t size,mach_vm_address_t right_object_offset)743 test_one_shared_pair(
744 checker_list_t *checker_list,
745 mach_vm_address_t left_entry_start,
746 mach_vm_address_t right_entry_start,
747 mach_vm_size_t size,
748 mach_vm_address_t right_object_offset)
749 {
750 /*
751 * Two entries, both have the same object with refcount two.
752 * Right entry's object offset varies.
753 */
754 vm_entry_checker_t *left_checker =
755 checker_list_find_allocation(checker_list, left_entry_start);
756 vm_entry_checker_t *right_checker =
757 checker_list_find_allocation(checker_list, right_entry_start);
758 assert(left_checker);
759 assert(right_checker);
760
761 vm_region_submap_info_data_64_t left_info, right_info;
762 assert_allocation_checker_and_entry(left_checker, left_entry_start, size, &left_info);
763 assert_allocation_checker_and_entry(right_checker, right_entry_start, size, &right_info);
764
765 assert(left_info.object_id_full != 0);
766 assert(left_info.object_id_full == right_info.object_id_full);
767 assert(left_info.ref_count == 2);
768 assert(right_info.ref_count == 2);
769 assert(left_info.share_mode == SM_TRUESHARED);
770 assert(right_info.share_mode == SM_TRUESHARED);
771 assert(left_info.offset == 0);
772 assert(right_info.offset == right_object_offset);
773 assert(left_info.user_tag != right_info.user_tag);
774
775 assert(left_checker->object == right_checker->object);
776 /* checker doesn't distinguish SM_SHARED from SM_TRUESHARED */
777 assert(checker_share_mode(left_checker) == SM_SHARED);
778 assert(checker_share_mode(right_checker) == SM_SHARED);
779 assert(left_checker->object_offset == 0);
780 assert(right_checker->object_offset == right_object_offset);
781 assert(left_checker->user_tag != right_checker->user_tag);
782 }
783
784 static test_result_t
test_shared_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)785 test_shared_entry(
786 checker_list_t *checker_list,
787 mach_vm_address_t start,
788 mach_vm_size_t size)
789 {
790 /* entries are both at object offset 0 */
791 test_one_shared_pair(checker_list, start, start + size, size, 0);
792 return TestSucceeded;
793 }
794
795 static test_result_t
test_shared_entry_discontiguous(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)796 test_shared_entry_discontiguous(
797 checker_list_t *checker_list,
798 mach_vm_address_t start,
799 mach_vm_size_t size)
800 {
801 /*
802 * right entry's object offset begins
803 * after the left entry's range ends
804 */
805 test_one_shared_pair(checker_list, start, start + size, size, DEFAULT_ENTRY_SIZE);
806 return TestSucceeded;
807 }
808
809 static test_result_t
test_shared_entry_partial(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)810 test_shared_entry_partial(
811 checker_list_t *checker_list,
812 mach_vm_address_t start,
813 mach_vm_size_t size)
814 {
815 /*
816 * right entry's object offset begins
817 * inside the left entry's range
818 */
819 test_one_shared_pair(checker_list, start, start + size, size, DEFAULT_PARTIAL_ENTRY_SIZE);
820 return TestSucceeded;
821 }
822
823 static test_result_t
test_shared_entry_pairs(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)824 test_shared_entry_pairs(
825 checker_list_t *checker_list,
826 mach_vm_address_t start,
827 mach_vm_size_t size)
828 {
829 /*
830 * two shared pairs
831 */
832 mach_vm_size_t entry_size = size / 4;
833 mach_vm_address_t one = start;
834 mach_vm_address_t two = one + entry_size;
835 mach_vm_address_t three = two + entry_size;
836 mach_vm_address_t four = three + entry_size;
837
838 test_one_shared_pair(checker_list, one, four, entry_size, 0);
839 test_one_shared_pair(checker_list, two, three, entry_size, 0);
840
841 return TestSucceeded;
842 }
843
844 static test_result_t
test_shared_entry_x1000(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)845 test_shared_entry_x1000(
846 checker_list_t *checker_list,
847 mach_vm_address_t start,
848 mach_vm_size_t size)
849 {
850 /* many entries, all of which share the same object */
851
852 entry_checker_range_t limit = checker_list_find_range(checker_list, start, size);
853 assert(checker_range_count(limit) == 1000);
854
855 uint64_t shared_object_id = 0;
856 FOREACH_CHECKER(checker, limit) {
857 assert(checker->object);
858 assert(checker->object->object_id_mode == object_has_known_id);
859 if (!shared_object_id) {
860 assert(checker->object->object_id != 0);
861 shared_object_id = checker->object->object_id;
862 }
863 assert(checker->object->object_id == shared_object_id);
864 assert(get_object_id_for_address(checker->address) == shared_object_id);
865 }
866
867 return TestSucceeded;
868 }
869
870
871 /* common code for two-shared-entry tests */
872 static test_result_t
test_cow_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)873 test_cow_entry(
874 checker_list_t *checker_list,
875 mach_vm_address_t start,
876 mach_vm_size_t size)
877 {
878 /*
879 * two entries, both have the same object and its refcount is two.
880 * [start, start + size) is only the first entry
881 */
882 vm_entry_checker_t *left_checker = checker_list_nth(checker_list, 0);
883 vm_region_submap_info_data_64_t left_info;
884 assert_allocation_checker_and_entry(left_checker, start, size, &left_info);
885
886 vm_entry_checker_t *right_checker = checker_list_nth(checker_list, 1);
887 vm_region_submap_info_data_64_t right_info;
888 assert_allocation_checker_and_entry(right_checker, start + size, size, &right_info);
889
890 assert(left_info.object_id_full != 0);
891 assert(left_info.object_id_full == right_info.object_id_full);
892 assert(left_info.ref_count == 2);
893 assert(right_info.ref_count == 2);
894 assert(left_info.share_mode == SM_COW);
895 assert(right_info.share_mode == SM_COW);
896 assert(left_info.offset == 0);
897 assert(right_info.offset == 0);
898
899 assert(left_checker->object == right_checker->object);
900 assert(checker_share_mode(left_checker) == SM_COW);
901 assert(checker_share_mode(right_checker) == SM_COW);
902 assert(left_checker->object_offset == 0);
903 assert(right_checker->object_offset == 0);
904
905 return TestSucceeded;
906 }
907
908 static test_result_t
test_cow_unreferenced(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)909 test_cow_unreferenced(
910 checker_list_t *checker_list,
911 mach_vm_address_t start,
912 mach_vm_size_t size)
913 {
914 /*
915 * one COW entry with refcount 1
916 */
917 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
918 vm_region_submap_info_data_64_t info;
919 assert_allocation_checker_and_entry(checker, start, size, &info);
920
921 assert(info.share_mode == SM_COW);
922 assert(info.object_id_full != 0);
923 assert(info.ref_count == 1);
924 assert(info.offset == 0);
925
926 assert(checker->object_offset == 0);
927 assert(checker_share_mode(checker) == SM_COW);
928 assert(checker->object);
929 assert(checker->object->self_ref_count == 1);
930
931 return TestSucceeded;
932 }
933
934 /* common checks for cow_nocow and nocow_cow */
935 static test_result_t
test_cow_nocow_common(vm_entry_checker_t * cow_checker,vm_entry_checker_t * plain_checker,mach_vm_address_t cow_start_address,mach_vm_address_t plain_start_address,mach_vm_size_t entry_size)936 test_cow_nocow_common(
937 vm_entry_checker_t *cow_checker,
938 vm_entry_checker_t *plain_checker,
939 mach_vm_address_t cow_start_address,
940 mach_vm_address_t plain_start_address,
941 mach_vm_size_t entry_size)
942 {
943 /* two entries: one is COW, one is not COW */
944 vm_region_submap_info_data_64_t cow_info, plain_info;
945 assert_allocation_checker_and_entry(cow_checker, cow_start_address, entry_size, &cow_info);
946 assert_allocation_checker_and_entry(plain_checker, plain_start_address, entry_size, &plain_info);
947
948 assert(cow_info.share_mode == SM_COW);
949 assert(plain_info.share_mode == SM_PRIVATE);
950 assert(cow_info.object_id_full != 0);
951 assert(cow_info.object_id_full != plain_info.object_id_full);
952 assert(cow_info.ref_count == 2);
953 assert(cow_info.offset == 0);
954
955 assert(checker_share_mode(cow_checker) == SM_COW);
956 assert(checker_share_mode(plain_checker) == SM_PRIVATE);
957 assert(cow_checker->object != NULL);
958 assert(cow_checker->object != plain_checker->object);
959 assert(cow_checker->object_offset == 0);
960
961 return TestSucceeded;
962 }
963
964 static test_result_t
test_cow_nocow(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)965 test_cow_nocow(
966 checker_list_t *checker_list,
967 mach_vm_address_t start,
968 mach_vm_size_t size)
969 {
970 /*
971 * two entries: first is COW, second is not
972 */
973 vm_entry_checker_t *cow_checker = checker_list_nth(checker_list, 0);
974 vm_entry_checker_t *plain_checker = checker_list_nth(checker_list, 1);
975
976 assert(size % 2 == 0);
977 mach_vm_address_t cow_start = start;
978 mach_vm_address_t plain_start = start + size / 2;
979
980 return test_cow_nocow_common(cow_checker, plain_checker,
981 cow_start, plain_start, size / 2);
982 }
983
984 static test_result_t
test_nocow_cow(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)985 test_nocow_cow(
986 checker_list_t *checker_list,
987 mach_vm_address_t start,
988 mach_vm_size_t size)
989 {
990 /*
991 * two entries: first is not COW, second is COW
992 */
993 vm_entry_checker_t *plain_checker = checker_list_nth(checker_list, 0);
994 vm_entry_checker_t *cow_checker = checker_list_nth(checker_list, 1);
995
996 assert(size % 2 == 0);
997 mach_vm_address_t plain_start = start;
998 mach_vm_address_t cow_start = start + size / 2;
999
1000 return test_cow_nocow_common(cow_checker, plain_checker,
1001 cow_start, plain_start, size / 2);
1002 }
1003
1004 static test_result_t
test_cow_unreadable(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1005 test_cow_unreadable(
1006 checker_list_t *checker_list,
1007 mach_vm_address_t start,
1008 mach_vm_size_t size)
1009 {
1010 /*
1011 * COW entry, unreadable
1012 */
1013 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
1014 vm_region_submap_info_data_64_t info;
1015 assert_allocation_checker_and_entry(checker, start, size, &info);
1016
1017 assert(info.share_mode == SM_COW);
1018 assert(info.protection == VM_PROT_NONE);
1019 assert(info.ref_count == 2);
1020
1021 assert(checker_share_mode(checker) == SM_COW);
1022 assert(checker->protection == VM_PROT_NONE);
1023 assert(checker->object != NULL);
1024 assert(checker->object->self_ref_count == 2);
1025
1026 return TestSucceeded;
1027 }
1028
1029 static test_result_t
test_cow_unwriteable(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1030 test_cow_unwriteable(
1031 checker_list_t *checker_list,
1032 mach_vm_address_t start,
1033 mach_vm_size_t size)
1034 {
1035 /*
1036 * COW entry, readable but unwriteable
1037 */
1038 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
1039 vm_region_submap_info_data_64_t info;
1040 assert_allocation_checker_and_entry(checker, start, size, &info);
1041
1042 assert(info.share_mode == SM_COW);
1043 assert(info.protection == VM_PROT_READ);
1044 assert(info.ref_count == 2);
1045
1046 assert(checker_share_mode(checker) == SM_COW);
1047 assert(checker->protection == VM_PROT_READ);
1048 assert(checker->object != NULL);
1049 assert(checker->object->self_ref_count == 2);
1050
1051 return TestSucceeded;
1052 }
1053
1054 static test_result_t
test_permanent_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1055 test_permanent_entry(
1056 checker_list_t *checker_list,
1057 mach_vm_address_t start,
1058 mach_vm_size_t size)
1059 {
1060 destructively_assert_permanent_checker_and_entry(
1061 checker_list_nth(checker_list, 0), start, size);
1062
1063 return TestSucceeded;
1064 }
1065
1066 static test_result_t
test_permanent_before_permanent(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1067 test_permanent_before_permanent(
1068 checker_list_t *checker_list,
1069 mach_vm_address_t start,
1070 mach_vm_size_t size)
1071 {
1072 destructively_assert_permanent_checker_and_entry(
1073 checker_list_nth(checker_list, 0),
1074 start, size / 2);
1075 destructively_assert_permanent_checker_and_entry(
1076 checker_list_nth(checker_list, 1),
1077 start + size / 2, size / 2);
1078
1079 return TestSucceeded;
1080 }
1081
1082 static test_result_t
test_permanent_before_allocation(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1083 test_permanent_before_allocation(
1084 checker_list_t *checker_list,
1085 mach_vm_address_t start,
1086 mach_vm_size_t size)
1087 {
1088 destructively_assert_permanent_checker_and_entry(
1089 checker_list_nth(checker_list, 0),
1090 start, size / 2);
1091 destructively_assert_nonpermanent_checker_and_entry(
1092 checker_list,
1093 checker_list_nth(checker_list, 1),
1094 start + size / 2, size / 2);
1095 assert_hole_checker_and_entry(
1096 checker_list_nth(checker_list, 2),
1097 start + size, DEFAULT_ENTRY_SIZE);
1098 return TestSucceeded;
1099 }
1100
1101 static test_result_t
test_permanent_before_allocation_2(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1102 test_permanent_before_allocation_2(
1103 checker_list_t *checker_list,
1104 mach_vm_address_t start,
1105 mach_vm_size_t size)
1106 {
1107 vm_region_submap_info_data_64_t info;
1108 destructively_assert_permanent_checker_and_entry(
1109 checker_list_nth(checker_list, 0),
1110 start, size / 2);
1111 destructively_assert_nonpermanent_checker_and_entry(
1112 checker_list,
1113 checker_list_nth(checker_list, 1),
1114 start + size / 2, size / 2);
1115 assert_allocation_checker_and_entry(
1116 checker_list_nth(checker_list, 2),
1117 start + size, DEFAULT_ENTRY_SIZE, &info);
1118
1119 return TestSucceeded;
1120 }
1121
1122 static test_result_t
test_permanent_before_hole(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1123 test_permanent_before_hole(
1124 checker_list_t *checker_list,
1125 mach_vm_address_t start,
1126 mach_vm_size_t size)
1127 {
1128 destructively_assert_permanent_checker_and_entry(
1129 checker_list_nth(checker_list, 0),
1130 start, size / 2);
1131 assert_hole_checker_and_entry(
1132 checker_list_nth(checker_list, 1),
1133 start + size / 2, size / 2);
1134
1135 return TestSucceeded;
1136 }
1137
1138 static test_result_t
test_permanent_after_allocation(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1139 test_permanent_after_allocation(
1140 checker_list_t *checker_list,
1141 mach_vm_address_t start,
1142 mach_vm_size_t size)
1143 {
1144 destructively_assert_nonpermanent_checker_and_entry(
1145 checker_list,
1146 checker_list_nth(checker_list, 0),
1147 start, size / 2);
1148 destructively_assert_permanent_checker_and_entry(
1149 checker_list_nth(checker_list, 1),
1150 start + size / 2, size / 2);
1151
1152 return TestSucceeded;
1153 }
1154
1155 static test_result_t
test_permanent_after_hole(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1156 test_permanent_after_hole(
1157 checker_list_t *checker_list,
1158 mach_vm_address_t start,
1159 mach_vm_size_t size)
1160 {
1161 assert_hole_checker_and_entry(
1162 checker_list_nth(checker_list, 0),
1163 start, size / 2);
1164 destructively_assert_permanent_checker_and_entry(
1165 checker_list_nth(checker_list, 1),
1166 start + size / 2, size / 2);
1167
1168 return TestSucceeded;
1169 }
1170
1171
1172 static test_result_t
test_single_submap_single_entry_common(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1173 test_single_submap_single_entry_common(
1174 checker_list_t *checker_list,
1175 mach_vm_address_t start,
1176 mach_vm_size_t size)
1177 {
1178 vm_region_submap_info_data_64_t info;
1179
1180 vm_entry_checker_t *submap_parent = checker_list_nth(checker_list, 0);
1181 assert_submap_checker_and_entry(submap_parent, start, size, &info);
1182
1183 checker_list_t *submap_checkers DEFER_UNSLIDE =
1184 checker_get_and_slide_submap_checkers(submap_parent);
1185
1186 vm_entry_checker_t *submap_content = checker_list_nth(submap_checkers, 0);
1187 assert_allocation_checker_and_entry(submap_content, start, size, &info);
1188
1189 return TestSucceeded;
1190 }
1191
1192 static test_result_t
test_single_submap_single_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1193 test_single_submap_single_entry(
1194 checker_list_t *checker_list,
1195 mach_vm_address_t start,
1196 mach_vm_size_t size)
1197 {
1198 return test_single_submap_single_entry_common(
1199 checker_list, start, size);
1200 }
1201
1202 static test_result_t
test_single_submap_single_entry_first_pages(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1203 test_single_submap_single_entry_first_pages(
1204 checker_list_t *checker_list,
1205 mach_vm_address_t start,
1206 mach_vm_size_t size)
1207 {
1208 /* tested range excludes the last 1/2 of the real entry */
1209 mach_vm_size_t submap_size = size * 2;
1210 mach_vm_address_t submap_start = start;
1211 return test_single_submap_single_entry_common(
1212 checker_list, submap_start, submap_size);
1213 }
1214
1215 static test_result_t
test_single_submap_single_entry_last_pages(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1216 test_single_submap_single_entry_last_pages(
1217 checker_list_t *checker_list,
1218 mach_vm_address_t start,
1219 mach_vm_size_t size)
1220 {
1221 /* tested range excludes the first 1/2 of the real entry */
1222 mach_vm_size_t submap_size = size * 2;
1223 mach_vm_address_t submap_start = start - submap_size / 2;
1224 return test_single_submap_single_entry_common(
1225 checker_list, submap_start, submap_size);
1226 }
1227
1228 static test_result_t
test_single_submap_single_entry_middle_pages(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1229 test_single_submap_single_entry_middle_pages(
1230 checker_list_t *checker_list,
1231 mach_vm_address_t start,
1232 mach_vm_size_t size)
1233 {
1234 /* tested range excludes the first 1/4 and last 1/4 of the real entry */
1235 mach_vm_size_t submap_size = size * 2;
1236 mach_vm_address_t submap_start = start - submap_size / 4;
1237 return test_single_submap_single_entry_common(
1238 checker_list, submap_start, submap_size);
1239 }
1240
1241 static test_result_t
test_single_submap_oversize_entry_common(checker_list_t * checker_list,mach_vm_address_t parent_start,mach_vm_size_t parent_size,mach_vm_address_t parent_offset,mach_vm_size_t submap_size)1242 test_single_submap_oversize_entry_common(
1243 checker_list_t *checker_list,
1244 mach_vm_address_t parent_start,
1245 mach_vm_size_t parent_size,
1246 mach_vm_address_t parent_offset,
1247 mach_vm_size_t submap_size)
1248 {
1249 vm_region_submap_info_data_64_t parent_info, content_info;
1250
1251 vm_entry_checker_t *submap_parent = checker_list_nth(checker_list, 0);
1252 assert_submap_checker_and_entry(submap_parent, parent_start, parent_size, &parent_info);
1253 assert(submap_parent->object_offset == parent_offset);
1254 assert(parent_info.offset == parent_offset);
1255
1256 checker_list_t *submap_checkers DEFER_UNSLIDE =
1257 checker_get_and_slide_submap_checkers(submap_parent);
1258
1259 /*
1260 * Actual entry in submap is clamped to the parent map submap view
1261 * by vm_region. Checker for that entry is unchanged.
1262 */
1263 vm_entry_checker_t *submap_content = checker_list_nth(submap_checkers, 0);
1264 assert_allocation_checker(submap_content, parent_start - parent_offset, submap_size);
1265 assert(submap_content->submap_depth == 1);
1266 assert_allocation_entry(parent_start, parent_size, 1 /* submap_depth */, &content_info);
1267 assert(submap_content->object_offset == 0);
1268 assert(content_info.offset == 0);
1269
1270 return TestSucceeded;
1271 }
1272
1273 static test_result_t
test_single_submap_oversize_entry_at_start(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1274 test_single_submap_oversize_entry_at_start(
1275 checker_list_t *checker_list,
1276 mach_vm_address_t start,
1277 mach_vm_size_t size)
1278 {
1279 /*
1280 * parent map: [start, start+size]
1281 * submap: [0 (size) size*2]
1282 */
1283 return test_single_submap_oversize_entry_common(checker_list,
1284 start, size,
1285 size /* parent_offset */, size * 2 /* submap_size */);
1286 }
1287
1288 static test_result_t
test_single_submap_oversize_entry_at_end(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1289 test_single_submap_oversize_entry_at_end(
1290 checker_list_t *checker_list,
1291 mach_vm_address_t start,
1292 mach_vm_size_t size)
1293 {
1294 /*
1295 * parent map: [start, start+size]
1296 * submap: [0 (size) size*2]
1297 */
1298 return test_single_submap_oversize_entry_common(checker_list,
1299 start, size,
1300 0 /* parent_offset */, size * 2 /* submap_size */);
1301 }
1302
1303 static test_result_t
test_single_submap_oversize_entry_at_both(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1304 test_single_submap_oversize_entry_at_both(
1305 checker_list_t *checker_list,
1306 mach_vm_address_t start,
1307 mach_vm_size_t size)
1308 {
1309 /*
1310 * parent map: [start, start+size]
1311 * submap: [0 (size / 2) size*2]
1312 */
1313 return test_single_submap_oversize_entry_common(checker_list,
1314 start, size,
1315 size / 2 /* parent_offset */, size * 2 /* submap_size */);
1316 }
1317
1318 static test_result_t
test_submap_before_allocation_common(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size,int submap_protection)1319 test_submap_before_allocation_common(
1320 checker_list_t *checker_list,
1321 mach_vm_address_t start,
1322 mach_vm_size_t size,
1323 int submap_protection)
1324 {
1325 vm_region_submap_info_data_64_t submap_parent_info;
1326 vm_entry_checker_t *submap_parent = checker_list_nth(checker_list, 0);
1327 assert_submap_checker_and_entry(submap_parent,
1328 start, size / 2, &submap_parent_info);
1329
1330 vm_region_submap_info_data_64_t allocation_info;
1331 vm_entry_checker_t *allocation = checker_list_nth(checker_list, 1);
1332 assert_allocation_checker_and_entry(allocation,
1333 start + size / 2, size / 2, &allocation_info);
1334
1335 checker_list_t *submap_checkers DEFER_UNSLIDE =
1336 checker_get_and_slide_submap_checkers(submap_parent);
1337
1338 vm_region_submap_info_data_64_t submap_content_info;
1339 vm_entry_checker_t *submap_content = checker_list_nth(submap_checkers, 0);
1340 assert_allocation_checker(submap_content, start, size / 2);
1341 assert_allocation_entry(start, size / 2, 1 /* submap_depth */, &submap_content_info);
1342 assert_checker_and_entry_protection_equals(submap_content, &submap_content_info,
1343 submap_protection, submap_protection);
1344
1345 return TestSucceeded;
1346 }
1347
1348 static test_result_t
test_submap_before_allocation(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1349 test_submap_before_allocation(
1350 checker_list_t *checker_list,
1351 mach_vm_address_t start,
1352 mach_vm_size_t size)
1353 {
1354 return test_submap_before_allocation_common(checker_list,
1355 start, size, VM_PROT_READ | VM_PROT_WRITE);
1356 }
1357
1358 static test_result_t
test_submap_before_allocation_ro(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1359 test_submap_before_allocation_ro(
1360 checker_list_t *checker_list,
1361 mach_vm_address_t start,
1362 mach_vm_size_t size)
1363 {
1364 return test_submap_before_allocation_common(checker_list,
1365 start, size, VM_PROT_READ);
1366 }
1367
1368 static test_result_t
test_submap_after_allocation_common(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size,int submap_protection)1369 test_submap_after_allocation_common(
1370 checker_list_t *checker_list,
1371 mach_vm_address_t start,
1372 mach_vm_size_t size,
1373 int submap_protection)
1374 {
1375 vm_region_submap_info_data_64_t allocation_info;
1376 vm_entry_checker_t *allocation = checker_list_nth(checker_list, 0);
1377 assert_allocation_checker_and_entry(allocation,
1378 start, size / 2, &allocation_info);
1379
1380 vm_region_submap_info_data_64_t submap_parent_info;
1381 vm_entry_checker_t *submap_parent = checker_list_nth(checker_list, 1);
1382 assert_submap_checker_and_entry(submap_parent,
1383 start + size / 2, size / 2, &submap_parent_info);
1384
1385 checker_list_t *submap_checkers DEFER_UNSLIDE =
1386 checker_get_and_slide_submap_checkers(submap_parent);
1387
1388 vm_region_submap_info_data_64_t submap_content_info;
1389 vm_entry_checker_t *submap_content = checker_list_nth(submap_checkers, 0);
1390 assert_allocation_checker(submap_content, start + size / 2, size / 2);
1391 assert_allocation_entry(start + size / 2, size / 2, 1 /* submap_depth */, &submap_content_info);
1392 assert_checker_and_entry_protection_equals(submap_content, &submap_content_info,
1393 submap_protection, submap_protection);
1394
1395 return TestSucceeded;
1396 }
1397
1398 static test_result_t
test_submap_after_allocation(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1399 test_submap_after_allocation(
1400 checker_list_t *checker_list,
1401 mach_vm_address_t start,
1402 mach_vm_size_t size)
1403 {
1404 return test_submap_after_allocation_common(checker_list,
1405 start, size, VM_PROT_READ | VM_PROT_WRITE);
1406 }
1407
1408 static test_result_t
test_submap_after_allocation_ro(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1409 test_submap_after_allocation_ro(
1410 checker_list_t *checker_list,
1411 mach_vm_address_t start,
1412 mach_vm_size_t size)
1413 {
1414 return test_submap_after_allocation_common(checker_list,
1415 start, size, VM_PROT_READ);
1416 }
1417
1418 static test_result_t
test_submap_before_hole_common(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size,int submap_protection)1419 test_submap_before_hole_common(
1420 checker_list_t *checker_list,
1421 mach_vm_address_t start,
1422 mach_vm_size_t size,
1423 int submap_protection)
1424 {
1425 vm_region_submap_info_data_64_t submap_parent_info;
1426 vm_entry_checker_t *submap_parent = checker_list_nth(checker_list, 0);
1427 assert_submap_checker_and_entry(submap_parent,
1428 start, size / 2, &submap_parent_info);
1429
1430 vm_entry_checker_t *hole = checker_list_nth(checker_list, 1);
1431 assert_hole_checker_and_entry(hole,
1432 start + size / 2, size / 2);
1433
1434 checker_list_t *submap_checkers DEFER_UNSLIDE =
1435 checker_get_and_slide_submap_checkers(submap_parent);
1436
1437 vm_region_submap_info_data_64_t submap_content_info;
1438 vm_entry_checker_t *submap_content = checker_list_nth(submap_checkers, 0);
1439 assert_allocation_checker(submap_content, start, size / 2);
1440 assert_allocation_entry(start, size / 2, 1 /* submap_depth */, &submap_content_info);
1441 assert_checker_and_entry_protection_equals(submap_content, &submap_content_info,
1442 submap_protection, submap_protection);
1443
1444 return TestSucceeded;
1445 }
1446
1447 static test_result_t
test_submap_before_hole(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1448 test_submap_before_hole(
1449 checker_list_t *checker_list,
1450 mach_vm_address_t start,
1451 mach_vm_size_t size)
1452 {
1453 return test_submap_before_hole_common(checker_list,
1454 start, size, VM_PROT_READ | VM_PROT_WRITE);
1455 }
1456
1457 static test_result_t
test_submap_before_hole_ro(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1458 test_submap_before_hole_ro(
1459 checker_list_t *checker_list,
1460 mach_vm_address_t start,
1461 mach_vm_size_t size)
1462 {
1463 return test_submap_before_hole_common(checker_list,
1464 start, size, VM_PROT_READ);
1465 }
1466
1467 static test_result_t
test_submap_after_hole_common(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size,int submap_protection)1468 test_submap_after_hole_common(
1469 checker_list_t *checker_list,
1470 mach_vm_address_t start,
1471 mach_vm_size_t size,
1472 int submap_protection)
1473 {
1474 vm_entry_checker_t *hole = checker_list_nth(checker_list, 0);
1475 assert_hole_checker_and_entry(hole,
1476 start, size / 2);
1477
1478 vm_region_submap_info_data_64_t submap_parent_info;
1479 vm_entry_checker_t *submap_parent = checker_list_nth(checker_list, 1);
1480 assert_submap_checker_and_entry(submap_parent,
1481 start + size / 2, size / 2, &submap_parent_info);
1482
1483 checker_list_t *submap_checkers DEFER_UNSLIDE =
1484 checker_get_and_slide_submap_checkers(submap_parent);
1485
1486 vm_region_submap_info_data_64_t submap_content_info;
1487 vm_entry_checker_t *submap_content = checker_list_nth(submap_checkers, 0);
1488 assert_allocation_checker(submap_content, start + size / 2, size / 2);
1489 assert_allocation_entry(start + size / 2, size / 2, 1 /* submap_depth */, &submap_content_info);
1490 assert_checker_and_entry_protection_equals(submap_content, &submap_content_info,
1491 submap_protection, submap_protection);
1492
1493 return TestSucceeded;
1494 }
1495
1496 static test_result_t
test_submap_after_hole(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1497 test_submap_after_hole(
1498 checker_list_t *checker_list,
1499 mach_vm_address_t start,
1500 mach_vm_size_t size)
1501 {
1502 return test_submap_after_hole_common(checker_list,
1503 start, size, VM_PROT_READ | VM_PROT_WRITE);
1504 }
1505
1506 static test_result_t
test_submap_after_hole_ro(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1507 test_submap_after_hole_ro(
1508 checker_list_t *checker_list,
1509 mach_vm_address_t start,
1510 mach_vm_size_t size)
1511 {
1512 return test_submap_after_hole_common(checker_list,
1513 start, size, VM_PROT_READ);
1514 }
1515
1516
1517 /*
1518 * Verify that the checker list consists of three entries,
1519 * a submap mapping, an allocation, and a submap mapping,
1520 * all of default size.
1521 */
1522 static void
assert_submap_allocation_submap(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1523 assert_submap_allocation_submap(
1524 checker_list_t *checker_list,
1525 mach_vm_address_t start,
1526 mach_vm_size_t size)
1527 {
1528 vm_region_submap_info_data_64_t info;
1529 vm_entry_checker_t *checker;
1530 mach_vm_size_t offset;
1531
1532 assert(checker_range_count(checker_list->entries) == 3);
1533
1534 offset = DEFAULT_ENTRY_SIZE * 0;
1535 checker = checker_list_nth(checker_list, 0);
1536 assert_submap_checker_and_entry(checker,
1537 start + offset, DEFAULT_ENTRY_SIZE, &info);
1538 assert(checker->object_offset == offset);
1539 assert(info.offset == offset);
1540
1541 offset = DEFAULT_ENTRY_SIZE * 1;
1542 checker = checker_list_nth(checker_list, 1);
1543 assert_allocation_checker_and_entry(checker,
1544 start + offset, DEFAULT_ENTRY_SIZE, &info);
1545
1546 offset = DEFAULT_ENTRY_SIZE * 2;
1547 checker = checker_list_nth(checker_list, 2);
1548 assert_submap_checker_and_entry(checker,
1549 start + offset, DEFAULT_ENTRY_SIZE, &info);
1550 assert(checker->object_offset == offset);
1551 assert(info.offset == offset);
1552
1553 offset = DEFAULT_ENTRY_SIZE * 3;
1554 assert(size == offset);
1555 }
1556
1557 static test_result_t
test_submap_allocation_submap_one_entry_common(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size,int submap_protection)1558 test_submap_allocation_submap_one_entry_common(
1559 checker_list_t *checker_list,
1560 mach_vm_address_t start,
1561 mach_vm_size_t size,
1562 int submap_protection)
1563 {
1564 /* parent map is submap - allocation - submap */
1565 assert_submap_allocation_submap(checker_list, start, size);
1566
1567 /* submap is one allocation entry */
1568 checker_list_t *submap_checkers DEFER_UNSLIDE =
1569 checker_get_and_slide_submap_checkers(checker_list_nth(checker_list, 0));
1570 assert(checker_range_count(submap_checkers->entries) == 1);
1571 vm_entry_checker_t *submap_content = checker_list_nth(submap_checkers, 0);
1572 assert_allocation_checker(submap_content, start, size);
1573 assert(submap_content->protection == submap_protection);
1574 assert(submap_content->max_protection == submap_protection);
1575
1576 return TestSucceeded;
1577 }
1578
1579 static test_result_t
test_submap_allocation_submap_one_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1580 test_submap_allocation_submap_one_entry(
1581 checker_list_t *checker_list,
1582 mach_vm_address_t start,
1583 mach_vm_size_t size)
1584 {
1585 return test_submap_allocation_submap_one_entry_common(checker_list,
1586 start, size, VM_PROT_READ | VM_PROT_WRITE);
1587 }
1588
1589 static test_result_t
test_submap_allocation_submap_one_entry_ro(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1590 test_submap_allocation_submap_one_entry_ro(
1591 checker_list_t *checker_list,
1592 mach_vm_address_t start,
1593 mach_vm_size_t size)
1594 {
1595 return test_submap_allocation_submap_one_entry_common(checker_list,
1596 start, size, VM_PROT_READ);
1597 }
1598
1599 static test_result_t
test_submap_allocation_submap_two_entries_common(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size,int submap_protection)1600 test_submap_allocation_submap_two_entries_common(
1601 checker_list_t *checker_list,
1602 mach_vm_address_t start,
1603 mach_vm_size_t size,
1604 int submap_protection)
1605 {
1606 /* parent map is submap - allocation - submap */
1607 assert_submap_allocation_submap(checker_list, start, size);
1608
1609 /* submap is two allocation entries */
1610 checker_list_t *submap_checkers DEFER_UNSLIDE =
1611 checker_get_and_slide_submap_checkers(checker_list_nth(checker_list, 0));
1612 assert(checker_range_count(submap_checkers->entries) == 2);
1613
1614 vm_entry_checker_t *submap_content = checker_list_nth(submap_checkers, 0);
1615 assert_allocation_checker(submap_content, start, size / 2);
1616 assert(submap_content->protection == submap_protection);
1617 assert(submap_content->max_protection == submap_protection);
1618
1619 submap_content = checker_list_nth(submap_checkers, 1);
1620 assert_allocation_checker(submap_content, start + size / 2, size / 2);
1621 assert(submap_content->protection == submap_protection);
1622 assert(submap_content->max_protection == submap_protection);
1623
1624 return TestSucceeded;
1625 }
1626
1627 static test_result_t
test_submap_allocation_submap_two_entries(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1628 test_submap_allocation_submap_two_entries(
1629 checker_list_t *checker_list,
1630 mach_vm_address_t start,
1631 mach_vm_size_t size)
1632 {
1633 return test_submap_allocation_submap_two_entries_common(checker_list,
1634 start, size, VM_PROT_READ | VM_PROT_WRITE);
1635 }
1636
1637 static test_result_t
test_submap_allocation_submap_two_entries_ro(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1638 test_submap_allocation_submap_two_entries_ro(
1639 checker_list_t *checker_list,
1640 mach_vm_address_t start,
1641 mach_vm_size_t size)
1642 {
1643 return test_submap_allocation_submap_two_entries_common(checker_list,
1644 start, size, VM_PROT_READ);
1645 }
1646
1647 static test_result_t
test_submap_allocation_submap_three_entries_common(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size,int submap_protection)1648 test_submap_allocation_submap_three_entries_common(
1649 checker_list_t *checker_list,
1650 mach_vm_address_t start,
1651 mach_vm_size_t size,
1652 int submap_protection)
1653 {
1654 /* parent map is submap - allocation - submap */
1655 assert_submap_allocation_submap(checker_list, start, size);
1656
1657 /* submap is three allocation entries */
1658 checker_list_t *submap_checkers DEFER_UNSLIDE =
1659 checker_get_and_slide_submap_checkers(checker_list_nth(checker_list, 0));
1660 assert(checker_range_count(submap_checkers->entries) == 3);
1661
1662 vm_entry_checker_t *submap_content = checker_list_nth(submap_checkers, 0);
1663 assert_allocation_checker(submap_content, start, size / 3);
1664 assert(submap_content->protection == submap_protection);
1665 assert(submap_content->max_protection == submap_protection);
1666
1667 submap_content = checker_list_nth(submap_checkers, 1);
1668 assert_allocation_checker(submap_content, start + size / 3, size / 3);
1669 assert(submap_content->protection == submap_protection);
1670 assert(submap_content->max_protection == submap_protection);
1671
1672 submap_content = checker_list_nth(submap_checkers, 2);
1673 assert_allocation_checker(submap_content, start + size / 3 * 2, size / 3);
1674 assert(submap_content->protection == submap_protection);
1675 assert(submap_content->max_protection == submap_protection);
1676
1677 return TestSucceeded;
1678 }
1679
1680 static test_result_t
test_submap_allocation_submap_three_entries(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1681 test_submap_allocation_submap_three_entries(
1682 checker_list_t *checker_list,
1683 mach_vm_address_t start,
1684 mach_vm_size_t size)
1685 {
1686 return test_submap_allocation_submap_three_entries_common(checker_list,
1687 start, size, VM_PROT_READ | VM_PROT_WRITE);
1688 }
1689
1690 static test_result_t
test_submap_allocation_submap_three_entries_ro(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)1691 test_submap_allocation_submap_three_entries_ro(
1692 checker_list_t *checker_list,
1693 mach_vm_address_t start,
1694 mach_vm_size_t size)
1695 {
1696 return test_submap_allocation_submap_three_entries_common(checker_list,
1697 start, size, VM_PROT_READ);
1698 }
1699
1700
1701 static void
assert_protection(mach_vm_address_t address,vm_prot_t prot,bool check_max,uint32_t submap_depth)1702 assert_protection(
1703 mach_vm_address_t address,
1704 vm_prot_t prot,
1705 bool check_max,
1706 uint32_t submap_depth)
1707 {
1708 mach_vm_address_t info_address = address;
1709 mach_vm_size_t info_size;
1710 vm_region_submap_info_data_64_t info;
1711 assert(get_info_for_address(&info_address, &info_size, &info, submap_depth));
1712 assert(info_address == address);
1713
1714 if (check_max) {
1715 T_QUIET; T_ASSERT_EQ(prot, info.max_protection, "entry max protection");
1716 } else {
1717 T_QUIET; T_ASSERT_EQ(prot, info.protection, "entry protection");
1718 }
1719 }
1720
1721 static test_result_t
test_protection_single_common(checker_list_t * checker_list,mach_vm_address_t address,vm_prot_t prot,vm_prot_t max)1722 test_protection_single_common(
1723 checker_list_t *checker_list,
1724 mach_vm_address_t address,
1725 vm_prot_t prot, vm_prot_t max)
1726 {
1727 vm_entry_checker_t *checker =
1728 checker_list_find_allocation(checker_list, address);
1729 T_QUIET; T_ASSERT_NOTNULL(checker, "checker");
1730 T_QUIET; T_ASSERT_EQ(checker->protection, prot, "checker protection");
1731 T_QUIET; T_ASSERT_EQ(checker->max_protection, max, "checker max protection");
1732
1733 assert_protection(address, prot, false /* check max */, 0 /* submap depth */);
1734 assert_protection(address, max, true /* check max */, 0 /* submap depth */);
1735
1736 return TestSucceeded;
1737 }
1738
1739 static test_result_t
test_protection_pair_common(checker_list_t * checker_list,mach_vm_address_t address,vm_prot_t left_prot,vm_prot_t right_prot)1740 test_protection_pair_common(
1741 checker_list_t *checker_list,
1742 mach_vm_address_t address,
1743 vm_prot_t left_prot,
1744 vm_prot_t right_prot)
1745 {
1746 vm_entry_checker_t *left_checker =
1747 checker_list_find_allocation(checker_list, address);
1748 vm_entry_checker_t *right_checker = left_checker->next;
1749
1750 T_QUIET; T_ASSERT_NOTNULL(left_checker, "checker");
1751 T_QUIET; T_ASSERT_EQ(left_checker->protection, left_prot, "left entry protection");
1752 T_QUIET; T_ASSERT_EQ(right_checker->protection, right_prot, "right entry protection");
1753
1754 assert_protection(left_checker->address, left_prot, false /* check max */, 0 /* submap depth */);
1755 assert_protection(right_checker->address, right_prot, false /* check max */, 0 /* submap depth */);
1756
1757 return TestSucceeded;
1758 }
1759
1760 static test_result_t
test_protection_single_000_000(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1761 test_protection_single_000_000(
1762 checker_list_t *checker_list,
1763 mach_vm_address_t start,
1764 mach_vm_size_t size __unused)
1765 {
1766 return test_protection_single_common(
1767 checker_list, start, VM_PROT_NONE, VM_PROT_NONE);
1768 }
1769
1770 static test_result_t
test_protection_single_000_r00(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1771 test_protection_single_000_r00(
1772 checker_list_t *checker_list,
1773 mach_vm_address_t start,
1774 mach_vm_size_t size __unused)
1775 {
1776 return test_protection_single_common(
1777 checker_list, start, VM_PROT_NONE, VM_PROT_READ);
1778 }
1779
1780 static test_result_t
test_protection_single_000_0w0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1781 test_protection_single_000_0w0(
1782 checker_list_t *checker_list,
1783 mach_vm_address_t start,
1784 mach_vm_size_t size __unused)
1785 {
1786 return test_protection_single_common(
1787 checker_list, start, VM_PROT_NONE, VM_PROT_WRITE);
1788 }
1789
1790 static test_result_t
test_protection_single_000_rw0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1791 test_protection_single_000_rw0(
1792 checker_list_t *checker_list,
1793 mach_vm_address_t start,
1794 mach_vm_size_t size __unused)
1795 {
1796 return test_protection_single_common(
1797 checker_list, start, VM_PROT_NONE, VM_PROT_READ | VM_PROT_WRITE);
1798 }
1799
1800 static test_result_t
test_protection_single_r00_r00(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1801 test_protection_single_r00_r00(
1802 checker_list_t *checker_list,
1803 mach_vm_address_t start,
1804 mach_vm_size_t size __unused)
1805 {
1806 return test_protection_single_common(
1807 checker_list, start, VM_PROT_READ, VM_PROT_READ);
1808 }
1809
1810 static test_result_t
test_protection_single_r00_rw0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1811 test_protection_single_r00_rw0(
1812 checker_list_t *checker_list,
1813 mach_vm_address_t start,
1814 mach_vm_size_t size __unused)
1815 {
1816 return test_protection_single_common(
1817 checker_list, start, VM_PROT_READ, VM_PROT_READ | VM_PROT_WRITE);
1818 }
1819
1820 static test_result_t
test_protection_single_0w0_0w0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1821 test_protection_single_0w0_0w0(
1822 checker_list_t *checker_list,
1823 mach_vm_address_t start,
1824 mach_vm_size_t size __unused)
1825 {
1826 return test_protection_single_common(
1827 checker_list, start, VM_PROT_WRITE, VM_PROT_WRITE);
1828 }
1829
1830 static test_result_t
test_protection_single_0w0_rw0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1831 test_protection_single_0w0_rw0(
1832 checker_list_t *checker_list,
1833 mach_vm_address_t start,
1834 mach_vm_size_t size __unused)
1835 {
1836 return test_protection_single_common(
1837 checker_list, start, VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE);
1838 }
1839
1840 static test_result_t
test_protection_single_rw0_rw0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1841 test_protection_single_rw0_rw0(
1842 checker_list_t *checker_list,
1843 mach_vm_address_t start,
1844 mach_vm_size_t size __unused)
1845 {
1846 return test_protection_single_common(
1847 checker_list, start, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE);
1848 }
1849
1850
1851 static test_result_t
test_protection_pair_000_000(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1852 test_protection_pair_000_000(
1853 checker_list_t *checker_list,
1854 mach_vm_address_t start,
1855 mach_vm_size_t size __unused)
1856 {
1857 return test_protection_pair_common(
1858 checker_list, start, VM_PROT_NONE, VM_PROT_NONE);
1859 }
1860
1861 static test_result_t
test_protection_pair_000_r00(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1862 test_protection_pair_000_r00(
1863 checker_list_t *checker_list,
1864 mach_vm_address_t start,
1865 mach_vm_size_t size __unused)
1866 {
1867 return test_protection_pair_common(
1868 checker_list, start, VM_PROT_NONE, VM_PROT_READ);
1869 }
1870
1871 static test_result_t
test_protection_pair_000_0w0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1872 test_protection_pair_000_0w0(
1873 checker_list_t *checker_list,
1874 mach_vm_address_t start,
1875 mach_vm_size_t size __unused)
1876 {
1877 return test_protection_pair_common(
1878 checker_list, start, VM_PROT_NONE, VM_PROT_WRITE);
1879 }
1880
1881 static test_result_t
test_protection_pair_000_rw0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1882 test_protection_pair_000_rw0(
1883 checker_list_t *checker_list,
1884 mach_vm_address_t start,
1885 mach_vm_size_t size __unused)
1886 {
1887 return test_protection_pair_common(
1888 checker_list, start, VM_PROT_NONE, VM_PROT_READ | VM_PROT_WRITE);
1889 }
1890
1891 static test_result_t
test_protection_pair_r00_000(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1892 test_protection_pair_r00_000(
1893 checker_list_t *checker_list,
1894 mach_vm_address_t start,
1895 mach_vm_size_t size __unused)
1896 {
1897 return test_protection_pair_common(
1898 checker_list, start, VM_PROT_READ, VM_PROT_NONE);
1899 }
1900
1901 static test_result_t
test_protection_pair_r00_r00(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1902 test_protection_pair_r00_r00(
1903 checker_list_t *checker_list,
1904 mach_vm_address_t start,
1905 mach_vm_size_t size __unused)
1906 {
1907 return test_protection_pair_common(
1908 checker_list, start, VM_PROT_READ, VM_PROT_READ);
1909 }
1910
1911 static test_result_t
test_protection_pair_r00_0w0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1912 test_protection_pair_r00_0w0(
1913 checker_list_t *checker_list,
1914 mach_vm_address_t start,
1915 mach_vm_size_t size __unused)
1916 {
1917 return test_protection_pair_common(
1918 checker_list, start, VM_PROT_READ, VM_PROT_WRITE);
1919 }
1920
1921 static test_result_t
test_protection_pair_r00_rw0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1922 test_protection_pair_r00_rw0(
1923 checker_list_t *checker_list,
1924 mach_vm_address_t start,
1925 mach_vm_size_t size __unused)
1926 {
1927 return test_protection_pair_common(
1928 checker_list, start, VM_PROT_READ, VM_PROT_READ | VM_PROT_WRITE);
1929 }
1930
1931 static test_result_t
test_protection_pair_0w0_000(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1932 test_protection_pair_0w0_000(
1933 checker_list_t *checker_list,
1934 mach_vm_address_t start,
1935 mach_vm_size_t size __unused)
1936 {
1937 return test_protection_pair_common(
1938 checker_list, start, VM_PROT_WRITE, VM_PROT_NONE);
1939 }
1940
1941 static test_result_t
test_protection_pair_0w0_r00(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1942 test_protection_pair_0w0_r00(
1943 checker_list_t *checker_list,
1944 mach_vm_address_t start,
1945 mach_vm_size_t size __unused)
1946 {
1947 return test_protection_pair_common(
1948 checker_list, start, VM_PROT_WRITE, VM_PROT_READ);
1949 }
1950
1951 static test_result_t
test_protection_pair_0w0_0w0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1952 test_protection_pair_0w0_0w0(
1953 checker_list_t *checker_list,
1954 mach_vm_address_t start,
1955 mach_vm_size_t size __unused)
1956 {
1957 return test_protection_pair_common(
1958 checker_list, start, VM_PROT_WRITE, VM_PROT_WRITE);
1959 }
1960
1961 static test_result_t
test_protection_pair_0w0_rw0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1962 test_protection_pair_0w0_rw0(
1963 checker_list_t *checker_list,
1964 mach_vm_address_t start,
1965 mach_vm_size_t size __unused)
1966 {
1967 return test_protection_pair_common(
1968 checker_list, start, VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE);
1969 }
1970
1971 static test_result_t
test_protection_pair_rw0_000(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1972 test_protection_pair_rw0_000(
1973 checker_list_t *checker_list,
1974 mach_vm_address_t start,
1975 mach_vm_size_t size __unused)
1976 {
1977 return test_protection_pair_common(
1978 checker_list, start, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_NONE);
1979 }
1980
1981 static test_result_t
test_protection_pair_rw0_r00(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1982 test_protection_pair_rw0_r00(
1983 checker_list_t *checker_list,
1984 mach_vm_address_t start,
1985 mach_vm_size_t size __unused)
1986 {
1987 return test_protection_pair_common(
1988 checker_list, start, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ);
1989 }
1990
1991 static test_result_t
test_protection_pair_rw0_0w0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)1992 test_protection_pair_rw0_0w0(
1993 checker_list_t *checker_list,
1994 mach_vm_address_t start,
1995 mach_vm_size_t size __unused)
1996 {
1997 return test_protection_pair_common(
1998 checker_list, start, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_WRITE);
1999 }
2000
2001 static test_result_t
test_protection_pair_rw0_rw0(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size __unused)2002 test_protection_pair_rw0_rw0(
2003 checker_list_t *checker_list,
2004 mach_vm_address_t start,
2005 mach_vm_size_t size __unused)
2006 {
2007 return test_protection_pair_common(
2008 checker_list, start, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE);
2009 }
2010
2011
2012 T_DECL(test_vm_configurator,
2013 "spot-check VM states generated by vm configurator")
2014 {
2015 vm_tests_t tests = {
2016 .single_entry_1 = test_single_entry_1,
2017 .single_entry_2 = test_single_entry_2,
2018 .single_entry_3 = test_single_entry_3,
2019 .single_entry_4 = test_single_entry_4,
2020
2021 .multiple_entries_1 = test_multiple_entries_1,
2022 .multiple_entries_2 = test_multiple_entries_2,
2023 .multiple_entries_3 = test_multiple_entries_3,
2024 .multiple_entries_4 = test_multiple_entries_4,
2025 .multiple_entries_5 = test_multiple_entries_5,
2026 .multiple_entries_6 = test_multiple_entries_6,
2027
2028 .some_holes_1 = test_some_holes_1,
2029 .some_holes_2 = test_some_holes_2,
2030 .some_holes_3 = test_some_holes_3,
2031 .some_holes_4 = test_some_holes_4,
2032 .some_holes_5 = test_some_holes_5,
2033 .some_holes_6 = test_some_holes_6,
2034 .some_holes_7 = test_some_holes_7,
2035 .some_holes_8 = test_some_holes_8,
2036 .some_holes_9 = test_some_holes_9,
2037 .some_holes_10 = test_some_holes_10,
2038 .some_holes_11 = test_some_holes_11,
2039 .some_holes_12 = test_some_holes_12,
2040
2041 .all_holes_1 = test_all_holes_1,
2042 .all_holes_2 = test_all_holes_2,
2043 .all_holes_3 = test_all_holes_3,
2044 .all_holes_4 = test_all_holes_4,
2045
2046 .null_entry = test_null_entry,
2047 .nonresident_entry = test_nonresident_entry,
2048 .resident_entry = test_resident_entry,
2049
2050 .shared_entry = test_shared_entry,
2051 .shared_entry_discontiguous = test_shared_entry_discontiguous,
2052 .shared_entry_partial = test_shared_entry_partial,
2053 .shared_entry_pairs = test_shared_entry_pairs,
2054 .shared_entry_x1000 = test_shared_entry_x1000,
2055
2056 .cow_entry = test_cow_entry,
2057 .cow_unreferenced = test_cow_unreferenced,
2058 .cow_nocow = test_cow_nocow,
2059 .nocow_cow = test_nocow_cow,
2060 .cow_unreadable = test_cow_unreadable,
2061 .cow_unwriteable = test_cow_unwriteable,
2062
2063 .permanent_entry = test_permanent_entry,
2064 .permanent_before_permanent = test_permanent_before_permanent,
2065 .permanent_before_allocation = test_permanent_before_allocation,
2066 .permanent_before_allocation_2 = test_permanent_before_allocation_2,
2067 .permanent_before_hole = test_permanent_before_hole,
2068 .permanent_after_allocation = test_permanent_after_allocation,
2069 .permanent_after_hole = test_permanent_after_hole,
2070
2071 .single_submap_single_entry = test_single_submap_single_entry,
2072 .single_submap_single_entry_first_pages = test_single_submap_single_entry_first_pages,
2073 .single_submap_single_entry_last_pages = test_single_submap_single_entry_last_pages,
2074 .single_submap_single_entry_middle_pages = test_single_submap_single_entry_middle_pages,
2075 .single_submap_oversize_entry_at_start = test_single_submap_oversize_entry_at_start,
2076 .single_submap_oversize_entry_at_end = test_single_submap_oversize_entry_at_end,
2077 .single_submap_oversize_entry_at_both = test_single_submap_oversize_entry_at_both,
2078
2079 .submap_before_allocation = test_submap_before_allocation,
2080 .submap_after_allocation = test_submap_after_allocation,
2081 .submap_before_hole = test_submap_before_hole,
2082 .submap_after_hole = test_submap_after_hole,
2083 .submap_allocation_submap_one_entry = test_submap_allocation_submap_one_entry,
2084 .submap_allocation_submap_two_entries = test_submap_allocation_submap_two_entries,
2085 .submap_allocation_submap_three_entries = test_submap_allocation_submap_three_entries,
2086
2087 .submap_before_allocation_ro = test_submap_before_allocation_ro,
2088 .submap_after_allocation_ro = test_submap_after_allocation_ro,
2089 .submap_before_hole_ro = test_submap_before_hole_ro,
2090 .submap_after_hole_ro = test_submap_after_hole_ro,
2091 .submap_allocation_submap_one_entry_ro = test_submap_allocation_submap_one_entry_ro,
2092 .submap_allocation_submap_two_entries_ro = test_submap_allocation_submap_two_entries_ro,
2093 .submap_allocation_submap_three_entries_ro = test_submap_allocation_submap_three_entries_ro,
2094
2095 .protection_single_000_000 = test_protection_single_000_000,
2096 .protection_single_000_r00 = test_protection_single_000_r00,
2097 .protection_single_000_0w0 = test_protection_single_000_0w0,
2098 .protection_single_000_rw0 = test_protection_single_000_rw0,
2099 .protection_single_r00_r00 = test_protection_single_r00_r00,
2100 .protection_single_r00_rw0 = test_protection_single_r00_rw0,
2101 .protection_single_0w0_0w0 = test_protection_single_0w0_0w0,
2102 .protection_single_0w0_rw0 = test_protection_single_0w0_rw0,
2103 .protection_single_rw0_rw0 = test_protection_single_rw0_rw0,
2104
2105 .protection_pairs_000_000 = test_protection_pair_000_000,
2106 .protection_pairs_000_r00 = test_protection_pair_000_r00,
2107 .protection_pairs_000_0w0 = test_protection_pair_000_0w0,
2108 .protection_pairs_000_rw0 = test_protection_pair_000_rw0,
2109 .protection_pairs_r00_000 = test_protection_pair_r00_000,
2110 .protection_pairs_r00_r00 = test_protection_pair_r00_r00,
2111 .protection_pairs_r00_0w0 = test_protection_pair_r00_0w0,
2112 .protection_pairs_r00_rw0 = test_protection_pair_r00_rw0,
2113 .protection_pairs_0w0_000 = test_protection_pair_0w0_000,
2114 .protection_pairs_0w0_r00 = test_protection_pair_0w0_r00,
2115 .protection_pairs_0w0_0w0 = test_protection_pair_0w0_0w0,
2116 .protection_pairs_0w0_rw0 = test_protection_pair_0w0_rw0,
2117 .protection_pairs_rw0_000 = test_protection_pair_rw0_000,
2118 .protection_pairs_rw0_r00 = test_protection_pair_rw0_r00,
2119 .protection_pairs_rw0_0w0 = test_protection_pair_rw0_0w0,
2120 .protection_pairs_rw0_rw0 = test_protection_pair_rw0_rw0,
2121 };
2122
2123 run_vm_tests("test_vm_configurator", __FILE__, &tests, argc, argv);
2124 }
2125