]>
Commit | Line | Data |
---|---|---|
5ba3f43e A |
1 | /* |
2 | * Copyright (c) 2000-2014 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_INTERNAL_H_ | |
30 | #define _KASAN_INTERNAL_H_ | |
31 | ||
32 | #include <stdbool.h> | |
33 | #include <mach/mach_vm.h> | |
34 | #include <kern/zalloc.h> | |
35 | ||
36 | typedef uintptr_t uptr; | |
37 | ||
5c9f4661 A |
38 | #define MiB(x) ((x) * 1024UL * 1024) |
39 | ||
5ba3f43e A |
40 | /* |
41 | * KASAN features and config | |
42 | */ | |
5ba3f43e | 43 | #define FAKESTACK 1 |
5ba3f43e A |
44 | /* KASAN_KALLOC defined in kasan.h */ |
45 | /* KASAN_ZALLOC defined in kasan.h */ | |
46 | #define FAKESTACK_QUARANTINE (1 && FAKESTACK) | |
47 | ||
48 | #define QUARANTINE_ENTRIES 5000 | |
5c9f4661 A |
49 | #define QUARANTINE_MAXSIZE MiB(10) |
50 | ||
51 | /* | |
52 | * The amount of physical memory stolen by KASan at boot to back the shadow memory | |
53 | * and page tables. Larger memory systems need to steal proportionally less. | |
54 | */ | |
55 | #ifdef __arm64__ | |
56 | /* Works out at about 25% of 512 MiB and 15% of 3GiB system */ | |
57 | # define STOLEN_MEM_PERCENT 13UL | |
0a7de745 | 58 | # define STOLEN_MEM_BYTES MiB(40) |
d9a64523 A |
59 | # define HW_PAGE_SIZE (ARM_PGBYTES) |
60 | # define HW_PAGE_MASK (ARM_PGMASK) | |
5c9f4661 A |
61 | #else |
62 | # define STOLEN_MEM_PERCENT 25UL | |
63 | # define STOLEN_MEM_BYTES 0 | |
d9a64523 A |
64 | # define HW_PAGE_SIZE (PAGE_SIZE) |
65 | # define HW_PAGE_MASK (PAGE_MASK) | |
5c9f4661 | 66 | #endif |
5ba3f43e | 67 | |
a39ff7e2 A |
68 | /* boot-args */ |
69 | #define KASAN_ARGS_FAKESTACK 0x0010U | |
70 | #define KASAN_ARGS_REPORTIGNORED 0x0020U | |
71 | #define KASAN_ARGS_NODYCHECKS 0x0100U | |
72 | #define KASAN_ARGS_NOPOISON_HEAP 0x0200U | |
73 | #define KASAN_ARGS_NOPOISON_GLOBAL 0x0400U | |
cb323159 A |
74 | #define KASAN_ARGS_CHECK_LEAKS 0x0800U |
75 | ||
76 | /* uninitialized memory detection */ | |
77 | #define KASAN_UNINITIALIZED_HEAP 0xbe | |
a39ff7e2 | 78 | |
5ba3f43e A |
79 | #ifndef KASAN |
80 | # error KASAN undefined | |
81 | #endif | |
82 | ||
f427ee49 A |
83 | #ifndef KASAN_OFFSET |
84 | # error KASAN_OFFSET undefined | |
5ba3f43e A |
85 | #endif |
86 | ||
f427ee49 A |
87 | #ifndef KASAN_SCALE |
88 | # error KASAN_SCALE undefined | |
89 | #endif | |
90 | ||
91 | #define KASAN_GRANULE (1UL << KASAN_SCALE) | |
92 | #define KASAN_GRANULE_MASK (KASAN_GRANULE - 1UL) | |
93 | ||
94 | static inline uintptr_t | |
95 | kasan_granule_trunc(uintptr_t x) | |
96 | { | |
97 | return x & ~KASAN_GRANULE_MASK; | |
98 | } | |
99 | ||
100 | static inline uintptr_t | |
101 | kasan_granule_round(uintptr_t x) | |
102 | { | |
103 | return (x + KASAN_GRANULE_MASK) & ~KASAN_GRANULE_MASK; | |
104 | } | |
105 | ||
106 | static inline size_t | |
107 | kasan_granule_partial(uintptr_t x) | |
108 | { | |
109 | return x & KASAN_GRANULE_MASK; | |
110 | } | |
111 | ||
112 | #define ADDRESS_FOR_SHADOW(x) (((x) - KASAN_OFFSET) << KASAN_SCALE) | |
113 | #define SHADOW_FOR_ADDRESS(x) (uint8_t *)(((x) >> KASAN_SCALE) + KASAN_OFFSET) | |
5ba3f43e | 114 | |
a39ff7e2 | 115 | #if KASAN_DEBUG |
d9a64523 | 116 | # define NOINLINE OS_NOINLINE |
a39ff7e2 A |
117 | #else |
118 | # define NOINLINE | |
119 | #endif | |
5ba3f43e A |
120 | #define ALWAYS_INLINE inline __attribute__((always_inline)) |
121 | ||
122 | #define CLANG_MIN_VERSION(x) (defined(__apple_build_version__) && (__apple_build_version__ >= (x))) | |
123 | ||
124 | #define BIT(x) (1U << (x)) | |
125 | ||
a39ff7e2 A |
126 | enum __attribute__((flag_enum)) kasan_access_types { |
127 | TYPE_LOAD = BIT(0), /* regular memory load */ | |
128 | TYPE_STORE = BIT(1), /* regular store */ | |
129 | TYPE_MEMR = BIT(2), /* memory intrinsic (read) */ | |
130 | TYPE_MEMW = BIT(3), /* memory intrinsic (write) */ | |
131 | TYPE_STRR = BIT(4), /* string intrinsic (read) */ | |
132 | TYPE_STRW = BIT(5), /* string intrinsic (write) */ | |
133 | TYPE_KFREE = BIT(6), /* kfree() */ | |
134 | TYPE_ZFREE = BIT(7), /* zfree() */ | |
135 | TYPE_FSFREE = BIT(8), /* fakestack free */ | |
136 | ||
137 | TYPE_UAF = BIT(12), | |
138 | TYPE_POISON_GLOBAL = BIT(13), | |
139 | TYPE_POISON_HEAP = BIT(14), | |
140 | /* no TYPE_POISON_STACK, because the runtime does not control stack poisoning */ | |
141 | TYPE_TEST = BIT(15), | |
cb323159 | 142 | TYPE_LEAK = BIT(16), |
5ba3f43e A |
143 | |
144 | /* masks */ | |
0a7de745 A |
145 | TYPE_MEM = TYPE_MEMR | TYPE_MEMW, /* memory intrinsics */ |
146 | TYPE_STR = TYPE_STRR | TYPE_STRW, /* string intrinsics */ | |
147 | TYPE_READ = TYPE_LOAD | TYPE_MEMR | TYPE_STRR, /* all reads */ | |
148 | TYPE_WRITE = TYPE_STORE | TYPE_MEMW | TYPE_STRW, /* all writes */ | |
149 | TYPE_RW = TYPE_READ | TYPE_WRITE, /* reads and writes */ | |
150 | TYPE_FREE = TYPE_KFREE | TYPE_ZFREE | TYPE_FSFREE, | |
151 | TYPE_NORMAL = TYPE_RW | TYPE_FREE, | |
152 | TYPE_DYNAMIC = TYPE_NORMAL | TYPE_UAF, | |
153 | TYPE_POISON = TYPE_POISON_GLOBAL | TYPE_POISON_HEAP, | |
a39ff7e2 | 154 | TYPE_ALL = ~0U, |
5ba3f43e A |
155 | }; |
156 | ||
a39ff7e2 A |
157 | enum kasan_violation_types { |
158 | REASON_POISONED = 0, /* read or write of poisoned data */ | |
159 | REASON_BAD_METADATA = 1, /* incorrect kasan metadata */ | |
160 | REASON_INVALID_SIZE = 2, /* free size did not match alloc size */ | |
161 | REASON_MOD_AFTER_FREE = 3, /* object modified after free */ | |
162 | REASON_MOD_OOB = 4, /* out of bounds modification of object */ | |
cb323159 | 163 | REASON_UNINITIALIZED = 5, /* leak of uninitialized kernel memory */ |
a39ff7e2 A |
164 | }; |
165 | ||
166 | typedef enum kasan_access_types access_t; | |
167 | typedef enum kasan_violation_types violation_t; | |
168 | ||
5ba3f43e | 169 | bool kasan_range_poisoned(vm_offset_t base, vm_size_t size, vm_offset_t *first_invalid); |
a39ff7e2 | 170 | void kasan_check_range(const void *x, size_t sz, access_t); |
5ba3f43e A |
171 | void kasan_test(int testno, int fail); |
172 | void kasan_handle_test(void); | |
5ba3f43e A |
173 | void kasan_free_internal(void **addrp, vm_size_t *sizep, int type, zone_t *, vm_size_t user_size, int locked, bool doquarantine); |
174 | void kasan_poison(vm_offset_t base, vm_size_t size, vm_size_t leftrz, vm_size_t rightrz, uint8_t flags); | |
5ba3f43e A |
175 | void kasan_lock(boolean_t *b); |
176 | void kasan_unlock(boolean_t b); | |
a39ff7e2 | 177 | bool kasan_lock_held(thread_t thread); |
5ba3f43e A |
178 | void kasan_init_fakestack(void); |
179 | ||
180 | /* dynamic blacklist */ | |
181 | void kasan_init_dybl(void); | |
a39ff7e2 | 182 | bool kasan_is_blacklisted(access_t); |
5ba3f43e A |
183 | void kasan_dybl_load_kext(uintptr_t addr, const char *kextname); |
184 | void kasan_dybl_unload_kext(uintptr_t addr); | |
185 | ||
186 | /* arch-specific interface */ | |
187 | void kasan_arch_init(void); | |
a39ff7e2 | 188 | bool kasan_is_shadow_mapped(uintptr_t shadowp); |
5ba3f43e A |
189 | |
190 | extern vm_address_t kernel_vbase; | |
191 | extern vm_address_t kernel_vtop; | |
192 | ||
a39ff7e2 A |
193 | extern unsigned shadow_pages_used; |
194 | ||
195 | /* boot-arg configurable */ | |
196 | extern int fakestack_enabled; | |
5ba3f43e A |
197 | |
198 | /* Describes the source location where a global is defined. */ | |
199 | struct asan_global_source_location { | |
200 | const char *filename; | |
201 | int line_no; | |
202 | int column_no; | |
203 | }; | |
204 | ||
205 | /* Describes an instrumented global variable. */ | |
206 | struct asan_global { | |
207 | uptr addr; | |
208 | uptr size; | |
209 | uptr size_with_redzone; | |
210 | const char *name; | |
211 | const char *module; | |
212 | uptr has_dynamic_init; | |
213 | struct asan_global_source_location *location; | |
214 | #if CLANG_MIN_VERSION(8020000) | |
215 | uptr odr_indicator; | |
216 | #endif | |
217 | }; | |
218 | ||
219 | #if defined(__x86_64__) | |
220 | # define _JBLEN ((9 * 2) + 3 + 16) | |
5c9f4661 A |
221 | #elif defined(__arm64__) |
222 | # define _JBLEN ((14 + 8 + 2) * 2) | |
223 | #else | |
224 | # error "Unknown arch" | |
5ba3f43e A |
225 | #endif |
226 | ||
5ba3f43e | 227 | typedef int jmp_buf[_JBLEN]; |
d9a64523 A |
228 | void _longjmp(jmp_buf env, int val) OS_NORETURN; |
229 | int _setjmp(jmp_buf env) __attribute__((returns_twice)); | |
5ba3f43e A |
230 | |
231 | #endif /* _KASAN_INTERNAL_H_ */ |