]>
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 | ||
83 | #ifndef KASAN_SHIFT | |
84 | # error KASAN_SHIFT undefined | |
85 | #endif | |
86 | ||
87 | #define ADDRESS_FOR_SHADOW(x) (((x) - KASAN_SHIFT) << 3) | |
88 | #define SHADOW_FOR_ADDRESS(x) (uint8_t *)(((x) >> 3) + KASAN_SHIFT) | |
89 | ||
a39ff7e2 | 90 | #if KASAN_DEBUG |
d9a64523 | 91 | # define NOINLINE OS_NOINLINE |
a39ff7e2 A |
92 | #else |
93 | # define NOINLINE | |
94 | #endif | |
5ba3f43e A |
95 | #define ALWAYS_INLINE inline __attribute__((always_inline)) |
96 | ||
97 | #define CLANG_MIN_VERSION(x) (defined(__apple_build_version__) && (__apple_build_version__ >= (x))) | |
98 | ||
99 | #define BIT(x) (1U << (x)) | |
100 | ||
a39ff7e2 A |
101 | enum __attribute__((flag_enum)) kasan_access_types { |
102 | TYPE_LOAD = BIT(0), /* regular memory load */ | |
103 | TYPE_STORE = BIT(1), /* regular store */ | |
104 | TYPE_MEMR = BIT(2), /* memory intrinsic (read) */ | |
105 | TYPE_MEMW = BIT(3), /* memory intrinsic (write) */ | |
106 | TYPE_STRR = BIT(4), /* string intrinsic (read) */ | |
107 | TYPE_STRW = BIT(5), /* string intrinsic (write) */ | |
108 | TYPE_KFREE = BIT(6), /* kfree() */ | |
109 | TYPE_ZFREE = BIT(7), /* zfree() */ | |
110 | TYPE_FSFREE = BIT(8), /* fakestack free */ | |
111 | ||
112 | TYPE_UAF = BIT(12), | |
113 | TYPE_POISON_GLOBAL = BIT(13), | |
114 | TYPE_POISON_HEAP = BIT(14), | |
115 | /* no TYPE_POISON_STACK, because the runtime does not control stack poisoning */ | |
116 | TYPE_TEST = BIT(15), | |
cb323159 | 117 | TYPE_LEAK = BIT(16), |
5ba3f43e A |
118 | |
119 | /* masks */ | |
0a7de745 A |
120 | TYPE_MEM = TYPE_MEMR | TYPE_MEMW, /* memory intrinsics */ |
121 | TYPE_STR = TYPE_STRR | TYPE_STRW, /* string intrinsics */ | |
122 | TYPE_READ = TYPE_LOAD | TYPE_MEMR | TYPE_STRR, /* all reads */ | |
123 | TYPE_WRITE = TYPE_STORE | TYPE_MEMW | TYPE_STRW, /* all writes */ | |
124 | TYPE_RW = TYPE_READ | TYPE_WRITE, /* reads and writes */ | |
125 | TYPE_FREE = TYPE_KFREE | TYPE_ZFREE | TYPE_FSFREE, | |
126 | TYPE_NORMAL = TYPE_RW | TYPE_FREE, | |
127 | TYPE_DYNAMIC = TYPE_NORMAL | TYPE_UAF, | |
128 | TYPE_POISON = TYPE_POISON_GLOBAL | TYPE_POISON_HEAP, | |
a39ff7e2 | 129 | TYPE_ALL = ~0U, |
5ba3f43e A |
130 | }; |
131 | ||
a39ff7e2 A |
132 | enum kasan_violation_types { |
133 | REASON_POISONED = 0, /* read or write of poisoned data */ | |
134 | REASON_BAD_METADATA = 1, /* incorrect kasan metadata */ | |
135 | REASON_INVALID_SIZE = 2, /* free size did not match alloc size */ | |
136 | REASON_MOD_AFTER_FREE = 3, /* object modified after free */ | |
137 | REASON_MOD_OOB = 4, /* out of bounds modification of object */ | |
cb323159 | 138 | REASON_UNINITIALIZED = 5, /* leak of uninitialized kernel memory */ |
a39ff7e2 A |
139 | }; |
140 | ||
141 | typedef enum kasan_access_types access_t; | |
142 | typedef enum kasan_violation_types violation_t; | |
143 | ||
5ba3f43e | 144 | bool kasan_range_poisoned(vm_offset_t base, vm_size_t size, vm_offset_t *first_invalid); |
a39ff7e2 | 145 | void kasan_check_range(const void *x, size_t sz, access_t); |
5ba3f43e A |
146 | void kasan_test(int testno, int fail); |
147 | void kasan_handle_test(void); | |
5ba3f43e A |
148 | void kasan_free_internal(void **addrp, vm_size_t *sizep, int type, zone_t *, vm_size_t user_size, int locked, bool doquarantine); |
149 | void kasan_poison(vm_offset_t base, vm_size_t size, vm_size_t leftrz, vm_size_t rightrz, uint8_t flags); | |
5ba3f43e A |
150 | void kasan_lock(boolean_t *b); |
151 | void kasan_unlock(boolean_t b); | |
a39ff7e2 | 152 | bool kasan_lock_held(thread_t thread); |
5ba3f43e A |
153 | void kasan_init_fakestack(void); |
154 | ||
155 | /* dynamic blacklist */ | |
156 | void kasan_init_dybl(void); | |
a39ff7e2 | 157 | bool kasan_is_blacklisted(access_t); |
5ba3f43e A |
158 | void kasan_dybl_load_kext(uintptr_t addr, const char *kextname); |
159 | void kasan_dybl_unload_kext(uintptr_t addr); | |
160 | ||
161 | /* arch-specific interface */ | |
162 | void kasan_arch_init(void); | |
a39ff7e2 | 163 | bool kasan_is_shadow_mapped(uintptr_t shadowp); |
5ba3f43e A |
164 | |
165 | extern vm_address_t kernel_vbase; | |
166 | extern vm_address_t kernel_vtop; | |
167 | ||
a39ff7e2 A |
168 | extern unsigned shadow_pages_used; |
169 | ||
170 | /* boot-arg configurable */ | |
171 | extern int fakestack_enabled; | |
5ba3f43e A |
172 | |
173 | /* Describes the source location where a global is defined. */ | |
174 | struct asan_global_source_location { | |
175 | const char *filename; | |
176 | int line_no; | |
177 | int column_no; | |
178 | }; | |
179 | ||
180 | /* Describes an instrumented global variable. */ | |
181 | struct asan_global { | |
182 | uptr addr; | |
183 | uptr size; | |
184 | uptr size_with_redzone; | |
185 | const char *name; | |
186 | const char *module; | |
187 | uptr has_dynamic_init; | |
188 | struct asan_global_source_location *location; | |
189 | #if CLANG_MIN_VERSION(8020000) | |
190 | uptr odr_indicator; | |
191 | #endif | |
192 | }; | |
193 | ||
194 | #if defined(__x86_64__) | |
195 | # define _JBLEN ((9 * 2) + 3 + 16) | |
5c9f4661 A |
196 | #elif defined(__arm64__) |
197 | # define _JBLEN ((14 + 8 + 2) * 2) | |
198 | #else | |
199 | # error "Unknown arch" | |
5ba3f43e A |
200 | #endif |
201 | ||
5ba3f43e | 202 | typedef int jmp_buf[_JBLEN]; |
d9a64523 A |
203 | void _longjmp(jmp_buf env, int val) OS_NORETURN; |
204 | int _setjmp(jmp_buf env) __attribute__((returns_twice)); | |
5ba3f43e A |
205 | |
206 | #endif /* _KASAN_INTERNAL_H_ */ |