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_helpers.h
31 *
32 * Assorted functions used by multiple vm_configurator tests.
33 */
34
35 #ifndef VM_CONFIGURATOR_HELPERS_H
36 #define VM_CONFIGURATOR_HELPERS_H
37
38 #include "vm_configurator.h"
39
40 /*
41 * Clear some bits from EXC_GUARD behavior, then set some bits.
42 * Halt with T_FAIL if task_get/set_exc_guard_behavior() fails.
43 */
44 static inline void
clear_then_set_exc_guard_behavior(task_exc_guard_behavior_t clear,task_exc_guard_behavior_t set)45 clear_then_set_exc_guard_behavior(
46 task_exc_guard_behavior_t clear,
47 task_exc_guard_behavior_t set)
48 {
49 task_exc_guard_behavior_t behavior;
50 kern_return_t kr = task_get_exc_guard_behavior(mach_task_self(), &behavior);
51 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "get EXC_GUARD behavior");
52
53 behavior &= ~clear;
54 behavior |= set;
55
56 kr = task_set_exc_guard_behavior(mach_task_self(), behavior);
57 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "update EXC_GUARD behavior");
58 }
59
60 /*
61 * Disable VM EXC_GUARD exceptions.
62 * Halt with T_FAIL if they cannot be disabled.
63 */
64 static inline void
disable_vm_exc_guard(void)65 disable_vm_exc_guard(void)
66 {
67 clear_then_set_exc_guard_behavior(
68 TASK_EXC_GUARD_VM_ALL, /* clear */
69 0 /* set */);
70 }
71
72 /*
73 * Enable VM EXC_GUARD fatal exceptions.
74 * Halt with T_FAIL if they cannot be enabled.
75 */
76 static inline void
enable_fatal_vm_exc_guard(void)77 enable_fatal_vm_exc_guard(void)
78 {
79 clear_then_set_exc_guard_behavior(
80 TASK_EXC_GUARD_VM_ALL, /* clear */
81 TASK_EXC_GUARD_VM_DELIVER | TASK_EXC_GUARD_VM_FATAL /* set */);
82 }
83
84 /*
85 * Enable VM EXC_GUARD non-fatal exceptions.
86 * Halt with T_FAIL if they cannot be enabled.
87 */
88 static inline void
enable_non_fatal_vm_exc_guard(void)89 enable_non_fatal_vm_exc_guard(void)
90 {
91 clear_then_set_exc_guard_behavior(
92 TASK_EXC_GUARD_VM_ALL, /* clear */
93 TASK_EXC_GUARD_VM_DELIVER /* set */);
94 }
95
96 /*
97 * Update the checker list after a successful call to vm_deallocate()
98 * of any number of ordinary allocations and holes.
99 * Don't use this if anything may be permanent entries.
100 */
101 static inline void
checker_perform_successful_vm_deallocate(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)102 checker_perform_successful_vm_deallocate(
103 checker_list_t *checker_list,
104 mach_vm_address_t start,
105 mach_vm_size_t size)
106 {
107 /* this may create adjacent hole checkers, but we don't care */
108 entry_checker_range_t limit =
109 checker_list_find_and_clip_including_holes(checker_list, start, size);
110 checker_list_free_range(checker_list, limit);
111 }
112
113 /*
114 * Update the checker list after a successful call to vm_allocate()
115 * of a permanent entry, which makes the memory inaccessible.
116 * On entry, the range must be a single checker for a permanent allocation.
117 */
118 static inline void
checker_perform_vm_deallocate_permanent(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)119 checker_perform_vm_deallocate_permanent(
120 checker_list_t *checker_list,
121 mach_vm_address_t start,
122 mach_vm_size_t size)
123 {
124 /* Find the checker and verify its address range and permanence. */
125 vm_entry_checker_t *checker =
126 checker_list_find_allocation(checker_list, start);
127 assert(checker);
128 assert(checker->address == start);
129 assert(checker->size == size);
130 assert(checker->permanent == true);
131
132 /* Mark the memory as inaccessible. */
133 checker->protection = VM_PROT_NONE;
134 checker->max_protection = VM_PROT_NONE;
135 }
136
137 #endif /* VM_CONFIGURATOR_HELPERS_H */
138