xref: /xnu-10002.81.5/san/memory/kasan.h (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1 /*
2  * Copyright (c) 2000-2019 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 #ifndef _KASAN_H_
30 #define _KASAN_H_
31 
32 #if KERNEL_PRIVATE
33 
34 #include <mach/mach_types.h>
35 #include <sys/queue.h>
36 
37 typedef uintptr_t uptr;
38 
39 #if KASAN
40 
41 #if KASAN_CLASSIC
42 #include "kasan-classic.h"
43 #elif KASAN_TBI
44 #include "kasan-tbi.h"
45 #else
46 #error "No kasan model specified"
47 #endif
48 
49 /*
50  * When mapping shadow memory, decide whether the created mapping can be later
51  * updated/poisoned or whether it should just stay marked accessible for its
52  * lifetime (and catch incorrect attempts at poisoning it).
53  *
54  * Consumed by: kasan_map_shadow()
55  */
56 #define KASAN_CANNOT_POISON             true
57 #define KASAN_MAY_POISON                false
58 
59 __BEGIN_DECLS
60 
61 void kasan_map_shadow(vm_offset_t, vm_size_t, bool);
62 
63 /* KASAN enable/disable and general initialization. */
64 void kasan_init(void);
65 void kasan_late_init(void);
66 void kasan_reserve_memory(void *);
67 void kasan_notify_stolen(vm_offset_t);
68 
69 /*
70  * Helper functions to run the necessary initialization and cleanup
71  * at every KEXT load/unload.
72  */
73 void kasan_load_kext(vm_offset_t, vm_size_t, const void *);
74 void kasan_unload_kext(vm_offset_t, vm_size_t);
75 
76 /*
77  * API for the kernel to communicate to KASAN that a new range needs to be
78  * accounted for in the shadow table.
79  */
80 void kasan_notify_address(vm_offset_t, vm_size_t);
81 void kasan_notify_address_nopoison(vm_offset_t, vm_size_t);
82 
83 /*
84  * Control the shadow table state for a given range.
85  */
86 void kasan_poison(vm_offset_t, vm_size_t, vm_size_t, vm_size_t, uint8_t);
87 void kasan_unpoison(void *, vm_size_t);
88 void kasan_poison_range(vm_offset_t, vm_size_t, uint8_t);
89 void kasan_unpoison_stack(vm_offset_t, vm_size_t);
90 void kasan_unpoison_curstack(bool);
91 bool kasan_check_shadow(vm_address_t, vm_size_t, uint8_t);
92 void kasan_unpoison_cxx_array_cookie(void *);
93 
94 /* Fakestack */
95 void kasan_fakestack_drop(thread_t); /* mark all fakestack entries for thread as unused */
96 void kasan_fakestack_gc(thread_t);   /* free and poison all unused fakestack objects for thread */
97 void kasan_fakestack_suspend(void);
98 void kasan_fakestack_resume(void);
99 void kasan_unpoison_fakestack(thread_t);
100 
101 /* KDP support */
102 typedef int (*pmap_traverse_callback)(vm_map_offset_t, vm_map_offset_t, void *);
103 int kasan_traverse_mappings(pmap_traverse_callback, void *);
104 void kasan_kdp_disable(void);
105 
106 /* Tests API */
107 struct kasan_test {
108 	int (* func)(struct kasan_test *);
109 	void (* cleanup)(struct kasan_test *);
110 	const char *name;
111 	int result;
112 	void *data;
113 	size_t datasz;
114 };
115 void __kasan_runtests(struct kasan_test *, int numtests);
116 
117 #if XNU_KERNEL_PRIVATE
118 extern unsigned shadow_pages_total;
119 
120 #if __arm64__
121 void kasan_notify_address_zero(vm_offset_t, vm_size_t);
122 #elif __x86_64__
123 extern void kasan_map_low_fixed_regions(void);
124 extern unsigned shadow_stolen_idx;
125 #endif /* __arm64__ */
126 
127 #endif /* XNU_KERNEL_PRIVATE */
128 
129 #if HIBERNATION
130 /*
131  * hibernate_write_image() needs to know the current extent of the shadow table
132  */
133 extern vm_offset_t shadow_pnext, shadow_ptop;
134 #endif /* HIBERNATION */
135 
136 /* thread interface */
137 struct kasan_thread_data {
138 	LIST_HEAD(fakestack_header_list, fakestack_header) fakestack_head;
139 };
140 struct kasan_thread_data *kasan_get_thread_data(thread_t);
141 void kasan_init_thread(struct kasan_thread_data *);
142 
143 /*
144  * ASAN callbacks - inserted by the compiler
145  */
146 
147 extern int __asan_option_detect_stack_use_after_return;
148 extern const uintptr_t __asan_shadow_memory_dynamic_address;
149 
150 #define KASAN_DECLARE_FOREACH_WIDTH(ret, func, ...) \
151 	ret func ## 1(__VA_ARGS__); \
152 	ret func ## 2(__VA_ARGS__); \
153 	ret func ## 4(__VA_ARGS__); \
154 	ret func ## 8(__VA_ARGS__); \
155 	ret func ## 16(__VA_ARGS__)
156 
157 KASAN_DECLARE_FOREACH_WIDTH(void, __asan_report_load, uptr);
158 KASAN_DECLARE_FOREACH_WIDTH(void, __asan_report_store, uptr);
159 KASAN_DECLARE_FOREACH_WIDTH(void, __asan_store, uptr);
160 KASAN_DECLARE_FOREACH_WIDTH(void, __asan_report_exp_load, uptr, int32_t);
161 KASAN_DECLARE_FOREACH_WIDTH(void, __asan_report_exp_store, uptr, int32_t);
162 KASAN_DECLARE_FOREACH_WIDTH(void, __asan_exp_load, uptr, int32_t);
163 KASAN_DECLARE_FOREACH_WIDTH(void, __asan_exp_store, uptr, int32_t);
164 KASAN_DECLARE_FOREACH_WIDTH(void, __asan_load, uptr);
165 
166 void __asan_report_load_n(uptr, unsigned long);
167 void __asan_report_store_n(uptr, unsigned long);
168 void __asan_handle_no_return(void);
169 uptr __asan_stack_malloc_0(size_t);
170 uptr __asan_stack_malloc_1(size_t);
171 uptr __asan_stack_malloc_2(size_t);
172 uptr __asan_stack_malloc_3(size_t);
173 uptr __asan_stack_malloc_4(size_t);
174 uptr __asan_stack_malloc_5(size_t);
175 uptr __asan_stack_malloc_6(size_t);
176 uptr __asan_stack_malloc_7(size_t);
177 uptr __asan_stack_malloc_8(size_t);
178 uptr __asan_stack_malloc_9(size_t);
179 uptr __asan_stack_malloc_10(size_t);
180 void __asan_stack_free_0(uptr, size_t);
181 void __asan_stack_free_1(uptr, size_t);
182 void __asan_stack_free_2(uptr, size_t);
183 void __asan_stack_free_3(uptr, size_t);
184 void __asan_stack_free_4(uptr, size_t);
185 void __asan_stack_free_5(uptr, size_t);
186 void __asan_stack_free_6(uptr, size_t);
187 void __asan_stack_free_7(uptr, size_t);
188 void __asan_stack_free_8(uptr, size_t);
189 void __asan_stack_free_9(uptr, size_t);
190 void __asan_stack_free_10(uptr, size_t);
191 void __asan_poison_cxx_array_cookie(uptr);
192 uptr __asan_load_cxx_array_cookie(uptr *);
193 void __asan_poison_stack_memory(uptr, size_t);
194 void __asan_unpoison_stack_memory(uptr, size_t);
195 void __asan_alloca_poison(uptr, uptr);
196 void __asan_allocas_unpoison(uptr, uptr);
197 void __asan_loadN(uptr, size_t);
198 void __asan_storeN(uptr, size_t);
199 void __sanitizer_ptr_sub(uptr, uptr);
200 void __sanitizer_ptr_cmp(uptr, uptr);
201 void __sanitizer_annotate_contiguous_container(const void *, const void *,
202     const void *, const void *n);
203 
204 void __asan_exp_loadN(uptr, size_t, int32_t);
205 void __asan_exp_storeN(uptr, size_t, int32_t);
206 void __asan_report_exp_load_n(uptr, unsigned long, int32_t);
207 void __asan_report_exp_store_n(uptr, unsigned long, int32_t);
208 
209 void __asan_set_shadow_00(uptr, size_t);
210 void __asan_set_shadow_f1(uptr, size_t);
211 void __asan_set_shadow_f2(uptr, size_t);
212 void __asan_set_shadow_f3(uptr, size_t);
213 void __asan_set_shadow_f5(uptr, size_t);
214 void __asan_set_shadow_f8(uptr, size_t);
215 
216 void __asan_init_v5(void);
217 void __asan_register_globals(uptr, uptr);
218 void __asan_unregister_globals(uptr, uptr);
219 void __asan_register_elf_globals(uptr, uptr, uptr);
220 void __asan_unregister_elf_globals(uptr, uptr, uptr);
221 
222 void __asan_before_dynamic_init(uptr);
223 void __asan_after_dynamic_init(void);
224 void __asan_init(void);
225 void __asan_unregister_image_globals(uptr);
226 void __asan_register_image_globals(uptr);
227 
228 void __hwasan_tag_memory(uintptr_t, unsigned char, uintptr_t);
229 unsigned char __hwasan_generate_tag(void);
230 
231 __END_DECLS
232 
233 #endif /* KASAN */
234 
235 #if __has_feature(address_sanitizer)
236 #define NOKASAN __attribute__ ((no_sanitize_address))
237 #elif __has_feature(hwaddress_sanitizer)
238 #define NOKASAN __attribute__((no_sanitize("kernel-hwaddress")))
239 #else /* address_sanitizer || hwaddress_sanitizer */
240 #define NOKASAN
241 #endif
242 
243 /*
244  * KASAN provides a description of each global variable in the
245  * __DATA.__asan_globals section. This description is walked for xnu at boot
246  * and at each KEXT load/unload operation, to allow the KASAN implementation
247  * to perform the necessary redzoning around each variable.
248  *
249  * Consumed in OSKext.cpp, so must stay outside KASAN-specific defines.
250  */
251 #define KASAN_GLOBAL_SEGNAME  "__DATA"
252 #define KASAN_GLOBAL_SECTNAME "__asan_globals"
253 
254 #endif /* KERNEL_PRIVATE */
255 #endif /* _KASAN_H_ */
256