1 /*
2 * Copyright (c) 2021 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 * This file contains all the necessary helpers that the compiler
31 * instrumentation inserts for KASAN. Due to the way the INSTALL phase is
32 * performed in our build system, it's non-trivial to support independent
33 * .exports for System.kext, therefore we take the easy way out and have
34 * a common set of exports between KASAN-CLASSIC (asan based) and KASAN-TBI
35 * (hwasan based). This also simplifies any backward compatibility without
36 * requiring to duplicate symbols.
37 *
38 * For checking and reporting functions, KASAN-TBI is built with
39 * -mllvm -hwasan-memory-access-callback-prefix="___asan" which allows to
40 * commonize the implementation. This also imposes that KASAN-CLASSIC and
41 * KASAN-TBI agree on the definition of access types (TYPE_LOAD/TYPE_STORE),
42 * which is a fair requirement.
43 *
44 * NOTE: there is a vast predominance of asan symbols due to the original
45 * implementation being based on the userland address sanitizer. For hwasan,
46 * the kernel-hwaddress sanitizer already strips out a non-trivial amount
47 * of non-kernel-applicable instrumentation/APIs.
48 */
49
50 #include <libkern/libkern.h>
51 #include "kasan.h"
52 #include "kasan_internal.h"
53
54
55
56 /* Report and checking for any size-based access. */
57 #define REPORT_DECLARE(n) \
58 void OS_NORETURN __asan_report_load##n(uptr p) { kasan_crash_report(p, n, TYPE_LOAD, 0); } \
59 void OS_NORETURN __asan_report_store##n(uptr p) { kasan_crash_report(p, n, TYPE_STORE, 0); } \
60 void OS_NORETURN UNSUPPORTED_API(__asan_report_exp_load##n, uptr a, int32_t b); \
61 void OS_NORETURN UNSUPPORTED_API(__asan_report_exp_store##n, uptr a, int32_t b);
62
63 REPORT_DECLARE(1)
64 REPORT_DECLARE(2)
65 REPORT_DECLARE(4)
66 REPORT_DECLARE(8)
67 REPORT_DECLARE(16)
68
69 void OS_NORETURN
__asan_report_load_n(uptr p,unsigned long sz)70 __asan_report_load_n(uptr p, unsigned long sz)
71 {
72 kasan_crash_report(p, sz, TYPE_LOAD, 0);
73 }
74 void OS_NORETURN
__asan_report_store_n(uptr p,unsigned long sz)75 __asan_report_store_n(uptr p, unsigned long sz)
76 {
77 kasan_crash_report(p, sz, TYPE_STORE, 0);
78 }
79
80 #define ACCESS_CHECK_DECLARE(type, sz, access) \
81 void __asan_##type##sz(uptr addr) { \
82 kasan_check_range((const void *)addr, sz, access); \
83 } \
84 void OS_NORETURN UNSUPPORTED_API(__asan_exp_##type##sz, uptr a, int32_t b);
85
86 #define ACCESS_CHECK_DECLARE(type, sz, access) \
87 void __asan_##type##sz(uptr addr) { \
88 kasan_check_range((const void *)addr, sz, access); \
89 } \
90 void OS_NORETURN UNSUPPORTED_API(__asan_exp_##type##sz, uptr a, int32_t b);
91
92 ACCESS_CHECK_DECLARE(load, 1, TYPE_LOAD);
93 ACCESS_CHECK_DECLARE(load, 2, TYPE_LOAD);
94 ACCESS_CHECK_DECLARE(load, 4, TYPE_LOAD);
95 ACCESS_CHECK_DECLARE(load, 8, TYPE_LOAD);
96 ACCESS_CHECK_DECLARE(load, 16, TYPE_LOAD);
97 ACCESS_CHECK_DECLARE(store, 1, TYPE_STORE);
98 ACCESS_CHECK_DECLARE(store, 2, TYPE_STORE);
99 ACCESS_CHECK_DECLARE(store, 4, TYPE_STORE);
100 ACCESS_CHECK_DECLARE(store, 8, TYPE_STORE);
101 ACCESS_CHECK_DECLARE(store, 16, TYPE_STORE);
102
103 void
__asan_loadN(uptr addr,size_t sz)104 __asan_loadN(uptr addr, size_t sz)
105 {
106 kasan_check_range((const void *)addr, sz, TYPE_LOAD);
107 }
108
109 void
__asan_storeN(uptr addr,size_t sz)110 __asan_storeN(uptr addr, size_t sz)
111 {
112 kasan_check_range((const void *)addr, sz, TYPE_STORE);
113 }
114
115 static void
kasan_set_shadow(uptr addr,size_t sz,uint8_t val)116 kasan_set_shadow(uptr addr, size_t sz, uint8_t val)
117 {
118 __nosan_memset((void *)addr, val, sz);
119 }
120
121 #define SET_SHADOW_DECLARE(val) \
122 void __asan_set_shadow_##val(uptr addr, size_t sz) { \
123 kasan_set_shadow(addr, sz, 0x##val); \
124 }
125
126 SET_SHADOW_DECLARE(00)
SET_SHADOW_DECLARE(f1)127 SET_SHADOW_DECLARE(f1)
128 SET_SHADOW_DECLARE(f2)
129 SET_SHADOW_DECLARE(f3)
130 SET_SHADOW_DECLARE(f5)
131 SET_SHADOW_DECLARE(f8)
132
133 #if KASAN_CLASSIC
134 #include "kasan-classic.h"
135
136 uptr
137 __asan_load_cxx_array_cookie(uptr *p)
138 {
139 uint8_t *shadow = SHADOW_FOR_ADDRESS((uptr)p);
140 if (*shadow == ASAN_ARRAY_COOKIE) {
141 return *p;
142 } else if (*shadow == ASAN_HEAP_FREED) {
143 return 0;
144 } else {
145 return *p;
146 }
147 }
148
149 void
__asan_poison_cxx_array_cookie(uptr p)150 __asan_poison_cxx_array_cookie(uptr p)
151 {
152 uint8_t *shadow = SHADOW_FOR_ADDRESS(p);
153 *shadow = ASAN_ARRAY_COOKIE;
154 }
155
156 unsigned char
__hwasan_generate_tag()157 __hwasan_generate_tag()
158 {
159 return 0;
160 }
161
162 void
__hwasan_tag_memory(uintptr_t __unused p,unsigned char __unused tag,uintptr_t __unused sz)163 __hwasan_tag_memory(uintptr_t __unused p, unsigned char __unused tag, uintptr_t __unused sz)
164 {
165 }
166 #else /* KASAN_CLASSIC */
167 uptr
168 __asan_load_cxx_array_cookie(uptr __unused *p)
169 {
170 return 0;
171 }
172
173 void
174 __asan_poison_cxx_array_cookie(uptr __unused p)
175 {
176 }
177 #endif /* KASAN_CLASSIC */
178
179 /*
180 * Unused ABI.
181 *
182 * These symbols must be present for KASAN to work correctly and for some
183 * external dependency tool to operate properly. E.g. Vortex relies on
184 * asan_init() being defined to identify a KASAN artifact.
185 */
186 #define UNUSED_ABI(func, ...) \
187 _Pragma("clang diagnostic push") \
188 _Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \
189 void func(__VA_ARGS__); \
190 void func(__VA_ARGS__) {}; \
191 _Pragma("clang diagnostic pop")
192
193 UNUSED_ABI(__asan_alloca_poison, uptr addr, uptr size);
194 UNUSED_ABI(__asan_allocas_unpoison, uptr top, uptr bottom);
195 UNUSED_ABI(__sanitizer_ptr_sub, uptr a, uptr b);
196 UNUSED_ABI(__sanitizer_ptr_cmp, uptr a, uptr b);
197 UNUSED_ABI(__sanitizer_annotate_contiguous_container, const void *a, const void *b, const void *c, const void *d);
198 UNUSED_ABI(__asan_poison_stack_memory, uptr addr, size_t size);
199 UNUSED_ABI(__asan_unpoison_stack_memory, uptr a, uptr b);
200 UNUSED_ABI(__asan_init, void);
201 UNUSED_ABI(__asan_register_image_globals, uptr a);
202 UNUSED_ABI(__asan_unregister_image_globals, uptr a);
203 UNUSED_ABI(__asan_before_dynamic_init, uptr a);
204 UNUSED_ABI(__asan_after_dynamic_init, void);
205 UNUSED_ABI(__asan_version_mismatch_check_v8, void);
206 UNUSED_ABI(__asan_version_mismatch_check_apple_802, void);
207 UNUSED_ABI(__asan_version_mismatch_check_apple_900, void);
208 UNUSED_ABI(__asan_version_mismatch_check_apple_902, void);
209 UNUSED_ABI(__asan_version_mismatch_check_apple_1000, void);
210 UNUSED_ABI(__asan_version_mismatch_check_apple_1001, void);
211 UNUSED_ABI(__asan_version_mismatch_check_apple_clang_1100, void);
212 UNUSED_ABI(__asan_version_mismatch_check_apple_clang_1200, void);
213
214 /* Panic if any of those is inserted by the instrumentation. */
215 void OS_NORETURN UNSUPPORTED_API(__asan_init_v5, void);
216 void OS_NORETURN UNSUPPORTED_API(__asan_register_globals, uptr a, uptr b);
217 void OS_NORETURN UNSUPPORTED_API(__asan_unregister_globals, uptr a, uptr b);
218 void OS_NORETURN UNSUPPORTED_API(__asan_register_elf_globals, uptr a, uptr b, uptr c);
219 void OS_NORETURN UNSUPPORTED_API(__asan_unregister_elf_globals, uptr a, uptr b, uptr c);
220 void OS_NORETURN UNSUPPORTED_API(__asan_exp_loadN, uptr addr, size_t sz, int32_t e);
221 void OS_NORETURN UNSUPPORTED_API(__asan_exp_storeN, uptr addr, size_t sz, int32_t e);
222 void OS_NORETURN UNSUPPORTED_API(__asan_report_exp_load_n, uptr addr, unsigned long b, int32_t c);
223 void OS_NORETURN UNSUPPORTED_API(__asan_report_exp_store_n, uptr addr, unsigned long b, int32_t c);
224