| @@ -1,1142 +1,1245 @@ | | | @@ -1,1142 +1,1245 @@ |
1 | /* $NetBSD: subr_asan.c,v 1.15 2019/10/04 06:27:42 maxv Exp $ */ | | 1 | /* $NetBSD: subr_asan.c,v 1.16 2019/10/10 13:45:14 maxv Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2018-2019 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2018-2019 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Maxime Villard. | | 8 | * by Maxime Villard. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.15 2019/10/04 06:27:42 maxv Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.16 2019/10/10 13:45:14 maxv Exp $"); |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <sys/device.h> | | 36 | #include <sys/device.h> |
37 | #include <sys/kernel.h> | | 37 | #include <sys/kernel.h> |
38 | #include <sys/param.h> | | 38 | #include <sys/param.h> |
39 | #include <sys/conf.h> | | 39 | #include <sys/conf.h> |
40 | #include <sys/systm.h> | | 40 | #include <sys/systm.h> |
41 | #include <sys/types.h> | | 41 | #include <sys/types.h> |
42 | #include <sys/asan.h> | | 42 | #include <sys/asan.h> |
43 | | | 43 | |
44 | #include <uvm/uvm.h> | | 44 | #include <uvm/uvm.h> |
45 | | | 45 | |
46 | #ifdef KASAN_PANIC | | 46 | #ifdef KASAN_PANIC |
47 | #define REPORT panic | | 47 | #define REPORT panic |
48 | #else | | 48 | #else |
49 | #define REPORT printf | | 49 | #define REPORT printf |
50 | #endif | | 50 | #endif |
51 | | | 51 | |
52 | /* ASAN constants. Part of the compiler ABI. */ | | 52 | /* ASAN constants. Part of the compiler ABI. */ |
53 | #define KASAN_SHADOW_SCALE_SHIFT 3 | | 53 | #define KASAN_SHADOW_SCALE_SHIFT 3 |
54 | #define KASAN_SHADOW_SCALE_SIZE (1UL << KASAN_SHADOW_SCALE_SHIFT) | | 54 | #define KASAN_SHADOW_SCALE_SIZE (1UL << KASAN_SHADOW_SCALE_SHIFT) |
55 | #define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE_SIZE - 1) | | 55 | #define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE_SIZE - 1) |
56 | | | 56 | |
57 | /* The MD code. */ | | 57 | /* The MD code. */ |
58 | #include <machine/asan.h> | | 58 | #include <machine/asan.h> |
59 | | | 59 | |
60 | /* ASAN ABI version. */ | | 60 | /* ASAN ABI version. */ |
61 | #if defined(__clang__) && (__clang_major__ - 0 >= 6) | | 61 | #if defined(__clang__) && (__clang_major__ - 0 >= 6) |
62 | #define ASAN_ABI_VERSION 8 | | 62 | #define ASAN_ABI_VERSION 8 |
63 | #elif __GNUC_PREREQ__(7, 1) && !defined(__clang__) | | 63 | #elif __GNUC_PREREQ__(7, 1) && !defined(__clang__) |
64 | #define ASAN_ABI_VERSION 8 | | 64 | #define ASAN_ABI_VERSION 8 |
65 | #elif __GNUC_PREREQ__(6, 1) && !defined(__clang__) | | 65 | #elif __GNUC_PREREQ__(6, 1) && !defined(__clang__) |
66 | #define ASAN_ABI_VERSION 6 | | 66 | #define ASAN_ABI_VERSION 6 |
67 | #else | | 67 | #else |
68 | #error "Unsupported compiler version" | | 68 | #error "Unsupported compiler version" |
69 | #endif | | 69 | #endif |
70 | | | 70 | |
71 | #define __RET_ADDR (unsigned long)__builtin_return_address(0) | | 71 | #define __RET_ADDR (unsigned long)__builtin_return_address(0) |
72 | | | 72 | |
73 | /* Global variable descriptor. Part of the compiler ABI. */ | | 73 | /* Global variable descriptor. Part of the compiler ABI. */ |
74 | struct __asan_global_source_location { | | 74 | struct __asan_global_source_location { |
75 | const char *filename; | | 75 | const char *filename; |
76 | int line_no; | | 76 | int line_no; |
77 | int column_no; | | 77 | int column_no; |
78 | }; | | 78 | }; |
79 | struct __asan_global { | | 79 | struct __asan_global { |
80 | const void *beg; /* address of the global variable */ | | 80 | const void *beg; /* address of the global variable */ |
81 | size_t size; /* size of the global variable */ | | 81 | size_t size; /* size of the global variable */ |
82 | size_t size_with_redzone; /* size with the redzone */ | | 82 | size_t size_with_redzone; /* size with the redzone */ |
83 | const void *name; /* name of the variable */ | | 83 | const void *name; /* name of the variable */ |
84 | const void *module_name; /* name of the module where the var is declared */ | | 84 | const void *module_name; /* name of the module where the var is declared */ |
85 | unsigned long has_dynamic_init; /* the var has dyn initializer (c++) */ | | 85 | unsigned long has_dynamic_init; /* the var has dyn initializer (c++) */ |
86 | struct __asan_global_source_location *location; | | 86 | struct __asan_global_source_location *location; |
87 | #if ASAN_ABI_VERSION >= 7 | | 87 | #if ASAN_ABI_VERSION >= 7 |
88 | uintptr_t odr_indicator; /* the address of the ODR indicator symbol */ | | 88 | uintptr_t odr_indicator; /* the address of the ODR indicator symbol */ |
89 | #endif | | 89 | #endif |
90 | }; | | 90 | }; |
91 | | | 91 | |
92 | static bool kasan_enabled __read_mostly = false; | | 92 | static bool kasan_enabled __read_mostly = false; |
93 | | | 93 | |
94 | /* -------------------------------------------------------------------------- */ | | 94 | /* -------------------------------------------------------------------------- */ |
95 | | | 95 | |
96 | void | | 96 | void |
97 | kasan_shadow_map(void *addr, size_t size) | | 97 | kasan_shadow_map(void *addr, size_t size) |
98 | { | | 98 | { |
99 | size_t sz, npages, i; | | 99 | size_t sz, npages, i; |
100 | vaddr_t sva, eva; | | 100 | vaddr_t sva, eva; |
101 | | | 101 | |
102 | KASSERT((vaddr_t)addr % KASAN_SHADOW_SCALE_SIZE == 0); | | 102 | KASSERT((vaddr_t)addr % KASAN_SHADOW_SCALE_SIZE == 0); |
103 | | | 103 | |
104 | sz = roundup(size, KASAN_SHADOW_SCALE_SIZE) / KASAN_SHADOW_SCALE_SIZE; | | 104 | sz = roundup(size, KASAN_SHADOW_SCALE_SIZE) / KASAN_SHADOW_SCALE_SIZE; |
105 | | | 105 | |
106 | sva = (vaddr_t)kasan_md_addr_to_shad(addr); | | 106 | sva = (vaddr_t)kasan_md_addr_to_shad(addr); |
107 | eva = (vaddr_t)kasan_md_addr_to_shad(addr) + sz; | | 107 | eva = (vaddr_t)kasan_md_addr_to_shad(addr) + sz; |
108 | | | 108 | |
109 | sva = rounddown(sva, PAGE_SIZE); | | 109 | sva = rounddown(sva, PAGE_SIZE); |
110 | eva = roundup(eva, PAGE_SIZE); | | 110 | eva = roundup(eva, PAGE_SIZE); |
111 | | | 111 | |
112 | npages = (eva - sva) / PAGE_SIZE; | | 112 | npages = (eva - sva) / PAGE_SIZE; |
113 | | | 113 | |
114 | KASSERT(sva >= KASAN_MD_SHADOW_START && eva < KASAN_MD_SHADOW_END); | | 114 | KASSERT(sva >= KASAN_MD_SHADOW_START && eva < KASAN_MD_SHADOW_END); |
115 | | | 115 | |
116 | for (i = 0; i < npages; i++) { | | 116 | for (i = 0; i < npages; i++) { |
117 | kasan_md_shadow_map_page(sva + i * PAGE_SIZE); | | 117 | kasan_md_shadow_map_page(sva + i * PAGE_SIZE); |
118 | } | | 118 | } |
119 | } | | 119 | } |
120 | | | 120 | |
121 | static void | | 121 | static void |
122 | kasan_ctors(void) | | 122 | kasan_ctors(void) |
123 | { | | 123 | { |
124 | extern uint64_t __CTOR_LIST__, __CTOR_END__; | | 124 | extern uint64_t __CTOR_LIST__, __CTOR_END__; |
125 | size_t nentries, i; | | 125 | size_t nentries, i; |
126 | uint64_t *ptr; | | 126 | uint64_t *ptr; |
127 | | | 127 | |
128 | nentries = ((size_t)&__CTOR_END__ - (size_t)&__CTOR_LIST__) / | | 128 | nentries = ((size_t)&__CTOR_END__ - (size_t)&__CTOR_LIST__) / |
129 | sizeof(uintptr_t); | | 129 | sizeof(uintptr_t); |
130 | | | 130 | |
131 | ptr = &__CTOR_LIST__; | | 131 | ptr = &__CTOR_LIST__; |
132 | for (i = 0; i < nentries; i++) { | | 132 | for (i = 0; i < nentries; i++) { |
133 | void (*func)(void); | | 133 | void (*func)(void); |
134 | | | 134 | |
135 | func = (void *)(*ptr); | | 135 | func = (void *)(*ptr); |
136 | (*func)(); | | 136 | (*func)(); |
137 | | | 137 | |
138 | ptr++; | | 138 | ptr++; |
139 | } | | 139 | } |
140 | } | | 140 | } |
141 | | | 141 | |
142 | void | | 142 | void |
143 | kasan_early_init(void *stack) | | 143 | kasan_early_init(void *stack) |
144 | { | | 144 | { |
145 | kasan_md_early_init(stack); | | 145 | kasan_md_early_init(stack); |
146 | } | | 146 | } |
147 | | | 147 | |
148 | void | | 148 | void |
149 | kasan_init(void) | | 149 | kasan_init(void) |
150 | { | | 150 | { |
151 | /* MD initialization. */ | | 151 | /* MD initialization. */ |
152 | kasan_md_init(); | | 152 | kasan_md_init(); |
153 | | | 153 | |
154 | /* Now officially enabled. */ | | 154 | /* Now officially enabled. */ |
155 | kasan_enabled = true; | | 155 | kasan_enabled = true; |
156 | | | 156 | |
157 | /* Call the ASAN constructors. */ | | 157 | /* Call the ASAN constructors. */ |
158 | kasan_ctors(); | | 158 | kasan_ctors(); |
159 | } | | 159 | } |
160 | | | 160 | |
161 | static inline const char * | | 161 | static inline const char * |
162 | kasan_code_name(uint8_t code) | | 162 | kasan_code_name(uint8_t code) |
163 | { | | 163 | { |
164 | switch (code) { | | 164 | switch (code) { |
165 | case KASAN_GENERIC_REDZONE: | | 165 | case KASAN_GENERIC_REDZONE: |
166 | return "GenericRedZone"; | | 166 | return "GenericRedZone"; |
167 | case KASAN_MALLOC_REDZONE: | | 167 | case KASAN_MALLOC_REDZONE: |
168 | return "MallocRedZone"; | | 168 | return "MallocRedZone"; |
169 | case KASAN_KMEM_REDZONE: | | 169 | case KASAN_KMEM_REDZONE: |
170 | return "KmemRedZone"; | | 170 | return "KmemRedZone"; |
171 | case KASAN_POOL_REDZONE: | | 171 | case KASAN_POOL_REDZONE: |
172 | return "PoolRedZone"; | | 172 | return "PoolRedZone"; |
173 | case KASAN_POOL_FREED: | | 173 | case KASAN_POOL_FREED: |
174 | return "PoolUseAfterFree"; | | 174 | return "PoolUseAfterFree"; |
175 | case 1 ... 7: | | 175 | case 1 ... 7: |
176 | return "RedZonePartial"; | | 176 | return "RedZonePartial"; |
177 | case KASAN_STACK_LEFT: | | 177 | case KASAN_STACK_LEFT: |
178 | return "StackLeft"; | | 178 | return "StackLeft"; |
179 | case KASAN_STACK_RIGHT: | | 179 | case KASAN_STACK_RIGHT: |
180 | return "StackRight"; | | 180 | return "StackRight"; |
181 | case KASAN_STACK_PARTIAL: | | 181 | case KASAN_STACK_PARTIAL: |
182 | return "StackPartial"; | | 182 | return "StackPartial"; |
183 | case KASAN_USE_AFTER_SCOPE: | | 183 | case KASAN_USE_AFTER_SCOPE: |
184 | return "UseAfterScope"; | | 184 | return "UseAfterScope"; |
185 | default: | | 185 | default: |
186 | return "Unknown"; | | 186 | return "Unknown"; |
187 | } | | 187 | } |
188 | } | | 188 | } |
189 | | | 189 | |
190 | static void | | 190 | static void |
191 | kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc, | | 191 | kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc, |
192 | uint8_t code) | | 192 | uint8_t code) |
193 | { | | 193 | { |
194 | REPORT("ASan: Unauthorized Access In %p: Addr %p [%zu byte%s, %s," | | 194 | REPORT("ASan: Unauthorized Access In %p: Addr %p [%zu byte%s, %s," |
195 | " %s]\n", | | 195 | " %s]\n", |
196 | (void *)pc, (void *)addr, size, (size > 1 ? "s" : ""), | | 196 | (void *)pc, (void *)addr, size, (size > 1 ? "s" : ""), |
197 | (write ? "write" : "read"), kasan_code_name(code)); | | 197 | (write ? "write" : "read"), kasan_code_name(code)); |
198 | kasan_md_unwind(); | | 198 | kasan_md_unwind(); |
199 | } | | 199 | } |
200 | | | 200 | |
201 | static __always_inline void | | 201 | static __always_inline void |
202 | kasan_shadow_1byte_markvalid(unsigned long addr) | | 202 | kasan_shadow_1byte_markvalid(unsigned long addr) |
203 | { | | 203 | { |
204 | int8_t *byte = kasan_md_addr_to_shad((void *)addr); | | 204 | int8_t *byte = kasan_md_addr_to_shad((void *)addr); |
205 | int8_t last = (addr & KASAN_SHADOW_MASK) + 1; | | 205 | int8_t last = (addr & KASAN_SHADOW_MASK) + 1; |
206 | | | 206 | |
207 | *byte = last; | | 207 | *byte = last; |
208 | } | | 208 | } |
209 | | | 209 | |
210 | static __always_inline void | | 210 | static __always_inline void |
211 | kasan_shadow_Nbyte_markvalid(const void *addr, size_t size) | | 211 | kasan_shadow_Nbyte_markvalid(const void *addr, size_t size) |
212 | { | | 212 | { |
213 | size_t i; | | 213 | size_t i; |
214 | | | 214 | |
215 | for (i = 0; i < size; i++) { | | 215 | for (i = 0; i < size; i++) { |
216 | kasan_shadow_1byte_markvalid((unsigned long)addr+i); | | 216 | kasan_shadow_1byte_markvalid((unsigned long)addr+i); |
217 | } | | 217 | } |
218 | } | | 218 | } |
219 | | | 219 | |
220 | static __always_inline void | | 220 | static __always_inline void |
221 | kasan_shadow_Nbyte_fill(const void *addr, size_t size, uint8_t code) | | 221 | kasan_shadow_Nbyte_fill(const void *addr, size_t size, uint8_t code) |
222 | { | | 222 | { |
223 | void *shad; | | 223 | void *shad; |
224 | | | 224 | |
225 | if (__predict_false(size == 0)) | | 225 | if (__predict_false(size == 0)) |
226 | return; | | 226 | return; |
227 | if (__predict_false(kasan_md_unsupported((vaddr_t)addr))) | | 227 | if (__predict_false(kasan_md_unsupported((vaddr_t)addr))) |
228 | return; | | 228 | return; |
229 | | | 229 | |
230 | KASSERT((vaddr_t)addr % KASAN_SHADOW_SCALE_SIZE == 0); | | 230 | KASSERT((vaddr_t)addr % KASAN_SHADOW_SCALE_SIZE == 0); |
231 | KASSERT(size % KASAN_SHADOW_SCALE_SIZE == 0); | | 231 | KASSERT(size % KASAN_SHADOW_SCALE_SIZE == 0); |
232 | | | 232 | |
233 | shad = (void *)kasan_md_addr_to_shad(addr); | | 233 | shad = (void *)kasan_md_addr_to_shad(addr); |
234 | size = size >> KASAN_SHADOW_SCALE_SHIFT; | | 234 | size = size >> KASAN_SHADOW_SCALE_SHIFT; |
235 | | | 235 | |
236 | __builtin_memset(shad, code, size); | | 236 | __builtin_memset(shad, code, size); |
237 | } | | 237 | } |
238 | | | 238 | |
239 | void | | 239 | void |
240 | kasan_add_redzone(size_t *size) | | 240 | kasan_add_redzone(size_t *size) |
241 | { | | 241 | { |
242 | *size = roundup(*size, KASAN_SHADOW_SCALE_SIZE); | | 242 | *size = roundup(*size, KASAN_SHADOW_SCALE_SIZE); |
243 | *size += KASAN_SHADOW_SCALE_SIZE; | | 243 | *size += KASAN_SHADOW_SCALE_SIZE; |
244 | } | | 244 | } |
245 | | | 245 | |
246 | void | | 246 | void |
247 | kasan_softint(struct lwp *l) | | 247 | kasan_softint(struct lwp *l) |
248 | { | | 248 | { |
249 | const void *stk = (const void *)uvm_lwp_getuarea(l); | | 249 | const void *stk = (const void *)uvm_lwp_getuarea(l); |
250 | | | 250 | |
251 | kasan_shadow_Nbyte_fill(stk, USPACE, 0); | | 251 | kasan_shadow_Nbyte_fill(stk, USPACE, 0); |
252 | } | | 252 | } |
253 | | | 253 | |
254 | /* | | 254 | /* |
255 | * In an area of size 'sz_with_redz', mark the 'size' first bytes as valid, | | 255 | * In an area of size 'sz_with_redz', mark the 'size' first bytes as valid, |
256 | * and the rest as invalid. There are generally two use cases: | | 256 | * and the rest as invalid. There are generally two use cases: |
257 | * | | 257 | * |
258 | * o kasan_mark(addr, origsize, size, code), with origsize < size. This marks | | 258 | * o kasan_mark(addr, origsize, size, code), with origsize < size. This marks |
259 | * the redzone at the end of the buffer as invalid. | | 259 | * the redzone at the end of the buffer as invalid. |
260 | * | | 260 | * |
261 | * o kasan_mark(addr, size, size, 0). This marks the entire buffer as valid. | | 261 | * o kasan_mark(addr, size, size, 0). This marks the entire buffer as valid. |
262 | */ | | 262 | */ |
263 | void | | 263 | void |
264 | kasan_mark(const void *addr, size_t size, size_t sz_with_redz, uint8_t code) | | 264 | kasan_mark(const void *addr, size_t size, size_t sz_with_redz, uint8_t code) |
265 | { | | 265 | { |
266 | size_t i, n, redz; | | 266 | size_t i, n, redz; |
267 | int8_t *shad; | | 267 | int8_t *shad; |
268 | | | 268 | |
269 | KASSERT((vaddr_t)addr % KASAN_SHADOW_SCALE_SIZE == 0); | | 269 | KASSERT((vaddr_t)addr % KASAN_SHADOW_SCALE_SIZE == 0); |
270 | redz = sz_with_redz - roundup(size, KASAN_SHADOW_SCALE_SIZE); | | 270 | redz = sz_with_redz - roundup(size, KASAN_SHADOW_SCALE_SIZE); |
271 | KASSERT(redz % KASAN_SHADOW_SCALE_SIZE == 0); | | 271 | KASSERT(redz % KASAN_SHADOW_SCALE_SIZE == 0); |
272 | shad = kasan_md_addr_to_shad(addr); | | 272 | shad = kasan_md_addr_to_shad(addr); |
273 | | | 273 | |
274 | /* Chunks of 8 bytes, valid. */ | | 274 | /* Chunks of 8 bytes, valid. */ |
275 | n = size / KASAN_SHADOW_SCALE_SIZE; | | 275 | n = size / KASAN_SHADOW_SCALE_SIZE; |
276 | for (i = 0; i < n; i++) { | | 276 | for (i = 0; i < n; i++) { |
277 | *shad++ = 0; | | 277 | *shad++ = 0; |
278 | } | | 278 | } |
279 | | | 279 | |
280 | /* Possibly one chunk, mid. */ | | 280 | /* Possibly one chunk, mid. */ |
281 | if ((size & KASAN_SHADOW_MASK) != 0) { | | 281 | if ((size & KASAN_SHADOW_MASK) != 0) { |
282 | *shad++ = (size & KASAN_SHADOW_MASK); | | 282 | *shad++ = (size & KASAN_SHADOW_MASK); |
283 | } | | 283 | } |
284 | | | 284 | |
285 | /* Chunks of 8 bytes, invalid. */ | | 285 | /* Chunks of 8 bytes, invalid. */ |
286 | n = redz / KASAN_SHADOW_SCALE_SIZE; | | 286 | n = redz / KASAN_SHADOW_SCALE_SIZE; |
287 | for (i = 0; i < n; i++) { | | 287 | for (i = 0; i < n; i++) { |
288 | *shad++ = code; | | 288 | *shad++ = code; |
289 | } | | 289 | } |
290 | } | | 290 | } |
291 | | | 291 | |
292 | /* -------------------------------------------------------------------------- */ | | 292 | /* -------------------------------------------------------------------------- */ |
293 | | | 293 | |
294 | #define ADDR_CROSSES_SCALE_BOUNDARY(addr, size) \ | | 294 | #define ADDR_CROSSES_SCALE_BOUNDARY(addr, size) \ |
295 | (addr >> KASAN_SHADOW_SCALE_SHIFT) != \ | | 295 | (addr >> KASAN_SHADOW_SCALE_SHIFT) != \ |
296 | ((addr + size - 1) >> KASAN_SHADOW_SCALE_SHIFT) | | 296 | ((addr + size - 1) >> KASAN_SHADOW_SCALE_SHIFT) |
297 | | | 297 | |
298 | static __always_inline bool | | 298 | static __always_inline bool |
299 | kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code) | | 299 | kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code) |
300 | { | | 300 | { |
301 | int8_t *byte = kasan_md_addr_to_shad((void *)addr); | | 301 | int8_t *byte = kasan_md_addr_to_shad((void *)addr); |
302 | int8_t last = (addr & KASAN_SHADOW_MASK) + 1; | | 302 | int8_t last = (addr & KASAN_SHADOW_MASK) + 1; |
303 | | | 303 | |
304 | if (__predict_true(*byte == 0 || last <= *byte)) { | | 304 | if (__predict_true(*byte == 0 || last <= *byte)) { |
305 | return true; | | 305 | return true; |
306 | } | | 306 | } |
307 | *code = *byte; | | 307 | *code = *byte; |
308 | return false; | | 308 | return false; |
309 | } | | 309 | } |
310 | | | 310 | |
311 | static __always_inline bool | | 311 | static __always_inline bool |
312 | kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code) | | 312 | kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code) |
313 | { | | 313 | { |
314 | int8_t *byte, last; | | 314 | int8_t *byte, last; |
315 | | | 315 | |
316 | if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 2)) { | | 316 | if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 2)) { |
317 | return (kasan_shadow_1byte_isvalid(addr, code) && | | 317 | return (kasan_shadow_1byte_isvalid(addr, code) && |
318 | kasan_shadow_1byte_isvalid(addr+1, code)); | | 318 | kasan_shadow_1byte_isvalid(addr+1, code)); |
319 | } | | 319 | } |
320 | | | 320 | |
321 | byte = kasan_md_addr_to_shad((void *)addr); | | 321 | byte = kasan_md_addr_to_shad((void *)addr); |
322 | last = ((addr + 1) & KASAN_SHADOW_MASK) + 1; | | 322 | last = ((addr + 1) & KASAN_SHADOW_MASK) + 1; |
323 | | | 323 | |
324 | if (__predict_true(*byte == 0 || last <= *byte)) { | | 324 | if (__predict_true(*byte == 0 || last <= *byte)) { |
325 | return true; | | 325 | return true; |
326 | } | | 326 | } |
327 | *code = *byte; | | 327 | *code = *byte; |
328 | return false; | | 328 | return false; |
329 | } | | 329 | } |
330 | | | 330 | |
331 | static __always_inline bool | | 331 | static __always_inline bool |
332 | kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code) | | 332 | kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code) |
333 | { | | 333 | { |
334 | int8_t *byte, last; | | 334 | int8_t *byte, last; |
335 | | | 335 | |
336 | if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 4)) { | | 336 | if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 4)) { |
337 | return (kasan_shadow_2byte_isvalid(addr, code) && | | 337 | return (kasan_shadow_2byte_isvalid(addr, code) && |
338 | kasan_shadow_2byte_isvalid(addr+2, code)); | | 338 | kasan_shadow_2byte_isvalid(addr+2, code)); |
339 | } | | 339 | } |
340 | | | 340 | |
341 | byte = kasan_md_addr_to_shad((void *)addr); | | 341 | byte = kasan_md_addr_to_shad((void *)addr); |
342 | last = ((addr + 3) & KASAN_SHADOW_MASK) + 1; | | 342 | last = ((addr + 3) & KASAN_SHADOW_MASK) + 1; |
343 | | | 343 | |
344 | if (__predict_true(*byte == 0 || last <= *byte)) { | | 344 | if (__predict_true(*byte == 0 || last <= *byte)) { |
345 | return true; | | 345 | return true; |
346 | } | | 346 | } |
347 | *code = *byte; | | 347 | *code = *byte; |
348 | return false; | | 348 | return false; |
349 | } | | 349 | } |
350 | | | 350 | |
351 | static __always_inline bool | | 351 | static __always_inline bool |
352 | kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code) | | 352 | kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code) |
353 | { | | 353 | { |
354 | int8_t *byte, last; | | 354 | int8_t *byte, last; |
355 | | | 355 | |
356 | if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 8)) { | | 356 | if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 8)) { |
357 | return (kasan_shadow_4byte_isvalid(addr, code) && | | 357 | return (kasan_shadow_4byte_isvalid(addr, code) && |
358 | kasan_shadow_4byte_isvalid(addr+4, code)); | | 358 | kasan_shadow_4byte_isvalid(addr+4, code)); |
359 | } | | 359 | } |
360 | | | 360 | |
361 | byte = kasan_md_addr_to_shad((void *)addr); | | 361 | byte = kasan_md_addr_to_shad((void *)addr); |
362 | last = ((addr + 7) & KASAN_SHADOW_MASK) + 1; | | 362 | last = ((addr + 7) & KASAN_SHADOW_MASK) + 1; |
363 | | | 363 | |
364 | if (__predict_true(*byte == 0 || last <= *byte)) { | | 364 | if (__predict_true(*byte == 0 || last <= *byte)) { |
365 | return true; | | 365 | return true; |
366 | } | | 366 | } |
367 | *code = *byte; | | 367 | *code = *byte; |
368 | return false; | | 368 | return false; |
369 | } | | 369 | } |
370 | | | 370 | |
371 | static __always_inline bool | | 371 | static __always_inline bool |
372 | kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code) | | 372 | kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code) |
373 | { | | 373 | { |
374 | size_t i; | | 374 | size_t i; |
375 | | | 375 | |
376 | for (i = 0; i < size; i++) { | | 376 | for (i = 0; i < size; i++) { |
377 | if (!kasan_shadow_1byte_isvalid(addr+i, code)) | | 377 | if (!kasan_shadow_1byte_isvalid(addr+i, code)) |
378 | return false; | | 378 | return false; |
379 | } | | 379 | } |
380 | | | 380 | |
381 | return true; | | 381 | return true; |
382 | } | | 382 | } |
383 | | | 383 | |
384 | static __always_inline void | | 384 | static __always_inline void |
385 | kasan_shadow_check(unsigned long addr, size_t size, bool write, | | 385 | kasan_shadow_check(unsigned long addr, size_t size, bool write, |
386 | unsigned long retaddr) | | 386 | unsigned long retaddr) |
387 | { | | 387 | { |
388 | uint8_t code; | | 388 | uint8_t code; |
389 | bool valid; | | 389 | bool valid; |
390 | | | 390 | |
391 | if (__predict_false(!kasan_enabled)) | | 391 | if (__predict_false(!kasan_enabled)) |
392 | return; | | 392 | return; |
393 | if (__predict_false(size == 0)) | | 393 | if (__predict_false(size == 0)) |
394 | return; | | 394 | return; |
395 | if (__predict_false(kasan_md_unsupported(addr))) | | 395 | if (__predict_false(kasan_md_unsupported(addr))) |
396 | return; | | 396 | return; |
397 | | | 397 | |
398 | if (__builtin_constant_p(size)) { | | 398 | if (__builtin_constant_p(size)) { |
399 | switch (size) { | | 399 | switch (size) { |
400 | case 1: | | 400 | case 1: |
401 | valid = kasan_shadow_1byte_isvalid(addr, &code); | | 401 | valid = kasan_shadow_1byte_isvalid(addr, &code); |
402 | break; | | 402 | break; |
403 | case 2: | | 403 | case 2: |
404 | valid = kasan_shadow_2byte_isvalid(addr, &code); | | 404 | valid = kasan_shadow_2byte_isvalid(addr, &code); |
405 | break; | | 405 | break; |
406 | case 4: | | 406 | case 4: |
407 | valid = kasan_shadow_4byte_isvalid(addr, &code); | | 407 | valid = kasan_shadow_4byte_isvalid(addr, &code); |
408 | break; | | 408 | break; |
409 | case 8: | | 409 | case 8: |
410 | valid = kasan_shadow_8byte_isvalid(addr, &code); | | 410 | valid = kasan_shadow_8byte_isvalid(addr, &code); |
411 | break; | | 411 | break; |
412 | default: | | 412 | default: |
413 | valid = kasan_shadow_Nbyte_isvalid(addr, size, &code); | | 413 | valid = kasan_shadow_Nbyte_isvalid(addr, size, &code); |
414 | break; | | 414 | break; |
415 | } | | 415 | } |
416 | } else { | | 416 | } else { |
417 | valid = kasan_shadow_Nbyte_isvalid(addr, size, &code); | | 417 | valid = kasan_shadow_Nbyte_isvalid(addr, size, &code); |
418 | } | | 418 | } |
419 | | | 419 | |
420 | if (__predict_false(!valid)) { | | 420 | if (__predict_false(!valid)) { |
421 | kasan_report(addr, size, write, retaddr, code); | | 421 | kasan_report(addr, size, write, retaddr, code); |
422 | } | | 422 | } |
423 | } | | 423 | } |
424 | | | 424 | |
425 | /* -------------------------------------------------------------------------- */ | | 425 | /* -------------------------------------------------------------------------- */ |
426 | | | 426 | |
427 | void * | | 427 | void * |
428 | kasan_memcpy(void *dst, const void *src, size_t len) | | 428 | kasan_memcpy(void *dst, const void *src, size_t len) |
429 | { | | 429 | { |
430 | kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); | | 430 | kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); |
431 | kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); | | 431 | kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); |
432 | return __builtin_memcpy(dst, src, len); | | 432 | return __builtin_memcpy(dst, src, len); |
433 | } | | 433 | } |
434 | | | 434 | |
435 | int | | 435 | int |
436 | kasan_memcmp(const void *b1, const void *b2, size_t len) | | 436 | kasan_memcmp(const void *b1, const void *b2, size_t len) |
437 | { | | 437 | { |
438 | kasan_shadow_check((unsigned long)b1, len, false, __RET_ADDR); | | 438 | kasan_shadow_check((unsigned long)b1, len, false, __RET_ADDR); |
439 | kasan_shadow_check((unsigned long)b2, len, false, __RET_ADDR); | | 439 | kasan_shadow_check((unsigned long)b2, len, false, __RET_ADDR); |
440 | return __builtin_memcmp(b1, b2, len); | | 440 | return __builtin_memcmp(b1, b2, len); |
441 | } | | 441 | } |
442 | | | 442 | |
443 | void * | | 443 | void * |
444 | kasan_memset(void *b, int c, size_t len) | | 444 | kasan_memset(void *b, int c, size_t len) |
445 | { | | 445 | { |
446 | kasan_shadow_check((unsigned long)b, len, true, __RET_ADDR); | | 446 | kasan_shadow_check((unsigned long)b, len, true, __RET_ADDR); |
447 | return __builtin_memset(b, c, len); | | 447 | return __builtin_memset(b, c, len); |
448 | } | | 448 | } |
449 | | | 449 | |
450 | void * | | 450 | void * |
451 | kasan_memmove(void *dst, const void *src, size_t len) | | 451 | kasan_memmove(void *dst, const void *src, size_t len) |
452 | { | | 452 | { |
453 | kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); | | 453 | kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); |
454 | kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); | | 454 | kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); |
455 | return __builtin_memmove(dst, src, len); | | 455 | return __builtin_memmove(dst, src, len); |
456 | } | | 456 | } |
457 | | | 457 | |
458 | char * | | 458 | char * |
459 | kasan_strcpy(char *dst, const char *src) | | 459 | kasan_strcpy(char *dst, const char *src) |
460 | { | | 460 | { |
461 | char *save = dst; | | 461 | char *save = dst; |
462 | | | 462 | |
463 | while (1) { | | 463 | while (1) { |
464 | kasan_shadow_check((unsigned long)src, 1, false, __RET_ADDR); | | 464 | kasan_shadow_check((unsigned long)src, 1, false, __RET_ADDR); |
465 | kasan_shadow_check((unsigned long)dst, 1, true, __RET_ADDR); | | 465 | kasan_shadow_check((unsigned long)dst, 1, true, __RET_ADDR); |
466 | *dst = *src; | | 466 | *dst = *src; |
467 | if (*src == '\0') | | 467 | if (*src == '\0') |
468 | break; | | 468 | break; |
469 | src++, dst++; | | 469 | src++, dst++; |
470 | } | | 470 | } |
471 | | | 471 | |
472 | return save; | | 472 | return save; |
473 | } | | 473 | } |
474 | | | 474 | |
475 | int | | 475 | int |
476 | kasan_strcmp(const char *s1, const char *s2) | | 476 | kasan_strcmp(const char *s1, const char *s2) |
477 | { | | 477 | { |
478 | while (1) { | | 478 | while (1) { |
479 | kasan_shadow_check((unsigned long)s1, 1, false, __RET_ADDR); | | 479 | kasan_shadow_check((unsigned long)s1, 1, false, __RET_ADDR); |
480 | kasan_shadow_check((unsigned long)s2, 1, false, __RET_ADDR); | | 480 | kasan_shadow_check((unsigned long)s2, 1, false, __RET_ADDR); |
481 | if (*s1 != *s2) | | 481 | if (*s1 != *s2) |
482 | break; | | 482 | break; |
483 | if (*s1 == '\0') | | 483 | if (*s1 == '\0') |
484 | return 0; | | 484 | return 0; |
485 | s1++, s2++; | | 485 | s1++, s2++; |
486 | } | | 486 | } |
487 | | | 487 | |
488 | return (*(const unsigned char *)s1 - *(const unsigned char *)s2); | | 488 | return (*(const unsigned char *)s1 - *(const unsigned char *)s2); |
489 | } | | 489 | } |
490 | | | 490 | |
491 | size_t | | 491 | size_t |
492 | kasan_strlen(const char *str) | | 492 | kasan_strlen(const char *str) |
493 | { | | 493 | { |
494 | const char *s; | | 494 | const char *s; |
495 | | | 495 | |
496 | s = str; | | 496 | s = str; |
497 | while (1) { | | 497 | while (1) { |
498 | kasan_shadow_check((unsigned long)s, 1, false, __RET_ADDR); | | 498 | kasan_shadow_check((unsigned long)s, 1, false, __RET_ADDR); |
499 | if (*s == '\0') | | 499 | if (*s == '\0') |
500 | break; | | 500 | break; |
501 | s++; | | 501 | s++; |
502 | } | | 502 | } |
503 | | | 503 | |
504 | return (s - str); | | 504 | return (s - str); |
505 | } | | 505 | } |
506 | | | 506 | |
507 | #undef kcopy | | 507 | #undef kcopy |
508 | #undef copystr | | 508 | #undef copystr |
509 | #undef copyinstr | | 509 | #undef copyinstr |
510 | #undef copyoutstr | | 510 | #undef copyoutstr |
511 | #undef copyin | | 511 | #undef copyin |
512 | | | 512 | |
513 | int kasan_kcopy(const void *, void *, size_t); | | 513 | int kasan_kcopy(const void *, void *, size_t); |
514 | int kasan_copystr(const void *, void *, size_t, size_t *); | | 514 | int kasan_copystr(const void *, void *, size_t, size_t *); |
515 | int kasan_copyinstr(const void *, void *, size_t, size_t *); | | 515 | int kasan_copyinstr(const void *, void *, size_t, size_t *); |
516 | int kasan_copyoutstr(const void *, void *, size_t, size_t *); | | 516 | int kasan_copyoutstr(const void *, void *, size_t, size_t *); |
517 | int kasan_copyin(const void *, void *, size_t); | | 517 | int kasan_copyin(const void *, void *, size_t); |
518 | int kcopy(const void *, void *, size_t); | | 518 | int kcopy(const void *, void *, size_t); |
519 | int copystr(const void *, void *, size_t, size_t *); | | 519 | int copystr(const void *, void *, size_t, size_t *); |
520 | int copyinstr(const void *, void *, size_t, size_t *); | | 520 | int copyinstr(const void *, void *, size_t, size_t *); |
521 | int copyoutstr(const void *, void *, size_t, size_t *); | | 521 | int copyoutstr(const void *, void *, size_t, size_t *); |
522 | int copyin(const void *, void *, size_t); | | 522 | int copyin(const void *, void *, size_t); |
523 | | | 523 | |
524 | int | | 524 | int |
525 | kasan_kcopy(const void *src, void *dst, size_t len) | | 525 | kasan_kcopy(const void *src, void *dst, size_t len) |
526 | { | | 526 | { |
527 | kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); | | 527 | kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); |
528 | kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); | | 528 | kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); |
529 | return kcopy(src, dst, len); | | 529 | return kcopy(src, dst, len); |
530 | } | | 530 | } |
531 | | | 531 | |
532 | int | | 532 | int |
533 | kasan_copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done) | | 533 | kasan_copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done) |
534 | { | | 534 | { |
535 | kasan_shadow_check((unsigned long)kdaddr, len, true, __RET_ADDR); | | 535 | kasan_shadow_check((unsigned long)kdaddr, len, true, __RET_ADDR); |
536 | return copystr(kfaddr, kdaddr, len, done); | | 536 | return copystr(kfaddr, kdaddr, len, done); |
537 | } | | 537 | } |
538 | | | 538 | |
539 | int | | 539 | int |
540 | kasan_copyin(const void *uaddr, void *kaddr, size_t len) | | 540 | kasan_copyin(const void *uaddr, void *kaddr, size_t len) |
541 | { | | 541 | { |
542 | kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR); | | 542 | kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR); |
543 | return copyin(uaddr, kaddr, len); | | 543 | return copyin(uaddr, kaddr, len); |
544 | } | | 544 | } |
545 | | | 545 | |
546 | int | | 546 | int |
547 | kasan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) | | 547 | kasan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) |
548 | { | | 548 | { |
549 | kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR); | | 549 | kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR); |
550 | return copyinstr(uaddr, kaddr, len, done); | | 550 | return copyinstr(uaddr, kaddr, len, done); |
551 | } | | 551 | } |
552 | | | 552 | |
553 | int | | 553 | int |
554 | kasan_copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done) | | 554 | kasan_copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done) |
555 | { | | 555 | { |
556 | kasan_shadow_check((unsigned long)kaddr, len, false, __RET_ADDR); | | 556 | kasan_shadow_check((unsigned long)kaddr, len, false, __RET_ADDR); |
557 | return copyoutstr(kaddr, uaddr, len, done); | | 557 | return copyoutstr(kaddr, uaddr, len, done); |
558 | } | | 558 | } |
559 | | | 559 | |
560 | /* -------------------------------------------------------------------------- */ | | 560 | /* -------------------------------------------------------------------------- */ |
561 | | | 561 | |
| | | 562 | #undef _ucas_32 |
| | | 563 | #undef _ucas_32_mp |
| | | 564 | #undef _ucas_64 |
| | | 565 | #undef _ucas_64_mp |
| | | 566 | #undef _ufetch_8 |
| | | 567 | #undef _ufetch_16 |
| | | 568 | #undef _ufetch_32 |
| | | 569 | #undef _ufetch_64 |
| | | 570 | |
| | | 571 | int _ucas_32(volatile uint32_t *, uint32_t, uint32_t, uint32_t *); |
| | | 572 | int kasan__ucas_32(volatile uint32_t *, uint32_t, uint32_t, uint32_t *); |
| | | 573 | int |
| | | 574 | kasan__ucas_32(volatile uint32_t *uaddr, uint32_t old, uint32_t new, |
| | | 575 | uint32_t *ret) |
| | | 576 | { |
| | | 577 | kasan_shadow_check((unsigned long)ret, sizeof(*ret), true, |
| | | 578 | __RET_ADDR); |
| | | 579 | return _ucas_32(uaddr, old, new, ret); |
| | | 580 | } |
| | | 581 | |
| | | 582 | #ifdef __HAVE_UCAS_MP |
| | | 583 | int _ucas_32_mp(volatile uint32_t *, uint32_t, uint32_t, uint32_t *); |
| | | 584 | int kasan__ucas_32_mp(volatile uint32_t *, uint32_t, uint32_t, uint32_t *); |
| | | 585 | int |
| | | 586 | kasan__ucas_32_mp(volatile uint32_t *uaddr, uint32_t old, uint32_t new, |
| | | 587 | uint32_t *ret) |
| | | 588 | { |
| | | 589 | kasan_shadow_check((unsigned long)ret, sizeof(*ret), true, |
| | | 590 | __RET_ADDR); |
| | | 591 | return _ucas_32_mp(uaddr, old, new, ret); |
| | | 592 | } |
| | | 593 | #endif |
| | | 594 | |
| | | 595 | #ifdef _LP64 |
| | | 596 | int _ucas_64(volatile uint64_t *, uint64_t, uint64_t, uint64_t *); |
| | | 597 | int kasan__ucas_64(volatile uint64_t *, uint64_t, uint64_t, uint64_t *); |
| | | 598 | int |
| | | 599 | kasan__ucas_64(volatile uint64_t *uaddr, uint64_t old, uint64_t new, |
| | | 600 | uint64_t *ret) |
| | | 601 | { |
| | | 602 | kasan_shadow_check((unsigned long)ret, sizeof(*ret), true, |
| | | 603 | __RET_ADDR); |
| | | 604 | return _ucas_64(uaddr, old, new, ret); |
| | | 605 | } |
| | | 606 | |
| | | 607 | #ifdef __HAVE_UCAS_MP |
| | | 608 | int _ucas_64_mp(volatile uint64_t *, uint64_t, uint64_t, uint64_t *); |
| | | 609 | int kasan__ucas_64_mp(volatile uint64_t *, uint64_t, uint64_t, uint64_t *); |
| | | 610 | int |
| | | 611 | kasan__ucas_64_mp(volatile uint64_t *uaddr, uint64_t old, uint64_t new, |
| | | 612 | uint64_t *ret) |
| | | 613 | { |
| | | 614 | kasan_shadow_check((unsigned long)ret, sizeof(*ret), true, |
| | | 615 | __RET_ADDR); |
| | | 616 | return _ucas_64_mp(uaddr, old, new, ret); |
| | | 617 | } |
| | | 618 | #endif |
| | | 619 | #endif |
| | | 620 | |
| | | 621 | int _ufetch_8(const uint8_t *, uint8_t *); |
| | | 622 | int kasan__ufetch_8(const uint8_t *, uint8_t *); |
| | | 623 | int |
| | | 624 | kasan__ufetch_8(const uint8_t *uaddr, uint8_t *valp) |
| | | 625 | { |
| | | 626 | kasan_shadow_check((unsigned long)valp, sizeof(*valp), true, |
| | | 627 | __RET_ADDR); |
| | | 628 | return _ufetch_8(uaddr, valp); |
| | | 629 | } |
| | | 630 | |
| | | 631 | int _ufetch_16(const uint16_t *, uint16_t *); |
| | | 632 | int kasan__ufetch_16(const uint16_t *, uint16_t *); |
| | | 633 | int |
| | | 634 | kasan__ufetch_16(const uint16_t *uaddr, uint16_t *valp) |
| | | 635 | { |
| | | 636 | kasan_shadow_check((unsigned long)valp, sizeof(*valp), true, |
| | | 637 | __RET_ADDR); |
| | | 638 | return _ufetch_16(uaddr, valp); |
| | | 639 | } |
| | | 640 | |
| | | 641 | int _ufetch_32(const uint32_t *, uint32_t *); |
| | | 642 | int kasan__ufetch_32(const uint32_t *, uint32_t *); |
| | | 643 | int |
| | | 644 | kasan__ufetch_32(const uint32_t *uaddr, uint32_t *valp) |
| | | 645 | { |
| | | 646 | kasan_shadow_check((unsigned long)valp, sizeof(*valp), true, |
| | | 647 | __RET_ADDR); |
| | | 648 | return _ufetch_32(uaddr, valp); |
| | | 649 | } |
| | | 650 | |
| | | 651 | #ifdef _LP64 |
| | | 652 | int _ufetch_64(const uint64_t *, uint64_t *); |
| | | 653 | int kasan__ufetch_64(const uint64_t *, uint64_t *); |
| | | 654 | int |
| | | 655 | kasan__ufetch_64(const uint64_t *uaddr, uint64_t *valp) |
| | | 656 | { |
| | | 657 | kasan_shadow_check((unsigned long)valp, sizeof(*valp), true, |
| | | 658 | __RET_ADDR); |
| | | 659 | return _ufetch_64(uaddr, valp); |
| | | 660 | } |
| | | 661 | #endif |
| | | 662 | |
| | | 663 | /* -------------------------------------------------------------------------- */ |
| | | 664 | |
562 | #undef atomic_add_32 | | 665 | #undef atomic_add_32 |
563 | #undef atomic_add_int | | 666 | #undef atomic_add_int |
564 | #undef atomic_add_long | | 667 | #undef atomic_add_long |
565 | #undef atomic_add_ptr | | 668 | #undef atomic_add_ptr |
566 | #undef atomic_add_64 | | 669 | #undef atomic_add_64 |
567 | #undef atomic_add_32_nv | | 670 | #undef atomic_add_32_nv |
568 | #undef atomic_add_int_nv | | 671 | #undef atomic_add_int_nv |
569 | #undef atomic_add_long_nv | | 672 | #undef atomic_add_long_nv |
570 | #undef atomic_add_ptr_nv | | 673 | #undef atomic_add_ptr_nv |
571 | #undef atomic_add_64_nv | | 674 | #undef atomic_add_64_nv |
572 | #undef atomic_and_32 | | 675 | #undef atomic_and_32 |
573 | #undef atomic_and_uint | | 676 | #undef atomic_and_uint |
574 | #undef atomic_and_ulong | | 677 | #undef atomic_and_ulong |
575 | #undef atomic_and_64 | | 678 | #undef atomic_and_64 |
576 | #undef atomic_and_32_nv | | 679 | #undef atomic_and_32_nv |
577 | #undef atomic_and_uint_nv | | 680 | #undef atomic_and_uint_nv |
578 | #undef atomic_and_ulong_nv | | 681 | #undef atomic_and_ulong_nv |
579 | #undef atomic_and_64_nv | | 682 | #undef atomic_and_64_nv |
580 | #undef atomic_or_32 | | 683 | #undef atomic_or_32 |
581 | #undef atomic_or_uint | | 684 | #undef atomic_or_uint |
582 | #undef atomic_or_ulong | | 685 | #undef atomic_or_ulong |
583 | #undef atomic_or_64 | | 686 | #undef atomic_or_64 |
584 | #undef atomic_or_32_nv | | 687 | #undef atomic_or_32_nv |
585 | #undef atomic_or_uint_nv | | 688 | #undef atomic_or_uint_nv |
586 | #undef atomic_or_ulong_nv | | 689 | #undef atomic_or_ulong_nv |
587 | #undef atomic_or_64_nv | | 690 | #undef atomic_or_64_nv |
588 | #undef atomic_cas_32 | | 691 | #undef atomic_cas_32 |
589 | #undef atomic_cas_uint | | 692 | #undef atomic_cas_uint |
590 | #undef atomic_cas_ulong | | 693 | #undef atomic_cas_ulong |
591 | #undef atomic_cas_ptr | | 694 | #undef atomic_cas_ptr |
592 | #undef atomic_cas_64 | | 695 | #undef atomic_cas_64 |
593 | #undef atomic_cas_32_ni | | 696 | #undef atomic_cas_32_ni |
594 | #undef atomic_cas_uint_ni | | 697 | #undef atomic_cas_uint_ni |
595 | #undef atomic_cas_ulong_ni | | 698 | #undef atomic_cas_ulong_ni |
596 | #undef atomic_cas_ptr_ni | | 699 | #undef atomic_cas_ptr_ni |
597 | #undef atomic_cas_64_ni | | 700 | #undef atomic_cas_64_ni |
598 | #undef atomic_swap_32 | | 701 | #undef atomic_swap_32 |
599 | #undef atomic_swap_uint | | 702 | #undef atomic_swap_uint |
600 | #undef atomic_swap_ulong | | 703 | #undef atomic_swap_ulong |
601 | #undef atomic_swap_ptr | | 704 | #undef atomic_swap_ptr |
602 | #undef atomic_swap_64 | | 705 | #undef atomic_swap_64 |
603 | #undef atomic_dec_32 | | 706 | #undef atomic_dec_32 |
604 | #undef atomic_dec_uint | | 707 | #undef atomic_dec_uint |
605 | #undef atomic_dec_ulong | | 708 | #undef atomic_dec_ulong |
606 | #undef atomic_dec_ptr | | 709 | #undef atomic_dec_ptr |
607 | #undef atomic_dec_64 | | 710 | #undef atomic_dec_64 |
608 | #undef atomic_dec_32_nv | | 711 | #undef atomic_dec_32_nv |
609 | #undef atomic_dec_uint_nv | | 712 | #undef atomic_dec_uint_nv |
610 | #undef atomic_dec_ulong_nv | | 713 | #undef atomic_dec_ulong_nv |
611 | #undef atomic_dec_ptr_nv | | 714 | #undef atomic_dec_ptr_nv |
612 | #undef atomic_dec_64_nv | | 715 | #undef atomic_dec_64_nv |
613 | #undef atomic_inc_32 | | 716 | #undef atomic_inc_32 |
614 | #undef atomic_inc_uint | | 717 | #undef atomic_inc_uint |
615 | #undef atomic_inc_ulong | | 718 | #undef atomic_inc_ulong |
616 | #undef atomic_inc_ptr | | 719 | #undef atomic_inc_ptr |
617 | #undef atomic_inc_64 | | 720 | #undef atomic_inc_64 |
618 | #undef atomic_inc_32_nv | | 721 | #undef atomic_inc_32_nv |
619 | #undef atomic_inc_uint_nv | | 722 | #undef atomic_inc_uint_nv |
620 | #undef atomic_inc_ulong_nv | | 723 | #undef atomic_inc_ulong_nv |
621 | #undef atomic_inc_ptr_nv | | 724 | #undef atomic_inc_ptr_nv |
622 | #undef atomic_inc_64_nv | | 725 | #undef atomic_inc_64_nv |
623 | | | 726 | |
624 | #define ASAN_ATOMIC_FUNC_ADD(name, tret, targ1, targ2) \ | | 727 | #define ASAN_ATOMIC_FUNC_ADD(name, tret, targ1, targ2) \ |
625 | void atomic_add_##name(volatile targ1 *, targ2); \ | | 728 | void atomic_add_##name(volatile targ1 *, targ2); \ |
626 | void kasan_atomic_add_##name(volatile targ1 *, targ2); \ | | 729 | void kasan_atomic_add_##name(volatile targ1 *, targ2); \ |
627 | void kasan_atomic_add_##name(volatile targ1 *ptr, targ2 val) \ | | 730 | void kasan_atomic_add_##name(volatile targ1 *ptr, targ2 val) \ |
628 | { \ | | 731 | { \ |
629 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 732 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
630 | __RET_ADDR); \ | | 733 | __RET_ADDR); \ |
631 | atomic_add_##name(ptr, val); \ | | 734 | atomic_add_##name(ptr, val); \ |
632 | } \ | | 735 | } \ |
633 | tret atomic_add_##name##_nv(volatile targ1 *, targ2); \ | | 736 | tret atomic_add_##name##_nv(volatile targ1 *, targ2); \ |
634 | tret kasan_atomic_add_##name##_nv(volatile targ1 *, targ2); \ | | 737 | tret kasan_atomic_add_##name##_nv(volatile targ1 *, targ2); \ |
635 | tret kasan_atomic_add_##name##_nv(volatile targ1 *ptr, targ2 val) \ | | 738 | tret kasan_atomic_add_##name##_nv(volatile targ1 *ptr, targ2 val) \ |
636 | { \ | | 739 | { \ |
637 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 740 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
638 | __RET_ADDR); \ | | 741 | __RET_ADDR); \ |
639 | return atomic_add_##name##_nv(ptr, val); \ | | 742 | return atomic_add_##name##_nv(ptr, val); \ |
640 | } | | 743 | } |
641 | | | 744 | |
642 | #define ASAN_ATOMIC_FUNC_AND(name, tret, targ1, targ2) \ | | 745 | #define ASAN_ATOMIC_FUNC_AND(name, tret, targ1, targ2) \ |
643 | void atomic_and_##name(volatile targ1 *, targ2); \ | | 746 | void atomic_and_##name(volatile targ1 *, targ2); \ |
644 | void kasan_atomic_and_##name(volatile targ1 *, targ2); \ | | 747 | void kasan_atomic_and_##name(volatile targ1 *, targ2); \ |
645 | void kasan_atomic_and_##name(volatile targ1 *ptr, targ2 val) \ | | 748 | void kasan_atomic_and_##name(volatile targ1 *ptr, targ2 val) \ |
646 | { \ | | 749 | { \ |
647 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 750 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
648 | __RET_ADDR); \ | | 751 | __RET_ADDR); \ |
649 | atomic_and_##name(ptr, val); \ | | 752 | atomic_and_##name(ptr, val); \ |
650 | } \ | | 753 | } \ |
651 | tret atomic_and_##name##_nv(volatile targ1 *, targ2); \ | | 754 | tret atomic_and_##name##_nv(volatile targ1 *, targ2); \ |
652 | tret kasan_atomic_and_##name##_nv(volatile targ1 *, targ2); \ | | 755 | tret kasan_atomic_and_##name##_nv(volatile targ1 *, targ2); \ |
653 | tret kasan_atomic_and_##name##_nv(volatile targ1 *ptr, targ2 val) \ | | 756 | tret kasan_atomic_and_##name##_nv(volatile targ1 *ptr, targ2 val) \ |
654 | { \ | | 757 | { \ |
655 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 758 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
656 | __RET_ADDR); \ | | 759 | __RET_ADDR); \ |
657 | return atomic_and_##name##_nv(ptr, val); \ | | 760 | return atomic_and_##name##_nv(ptr, val); \ |
658 | } | | 761 | } |
659 | | | 762 | |
660 | #define ASAN_ATOMIC_FUNC_OR(name, tret, targ1, targ2) \ | | 763 | #define ASAN_ATOMIC_FUNC_OR(name, tret, targ1, targ2) \ |
661 | void atomic_or_##name(volatile targ1 *, targ2); \ | | 764 | void atomic_or_##name(volatile targ1 *, targ2); \ |
662 | void kasan_atomic_or_##name(volatile targ1 *, targ2); \ | | 765 | void kasan_atomic_or_##name(volatile targ1 *, targ2); \ |
663 | void kasan_atomic_or_##name(volatile targ1 *ptr, targ2 val) \ | | 766 | void kasan_atomic_or_##name(volatile targ1 *ptr, targ2 val) \ |
664 | { \ | | 767 | { \ |
665 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 768 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
666 | __RET_ADDR); \ | | 769 | __RET_ADDR); \ |
667 | atomic_or_##name(ptr, val); \ | | 770 | atomic_or_##name(ptr, val); \ |
668 | } \ | | 771 | } \ |
669 | tret atomic_or_##name##_nv(volatile targ1 *, targ2); \ | | 772 | tret atomic_or_##name##_nv(volatile targ1 *, targ2); \ |
670 | tret kasan_atomic_or_##name##_nv(volatile targ1 *, targ2); \ | | 773 | tret kasan_atomic_or_##name##_nv(volatile targ1 *, targ2); \ |
671 | tret kasan_atomic_or_##name##_nv(volatile targ1 *ptr, targ2 val) \ | | 774 | tret kasan_atomic_or_##name##_nv(volatile targ1 *ptr, targ2 val) \ |
672 | { \ | | 775 | { \ |
673 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 776 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
674 | __RET_ADDR); \ | | 777 | __RET_ADDR); \ |
675 | return atomic_or_##name##_nv(ptr, val); \ | | 778 | return atomic_or_##name##_nv(ptr, val); \ |
676 | } | | 779 | } |
677 | | | 780 | |
678 | #define ASAN_ATOMIC_FUNC_CAS(name, tret, targ1, targ2) \ | | 781 | #define ASAN_ATOMIC_FUNC_CAS(name, tret, targ1, targ2) \ |
679 | tret atomic_cas_##name(volatile targ1 *, targ2, targ2); \ | | 782 | tret atomic_cas_##name(volatile targ1 *, targ2, targ2); \ |
680 | tret kasan_atomic_cas_##name(volatile targ1 *, targ2, targ2); \ | | 783 | tret kasan_atomic_cas_##name(volatile targ1 *, targ2, targ2); \ |
681 | tret kasan_atomic_cas_##name(volatile targ1 *ptr, targ2 exp, targ2 new) \ | | 784 | tret kasan_atomic_cas_##name(volatile targ1 *ptr, targ2 exp, targ2 new) \ |
682 | { \ | | 785 | { \ |
683 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 786 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
684 | __RET_ADDR); \ | | 787 | __RET_ADDR); \ |
685 | return atomic_cas_##name(ptr, exp, new); \ | | 788 | return atomic_cas_##name(ptr, exp, new); \ |
686 | } \ | | 789 | } \ |
687 | tret atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2); \ | | 790 | tret atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2); \ |
688 | tret kasan_atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2); \ | | 791 | tret kasan_atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2); \ |
689 | tret kasan_atomic_cas_##name##_ni(volatile targ1 *ptr, targ2 exp, targ2 new) \ | | 792 | tret kasan_atomic_cas_##name##_ni(volatile targ1 *ptr, targ2 exp, targ2 new) \ |
690 | { \ | | 793 | { \ |
691 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 794 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
692 | __RET_ADDR); \ | | 795 | __RET_ADDR); \ |
693 | return atomic_cas_##name##_ni(ptr, exp, new); \ | | 796 | return atomic_cas_##name##_ni(ptr, exp, new); \ |
694 | } | | 797 | } |
695 | | | 798 | |
696 | #define ASAN_ATOMIC_FUNC_SWAP(name, tret, targ1, targ2) \ | | 799 | #define ASAN_ATOMIC_FUNC_SWAP(name, tret, targ1, targ2) \ |
697 | tret atomic_swap_##name(volatile targ1 *, targ2); \ | | 800 | tret atomic_swap_##name(volatile targ1 *, targ2); \ |
698 | tret kasan_atomic_swap_##name(volatile targ1 *, targ2); \ | | 801 | tret kasan_atomic_swap_##name(volatile targ1 *, targ2); \ |
699 | tret kasan_atomic_swap_##name(volatile targ1 *ptr, targ2 val) \ | | 802 | tret kasan_atomic_swap_##name(volatile targ1 *ptr, targ2 val) \ |
700 | { \ | | 803 | { \ |
701 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 804 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
702 | __RET_ADDR); \ | | 805 | __RET_ADDR); \ |
703 | return atomic_swap_##name(ptr, val); \ | | 806 | return atomic_swap_##name(ptr, val); \ |
704 | } | | 807 | } |
705 | | | 808 | |
706 | #define ASAN_ATOMIC_FUNC_DEC(name, tret, targ1) \ | | 809 | #define ASAN_ATOMIC_FUNC_DEC(name, tret, targ1) \ |
707 | void atomic_dec_##name(volatile targ1 *); \ | | 810 | void atomic_dec_##name(volatile targ1 *); \ |
708 | void kasan_atomic_dec_##name(volatile targ1 *); \ | | 811 | void kasan_atomic_dec_##name(volatile targ1 *); \ |
709 | void kasan_atomic_dec_##name(volatile targ1 *ptr) \ | | 812 | void kasan_atomic_dec_##name(volatile targ1 *ptr) \ |
710 | { \ | | 813 | { \ |
711 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 814 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
712 | __RET_ADDR); \ | | 815 | __RET_ADDR); \ |
713 | atomic_dec_##name(ptr); \ | | 816 | atomic_dec_##name(ptr); \ |
714 | } \ | | 817 | } \ |
715 | tret atomic_dec_##name##_nv(volatile targ1 *); \ | | 818 | tret atomic_dec_##name##_nv(volatile targ1 *); \ |
716 | tret kasan_atomic_dec_##name##_nv(volatile targ1 *); \ | | 819 | tret kasan_atomic_dec_##name##_nv(volatile targ1 *); \ |
717 | tret kasan_atomic_dec_##name##_nv(volatile targ1 *ptr) \ | | 820 | tret kasan_atomic_dec_##name##_nv(volatile targ1 *ptr) \ |
718 | { \ | | 821 | { \ |
719 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 822 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
720 | __RET_ADDR); \ | | 823 | __RET_ADDR); \ |
721 | return atomic_dec_##name##_nv(ptr); \ | | 824 | return atomic_dec_##name##_nv(ptr); \ |
722 | } | | 825 | } |
723 | | | 826 | |
724 | #define ASAN_ATOMIC_FUNC_INC(name, tret, targ1) \ | | 827 | #define ASAN_ATOMIC_FUNC_INC(name, tret, targ1) \ |
725 | void atomic_inc_##name(volatile targ1 *); \ | | 828 | void atomic_inc_##name(volatile targ1 *); \ |
726 | void kasan_atomic_inc_##name(volatile targ1 *); \ | | 829 | void kasan_atomic_inc_##name(volatile targ1 *); \ |
727 | void kasan_atomic_inc_##name(volatile targ1 *ptr) \ | | 830 | void kasan_atomic_inc_##name(volatile targ1 *ptr) \ |
728 | { \ | | 831 | { \ |
729 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 832 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
730 | __RET_ADDR); \ | | 833 | __RET_ADDR); \ |
731 | atomic_inc_##name(ptr); \ | | 834 | atomic_inc_##name(ptr); \ |
732 | } \ | | 835 | } \ |
733 | tret atomic_inc_##name##_nv(volatile targ1 *); \ | | 836 | tret atomic_inc_##name##_nv(volatile targ1 *); \ |
734 | tret kasan_atomic_inc_##name##_nv(volatile targ1 *); \ | | 837 | tret kasan_atomic_inc_##name##_nv(volatile targ1 *); \ |
735 | tret kasan_atomic_inc_##name##_nv(volatile targ1 *ptr) \ | | 838 | tret kasan_atomic_inc_##name##_nv(volatile targ1 *ptr) \ |
736 | { \ | | 839 | { \ |
737 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ | | 840 | kasan_shadow_check((uintptr_t)ptr, sizeof(tret), true, \ |
738 | __RET_ADDR); \ | | 841 | __RET_ADDR); \ |
739 | return atomic_inc_##name##_nv(ptr); \ | | 842 | return atomic_inc_##name##_nv(ptr); \ |
740 | } | | 843 | } |
741 | | | 844 | |
742 | ASAN_ATOMIC_FUNC_ADD(32, uint32_t, uint32_t, int32_t); | | 845 | ASAN_ATOMIC_FUNC_ADD(32, uint32_t, uint32_t, int32_t); |
743 | ASAN_ATOMIC_FUNC_ADD(64, uint64_t, uint64_t, int64_t); | | 846 | ASAN_ATOMIC_FUNC_ADD(64, uint64_t, uint64_t, int64_t); |
744 | ASAN_ATOMIC_FUNC_ADD(int, unsigned int, unsigned int, int); | | 847 | ASAN_ATOMIC_FUNC_ADD(int, unsigned int, unsigned int, int); |
745 | ASAN_ATOMIC_FUNC_ADD(long, unsigned long, unsigned long, long); | | 848 | ASAN_ATOMIC_FUNC_ADD(long, unsigned long, unsigned long, long); |
746 | ASAN_ATOMIC_FUNC_ADD(ptr, void *, void, ssize_t); | | 849 | ASAN_ATOMIC_FUNC_ADD(ptr, void *, void, ssize_t); |
747 | | | 850 | |
748 | ASAN_ATOMIC_FUNC_AND(32, uint32_t, uint32_t, uint32_t); | | 851 | ASAN_ATOMIC_FUNC_AND(32, uint32_t, uint32_t, uint32_t); |
749 | ASAN_ATOMIC_FUNC_AND(64, uint64_t, uint64_t, uint64_t); | | 852 | ASAN_ATOMIC_FUNC_AND(64, uint64_t, uint64_t, uint64_t); |
750 | ASAN_ATOMIC_FUNC_AND(uint, unsigned int, unsigned int, unsigned int); | | 853 | ASAN_ATOMIC_FUNC_AND(uint, unsigned int, unsigned int, unsigned int); |
751 | ASAN_ATOMIC_FUNC_AND(ulong, unsigned long, unsigned long, unsigned long); | | 854 | ASAN_ATOMIC_FUNC_AND(ulong, unsigned long, unsigned long, unsigned long); |
752 | | | 855 | |
753 | ASAN_ATOMIC_FUNC_OR(32, uint32_t, uint32_t, uint32_t); | | 856 | ASAN_ATOMIC_FUNC_OR(32, uint32_t, uint32_t, uint32_t); |
754 | ASAN_ATOMIC_FUNC_OR(64, uint64_t, uint64_t, uint64_t); | | 857 | ASAN_ATOMIC_FUNC_OR(64, uint64_t, uint64_t, uint64_t); |
755 | ASAN_ATOMIC_FUNC_OR(uint, unsigned int, unsigned int, unsigned int); | | 858 | ASAN_ATOMIC_FUNC_OR(uint, unsigned int, unsigned int, unsigned int); |
756 | ASAN_ATOMIC_FUNC_OR(ulong, unsigned long, unsigned long, unsigned long); | | 859 | ASAN_ATOMIC_FUNC_OR(ulong, unsigned long, unsigned long, unsigned long); |
757 | | | 860 | |
758 | ASAN_ATOMIC_FUNC_CAS(32, uint32_t, uint32_t, uint32_t); | | 861 | ASAN_ATOMIC_FUNC_CAS(32, uint32_t, uint32_t, uint32_t); |
759 | ASAN_ATOMIC_FUNC_CAS(64, uint64_t, uint64_t, uint64_t); | | 862 | ASAN_ATOMIC_FUNC_CAS(64, uint64_t, uint64_t, uint64_t); |
760 | ASAN_ATOMIC_FUNC_CAS(uint, unsigned int, unsigned int, unsigned int); | | 863 | ASAN_ATOMIC_FUNC_CAS(uint, unsigned int, unsigned int, unsigned int); |
761 | ASAN_ATOMIC_FUNC_CAS(ulong, unsigned long, unsigned long, unsigned long); | | 864 | ASAN_ATOMIC_FUNC_CAS(ulong, unsigned long, unsigned long, unsigned long); |
762 | ASAN_ATOMIC_FUNC_CAS(ptr, void *, void, void *); | | 865 | ASAN_ATOMIC_FUNC_CAS(ptr, void *, void, void *); |
763 | | | 866 | |
764 | ASAN_ATOMIC_FUNC_SWAP(32, uint32_t, uint32_t, uint32_t); | | 867 | ASAN_ATOMIC_FUNC_SWAP(32, uint32_t, uint32_t, uint32_t); |
765 | ASAN_ATOMIC_FUNC_SWAP(64, uint64_t, uint64_t, uint64_t); | | 868 | ASAN_ATOMIC_FUNC_SWAP(64, uint64_t, uint64_t, uint64_t); |
766 | ASAN_ATOMIC_FUNC_SWAP(uint, unsigned int, unsigned int, unsigned int); | | 869 | ASAN_ATOMIC_FUNC_SWAP(uint, unsigned int, unsigned int, unsigned int); |
767 | ASAN_ATOMIC_FUNC_SWAP(ulong, unsigned long, unsigned long, unsigned long); | | 870 | ASAN_ATOMIC_FUNC_SWAP(ulong, unsigned long, unsigned long, unsigned long); |
768 | ASAN_ATOMIC_FUNC_SWAP(ptr, void *, void, void *); | | 871 | ASAN_ATOMIC_FUNC_SWAP(ptr, void *, void, void *); |
769 | | | 872 | |
770 | ASAN_ATOMIC_FUNC_DEC(32, uint32_t, uint32_t) | | 873 | ASAN_ATOMIC_FUNC_DEC(32, uint32_t, uint32_t) |
771 | ASAN_ATOMIC_FUNC_DEC(64, uint64_t, uint64_t) | | 874 | ASAN_ATOMIC_FUNC_DEC(64, uint64_t, uint64_t) |
772 | ASAN_ATOMIC_FUNC_DEC(uint, unsigned int, unsigned int); | | 875 | ASAN_ATOMIC_FUNC_DEC(uint, unsigned int, unsigned int); |
773 | ASAN_ATOMIC_FUNC_DEC(ulong, unsigned long, unsigned long); | | 876 | ASAN_ATOMIC_FUNC_DEC(ulong, unsigned long, unsigned long); |
774 | ASAN_ATOMIC_FUNC_DEC(ptr, void *, void); | | 877 | ASAN_ATOMIC_FUNC_DEC(ptr, void *, void); |
775 | | | 878 | |
776 | ASAN_ATOMIC_FUNC_INC(32, uint32_t, uint32_t) | | 879 | ASAN_ATOMIC_FUNC_INC(32, uint32_t, uint32_t) |
777 | ASAN_ATOMIC_FUNC_INC(64, uint64_t, uint64_t) | | 880 | ASAN_ATOMIC_FUNC_INC(64, uint64_t, uint64_t) |
778 | ASAN_ATOMIC_FUNC_INC(uint, unsigned int, unsigned int); | | 881 | ASAN_ATOMIC_FUNC_INC(uint, unsigned int, unsigned int); |
779 | ASAN_ATOMIC_FUNC_INC(ulong, unsigned long, unsigned long); | | 882 | ASAN_ATOMIC_FUNC_INC(ulong, unsigned long, unsigned long); |
780 | ASAN_ATOMIC_FUNC_INC(ptr, void *, void); | | 883 | ASAN_ATOMIC_FUNC_INC(ptr, void *, void); |
781 | | | 884 | |
782 | /* -------------------------------------------------------------------------- */ | | 885 | /* -------------------------------------------------------------------------- */ |
783 | | | 886 | |
784 | #ifdef __HAVE_KASAN_INSTR_BUS | | 887 | #ifdef __HAVE_KASAN_INSTR_BUS |
785 | | | 888 | |
786 | #include <sys/bus.h> | | 889 | #include <sys/bus.h> |
787 | | | 890 | |
788 | #undef bus_space_read_multi_1 | | 891 | #undef bus_space_read_multi_1 |
789 | #undef bus_space_read_multi_2 | | 892 | #undef bus_space_read_multi_2 |
790 | #undef bus_space_read_multi_4 | | 893 | #undef bus_space_read_multi_4 |
791 | #undef bus_space_read_multi_8 | | 894 | #undef bus_space_read_multi_8 |
792 | #undef bus_space_read_multi_stream_1 | | 895 | #undef bus_space_read_multi_stream_1 |
793 | #undef bus_space_read_multi_stream_2 | | 896 | #undef bus_space_read_multi_stream_2 |
794 | #undef bus_space_read_multi_stream_4 | | 897 | #undef bus_space_read_multi_stream_4 |
795 | #undef bus_space_read_multi_stream_8 | | 898 | #undef bus_space_read_multi_stream_8 |
796 | #undef bus_space_read_region_1 | | 899 | #undef bus_space_read_region_1 |
797 | #undef bus_space_read_region_2 | | 900 | #undef bus_space_read_region_2 |
798 | #undef bus_space_read_region_4 | | 901 | #undef bus_space_read_region_4 |
799 | #undef bus_space_read_region_8 | | 902 | #undef bus_space_read_region_8 |
800 | #undef bus_space_read_region_stream_1 | | 903 | #undef bus_space_read_region_stream_1 |
801 | #undef bus_space_read_region_stream_2 | | 904 | #undef bus_space_read_region_stream_2 |
802 | #undef bus_space_read_region_stream_4 | | 905 | #undef bus_space_read_region_stream_4 |
803 | #undef bus_space_read_region_stream_8 | | 906 | #undef bus_space_read_region_stream_8 |
804 | #undef bus_space_write_multi_1 | | 907 | #undef bus_space_write_multi_1 |
805 | #undef bus_space_write_multi_2 | | 908 | #undef bus_space_write_multi_2 |
806 | #undef bus_space_write_multi_4 | | 909 | #undef bus_space_write_multi_4 |
807 | #undef bus_space_write_multi_8 | | 910 | #undef bus_space_write_multi_8 |
808 | #undef bus_space_write_multi_stream_1 | | 911 | #undef bus_space_write_multi_stream_1 |
809 | #undef bus_space_write_multi_stream_2 | | 912 | #undef bus_space_write_multi_stream_2 |
810 | #undef bus_space_write_multi_stream_4 | | 913 | #undef bus_space_write_multi_stream_4 |
811 | #undef bus_space_write_multi_stream_8 | | 914 | #undef bus_space_write_multi_stream_8 |
812 | #undef bus_space_write_region_1 | | 915 | #undef bus_space_write_region_1 |
813 | #undef bus_space_write_region_2 | | 916 | #undef bus_space_write_region_2 |
814 | #undef bus_space_write_region_4 | | 917 | #undef bus_space_write_region_4 |
815 | #undef bus_space_write_region_8 | | 918 | #undef bus_space_write_region_8 |
816 | #undef bus_space_write_region_stream_1 | | 919 | #undef bus_space_write_region_stream_1 |
817 | #undef bus_space_write_region_stream_2 | | 920 | #undef bus_space_write_region_stream_2 |
818 | #undef bus_space_write_region_stream_4 | | 921 | #undef bus_space_write_region_stream_4 |
819 | #undef bus_space_write_region_stream_8 | | 922 | #undef bus_space_write_region_stream_8 |
820 | | | 923 | |
821 | #define ASAN_BUS_READ_FUNC(bytes, bits) \ | | 924 | #define ASAN_BUS_READ_FUNC(bytes, bits) \ |
822 | void bus_space_read_multi_##bytes(bus_space_tag_t, bus_space_handle_t, \ | | 925 | void bus_space_read_multi_##bytes(bus_space_tag_t, bus_space_handle_t, \ |
823 | bus_size_t, uint##bits##_t *, bus_size_t); \ | | 926 | bus_size_t, uint##bits##_t *, bus_size_t); \ |
824 | void kasan_bus_space_read_multi_##bytes(bus_space_tag_t, \ | | 927 | void kasan_bus_space_read_multi_##bytes(bus_space_tag_t, \ |
825 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ | | 928 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ |
826 | void kasan_bus_space_read_multi_##bytes(bus_space_tag_t tag, \ | | 929 | void kasan_bus_space_read_multi_##bytes(bus_space_tag_t tag, \ |
827 | bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ | | 930 | bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ |
828 | bus_size_t count) \ | | 931 | bus_size_t count) \ |
829 | { \ | | 932 | { \ |
830 | kasan_shadow_check((uintptr_t)buf, \ | | 933 | kasan_shadow_check((uintptr_t)buf, \ |
831 | sizeof(uint##bits##_t) * count, false, __RET_ADDR); \ | | 934 | sizeof(uint##bits##_t) * count, false, __RET_ADDR); \ |
832 | bus_space_read_multi_##bytes(tag, hnd, size, buf, count); \ | | 935 | bus_space_read_multi_##bytes(tag, hnd, size, buf, count); \ |
833 | } \ | | 936 | } \ |
834 | void bus_space_read_multi_stream_##bytes(bus_space_tag_t, \ | | 937 | void bus_space_read_multi_stream_##bytes(bus_space_tag_t, \ |
835 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ | | 938 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ |
836 | void kasan_bus_space_read_multi_stream_##bytes(bus_space_tag_t, \ | | 939 | void kasan_bus_space_read_multi_stream_##bytes(bus_space_tag_t, \ |
837 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ | | 940 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ |
838 | void kasan_bus_space_read_multi_stream_##bytes(bus_space_tag_t tag, \ | | 941 | void kasan_bus_space_read_multi_stream_##bytes(bus_space_tag_t tag, \ |
839 | bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ | | 942 | bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ |
840 | bus_size_t count) \ | | 943 | bus_size_t count) \ |
841 | { \ | | 944 | { \ |
842 | kasan_shadow_check((uintptr_t)buf, \ | | 945 | kasan_shadow_check((uintptr_t)buf, \ |
843 | sizeof(uint##bits##_t) * count, false, __RET_ADDR); \ | | 946 | sizeof(uint##bits##_t) * count, false, __RET_ADDR); \ |
844 | bus_space_read_multi_stream_##bytes(tag, hnd, size, buf, count);\ | | 947 | bus_space_read_multi_stream_##bytes(tag, hnd, size, buf, count);\ |
845 | } \ | | 948 | } \ |
846 | void bus_space_read_region_##bytes(bus_space_tag_t, bus_space_handle_t, \ | | 949 | void bus_space_read_region_##bytes(bus_space_tag_t, bus_space_handle_t, \ |
847 | bus_size_t, uint##bits##_t *, bus_size_t); \ | | 950 | bus_size_t, uint##bits##_t *, bus_size_t); \ |
848 | void kasan_bus_space_read_region_##bytes(bus_space_tag_t, \ | | 951 | void kasan_bus_space_read_region_##bytes(bus_space_tag_t, \ |
849 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ | | 952 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ |
850 | void kasan_bus_space_read_region_##bytes(bus_space_tag_t tag, \ | | 953 | void kasan_bus_space_read_region_##bytes(bus_space_tag_t tag, \ |
851 | bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ | | 954 | bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ |
852 | bus_size_t count) \ | | 955 | bus_size_t count) \ |
853 | { \ | | 956 | { \ |
854 | kasan_shadow_check((uintptr_t)buf, \ | | 957 | kasan_shadow_check((uintptr_t)buf, \ |
855 | sizeof(uint##bits##_t) * count, false, __RET_ADDR); \ | | 958 | sizeof(uint##bits##_t) * count, false, __RET_ADDR); \ |
856 | bus_space_read_region_##bytes(tag, hnd, size, buf, count); \ | | 959 | bus_space_read_region_##bytes(tag, hnd, size, buf, count); \ |
857 | } \ | | 960 | } \ |
858 | void bus_space_read_region_stream_##bytes(bus_space_tag_t, \ | | 961 | void bus_space_read_region_stream_##bytes(bus_space_tag_t, \ |
859 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ | | 962 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ |
860 | void kasan_bus_space_read_region_stream_##bytes(bus_space_tag_t, \ | | 963 | void kasan_bus_space_read_region_stream_##bytes(bus_space_tag_t, \ |
861 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ | | 964 | bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ |
862 | void kasan_bus_space_read_region_stream_##bytes(bus_space_tag_t tag, \ | | 965 | void kasan_bus_space_read_region_stream_##bytes(bus_space_tag_t tag, \ |
863 | bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ | | 966 | bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ |
864 | bus_size_t count) \ | | 967 | bus_size_t count) \ |
865 | { \ | | 968 | { \ |
866 | kasan_shadow_check((uintptr_t)buf, \ | | 969 | kasan_shadow_check((uintptr_t)buf, \ |
867 | sizeof(uint##bits##_t) * count, false, __RET_ADDR); \ | | 970 | sizeof(uint##bits##_t) * count, false, __RET_ADDR); \ |
868 | bus_space_read_region_stream_##bytes(tag, hnd, size, buf, count);\ | | 971 | bus_space_read_region_stream_##bytes(tag, hnd, size, buf, count);\ |
869 | } | | 972 | } |
870 | | | 973 | |
871 | #define ASAN_BUS_WRITE_FUNC(bytes, bits) \ | | 974 | #define ASAN_BUS_WRITE_FUNC(bytes, bits) \ |
872 | void bus_space_write_multi_##bytes(bus_space_tag_t, bus_space_handle_t, \ | | 975 | void bus_space_write_multi_##bytes(bus_space_tag_t, bus_space_handle_t, \ |
873 | bus_size_t, const uint##bits##_t *, bus_size_t); \ | | 976 | bus_size_t, const uint##bits##_t *, bus_size_t); \ |
874 | void kasan_bus_space_write_multi_##bytes(bus_space_tag_t, \ | | 977 | void kasan_bus_space_write_multi_##bytes(bus_space_tag_t, \ |
875 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ | | 978 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ |
876 | void kasan_bus_space_write_multi_##bytes(bus_space_tag_t tag, \ | | 979 | void kasan_bus_space_write_multi_##bytes(bus_space_tag_t tag, \ |
877 | bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ | | 980 | bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ |
878 | bus_size_t count) \ | | 981 | bus_size_t count) \ |
879 | { \ | | 982 | { \ |
880 | kasan_shadow_check((uintptr_t)buf, \ | | 983 | kasan_shadow_check((uintptr_t)buf, \ |
881 | sizeof(uint##bits##_t) * count, true, __RET_ADDR); \ | | 984 | sizeof(uint##bits##_t) * count, true, __RET_ADDR); \ |
882 | bus_space_write_multi_##bytes(tag, hnd, size, buf, count); \ | | 985 | bus_space_write_multi_##bytes(tag, hnd, size, buf, count); \ |
883 | } \ | | 986 | } \ |
884 | void bus_space_write_multi_stream_##bytes(bus_space_tag_t, \ | | 987 | void bus_space_write_multi_stream_##bytes(bus_space_tag_t, \ |
885 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ | | 988 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ |
886 | void kasan_bus_space_write_multi_stream_##bytes(bus_space_tag_t, \ | | 989 | void kasan_bus_space_write_multi_stream_##bytes(bus_space_tag_t, \ |
887 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ | | 990 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ |
888 | void kasan_bus_space_write_multi_stream_##bytes(bus_space_tag_t tag, \ | | 991 | void kasan_bus_space_write_multi_stream_##bytes(bus_space_tag_t tag, \ |
889 | bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ | | 992 | bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ |
890 | bus_size_t count) \ | | 993 | bus_size_t count) \ |
891 | { \ | | 994 | { \ |
892 | kasan_shadow_check((uintptr_t)buf, \ | | 995 | kasan_shadow_check((uintptr_t)buf, \ |
893 | sizeof(uint##bits##_t) * count, true, __RET_ADDR); \ | | 996 | sizeof(uint##bits##_t) * count, true, __RET_ADDR); \ |
894 | bus_space_write_multi_stream_##bytes(tag, hnd, size, buf, count);\ | | 997 | bus_space_write_multi_stream_##bytes(tag, hnd, size, buf, count);\ |
895 | } \ | | 998 | } \ |
896 | void bus_space_write_region_##bytes(bus_space_tag_t, bus_space_handle_t,\ | | 999 | void bus_space_write_region_##bytes(bus_space_tag_t, bus_space_handle_t,\ |
897 | bus_size_t, const uint##bits##_t *, bus_size_t); \ | | 1000 | bus_size_t, const uint##bits##_t *, bus_size_t); \ |
898 | void kasan_bus_space_write_region_##bytes(bus_space_tag_t, \ | | 1001 | void kasan_bus_space_write_region_##bytes(bus_space_tag_t, \ |
899 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ | | 1002 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ |
900 | void kasan_bus_space_write_region_##bytes(bus_space_tag_t tag, \ | | 1003 | void kasan_bus_space_write_region_##bytes(bus_space_tag_t tag, \ |
901 | bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ | | 1004 | bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ |
902 | bus_size_t count) \ | | 1005 | bus_size_t count) \ |
903 | { \ | | 1006 | { \ |
904 | kasan_shadow_check((uintptr_t)buf, \ | | 1007 | kasan_shadow_check((uintptr_t)buf, \ |
905 | sizeof(uint##bits##_t) * count, true, __RET_ADDR); \ | | 1008 | sizeof(uint##bits##_t) * count, true, __RET_ADDR); \ |
906 | bus_space_write_region_##bytes(tag, hnd, size, buf, count); \ | | 1009 | bus_space_write_region_##bytes(tag, hnd, size, buf, count); \ |
907 | } \ | | 1010 | } \ |
908 | void bus_space_write_region_stream_##bytes(bus_space_tag_t, \ | | 1011 | void bus_space_write_region_stream_##bytes(bus_space_tag_t, \ |
909 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ | | 1012 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ |
910 | void kasan_bus_space_write_region_stream_##bytes(bus_space_tag_t, \ | | 1013 | void kasan_bus_space_write_region_stream_##bytes(bus_space_tag_t, \ |
911 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ | | 1014 | bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ |
912 | void kasan_bus_space_write_region_stream_##bytes(bus_space_tag_t tag, \ | | 1015 | void kasan_bus_space_write_region_stream_##bytes(bus_space_tag_t tag, \ |
913 | bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ | | 1016 | bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ |
914 | bus_size_t count) \ | | 1017 | bus_size_t count) \ |
915 | { \ | | 1018 | { \ |
916 | kasan_shadow_check((uintptr_t)buf, \ | | 1019 | kasan_shadow_check((uintptr_t)buf, \ |
917 | sizeof(uint##bits##_t) * count, true, __RET_ADDR); \ | | 1020 | sizeof(uint##bits##_t) * count, true, __RET_ADDR); \ |
918 | bus_space_write_region_stream_##bytes(tag, hnd, size, buf, count);\ | | 1021 | bus_space_write_region_stream_##bytes(tag, hnd, size, buf, count);\ |
919 | } | | 1022 | } |
920 | | | 1023 | |
921 | ASAN_BUS_READ_FUNC(1, 8) | | 1024 | ASAN_BUS_READ_FUNC(1, 8) |
922 | ASAN_BUS_READ_FUNC(2, 16) | | 1025 | ASAN_BUS_READ_FUNC(2, 16) |
923 | ASAN_BUS_READ_FUNC(4, 32) | | 1026 | ASAN_BUS_READ_FUNC(4, 32) |
924 | ASAN_BUS_READ_FUNC(8, 64) | | 1027 | ASAN_BUS_READ_FUNC(8, 64) |
925 | | | 1028 | |
926 | ASAN_BUS_WRITE_FUNC(1, 8) | | 1029 | ASAN_BUS_WRITE_FUNC(1, 8) |
927 | ASAN_BUS_WRITE_FUNC(2, 16) | | 1030 | ASAN_BUS_WRITE_FUNC(2, 16) |
928 | ASAN_BUS_WRITE_FUNC(4, 32) | | 1031 | ASAN_BUS_WRITE_FUNC(4, 32) |
929 | ASAN_BUS_WRITE_FUNC(8, 64) | | 1032 | ASAN_BUS_WRITE_FUNC(8, 64) |
930 | | | 1033 | |
931 | #endif /* __HAVE_KASAN_INSTR_BUS */ | | 1034 | #endif /* __HAVE_KASAN_INSTR_BUS */ |
932 | | | 1035 | |
933 | /* -------------------------------------------------------------------------- */ | | 1036 | /* -------------------------------------------------------------------------- */ |
934 | | | 1037 | |
935 | #ifdef __HAVE_KASAN_INSTR_DMA | | 1038 | #ifdef __HAVE_KASAN_INSTR_DMA |
936 | | | 1039 | |
937 | #include <sys/mbuf.h> | | 1040 | #include <sys/mbuf.h> |
938 | | | 1041 | |
939 | static void | | 1042 | static void |
940 | kasan_dma_sync_linear(uint8_t *buf, bus_addr_t offset, bus_size_t len, | | 1043 | kasan_dma_sync_linear(uint8_t *buf, bus_addr_t offset, bus_size_t len, |
941 | bool write, uintptr_t pc) | | 1044 | bool write, uintptr_t pc) |
942 | { | | 1045 | { |
943 | kasan_shadow_check((uintptr_t)(buf + offset), len, write, pc); | | 1046 | kasan_shadow_check((uintptr_t)(buf + offset), len, write, pc); |
944 | } | | 1047 | } |
945 | | | 1048 | |
946 | static void | | 1049 | static void |
947 | kasan_dma_sync_mbuf(struct mbuf *m, bus_addr_t offset, bus_size_t len, | | 1050 | kasan_dma_sync_mbuf(struct mbuf *m, bus_addr_t offset, bus_size_t len, |
948 | bool write, uintptr_t pc) | | 1051 | bool write, uintptr_t pc) |
949 | { | | 1052 | { |
950 | bus_addr_t minlen; | | 1053 | bus_addr_t minlen; |
951 | | | 1054 | |
952 | for (; m != NULL && len != 0; m = m->m_next) { | | 1055 | for (; m != NULL && len != 0; m = m->m_next) { |
953 | kasan_shadow_check((uintptr_t)m, sizeof(*m), false, pc); | | 1056 | kasan_shadow_check((uintptr_t)m, sizeof(*m), false, pc); |
954 | | | 1057 | |
955 | if (offset >= m->m_len) { | | 1058 | if (offset >= m->m_len) { |
956 | offset -= m->m_len; | | 1059 | offset -= m->m_len; |
957 | continue; | | 1060 | continue; |
958 | } | | 1061 | } |
959 | | | 1062 | |
960 | minlen = MIN(len, m->m_len - offset); | | 1063 | minlen = MIN(len, m->m_len - offset); |
961 | kasan_shadow_check((uintptr_t)(mtod(m, char *) + offset), | | 1064 | kasan_shadow_check((uintptr_t)(mtod(m, char *) + offset), |
962 | minlen, write, pc); | | 1065 | minlen, write, pc); |
963 | | | 1066 | |
964 | offset = 0; | | 1067 | offset = 0; |
965 | len -= minlen; | | 1068 | len -= minlen; |
966 | } | | 1069 | } |
967 | } | | 1070 | } |
968 | | | 1071 | |
969 | static void | | 1072 | static void |
970 | kasan_dma_sync_uio(struct uio *uio, bus_addr_t offset, bus_size_t len, | | 1073 | kasan_dma_sync_uio(struct uio *uio, bus_addr_t offset, bus_size_t len, |
971 | bool write, uintptr_t pc) | | 1074 | bool write, uintptr_t pc) |
972 | { | | 1075 | { |
973 | bus_size_t minlen, resid; | | 1076 | bus_size_t minlen, resid; |
974 | struct iovec *iov; | | 1077 | struct iovec *iov; |
975 | int i; | | 1078 | int i; |
976 | | | 1079 | |
977 | if (uio->uio_vmspace != NULL) | | 1080 | if (uio->uio_vmspace != NULL) |
978 | return; | | 1081 | return; |
979 | | | 1082 | |
980 | kasan_shadow_check((uintptr_t)uio, sizeof(struct uio), false, pc); | | 1083 | kasan_shadow_check((uintptr_t)uio, sizeof(struct uio), false, pc); |
981 | | | 1084 | |
982 | resid = uio->uio_resid; | | 1085 | resid = uio->uio_resid; |
983 | iov = uio->uio_iov; | | 1086 | iov = uio->uio_iov; |
984 | | | 1087 | |
985 | for (i = 0; i < uio->uio_iovcnt && resid != 0; i++) { | | 1088 | for (i = 0; i < uio->uio_iovcnt && resid != 0; i++) { |
986 | kasan_shadow_check((uintptr_t)&iov[i], sizeof(iov[i]), | | 1089 | kasan_shadow_check((uintptr_t)&iov[i], sizeof(iov[i]), |
987 | false, pc); | | 1090 | false, pc); |
988 | minlen = MIN(resid, iov[i].iov_len); | | 1091 | minlen = MIN(resid, iov[i].iov_len); |
989 | kasan_shadow_check((uintptr_t)iov[i].iov_base, minlen, | | 1092 | kasan_shadow_check((uintptr_t)iov[i].iov_base, minlen, |
990 | write, pc); | | 1093 | write, pc); |
991 | resid -= minlen; | | 1094 | resid -= minlen; |
992 | } | | 1095 | } |
993 | } | | 1096 | } |
994 | | | 1097 | |
995 | void | | 1098 | void |
996 | kasan_dma_sync(bus_dmamap_t map, bus_addr_t offset, bus_size_t len, int ops) | | 1099 | kasan_dma_sync(bus_dmamap_t map, bus_addr_t offset, bus_size_t len, int ops) |
997 | { | | 1100 | { |
998 | bool write = (ops & (BUS_DMASYNC_PREWRITE|BUS_DMASYNC_POSTWRITE)) != 0; | | 1101 | bool write = (ops & (BUS_DMASYNC_PREWRITE|BUS_DMASYNC_POSTWRITE)) != 0; |
999 | | | 1102 | |
1000 | switch (map->dm_buftype) { | | 1103 | switch (map->dm_buftype) { |
1001 | case KASAN_DMA_LINEAR: | | 1104 | case KASAN_DMA_LINEAR: |
1002 | kasan_dma_sync_linear(map->dm_buf, offset, len, write, | | 1105 | kasan_dma_sync_linear(map->dm_buf, offset, len, write, |
1003 | __RET_ADDR); | | 1106 | __RET_ADDR); |
1004 | break; | | 1107 | break; |
1005 | case KASAN_DMA_MBUF: | | 1108 | case KASAN_DMA_MBUF: |
1006 | kasan_dma_sync_mbuf(map->dm_buf, offset, len, write, | | 1109 | kasan_dma_sync_mbuf(map->dm_buf, offset, len, write, |
1007 | __RET_ADDR); | | 1110 | __RET_ADDR); |
1008 | break; | | 1111 | break; |
1009 | case KASAN_DMA_UIO: | | 1112 | case KASAN_DMA_UIO: |
1010 | kasan_dma_sync_uio(map->dm_buf, offset, len, write, | | 1113 | kasan_dma_sync_uio(map->dm_buf, offset, len, write, |
1011 | __RET_ADDR); | | 1114 | __RET_ADDR); |
1012 | break; | | 1115 | break; |
1013 | case KASAN_DMA_RAW: | | 1116 | case KASAN_DMA_RAW: |
1014 | break; | | 1117 | break; |
1015 | default: | | 1118 | default: |
1016 | panic("%s: impossible", __func__); | | 1119 | panic("%s: impossible", __func__); |
1017 | } | | 1120 | } |
1018 | } | | 1121 | } |
1019 | | | 1122 | |
1020 | void | | 1123 | void |
1021 | kasan_dma_load(bus_dmamap_t map, void *buf, bus_size_t buflen, int type) | | 1124 | kasan_dma_load(bus_dmamap_t map, void *buf, bus_size_t buflen, int type) |
1022 | { | | 1125 | { |
1023 | map->dm_buf = buf; | | 1126 | map->dm_buf = buf; |
1024 | map->dm_buflen = buflen; | | 1127 | map->dm_buflen = buflen; |
1025 | map->dm_buftype = type; | | 1128 | map->dm_buftype = type; |
1026 | } | | 1129 | } |
1027 | | | 1130 | |
1028 | #endif /* __HAVE_KASAN_INSTR_DMA */ | | 1131 | #endif /* __HAVE_KASAN_INSTR_DMA */ |
1029 | | | 1132 | |
1030 | /* -------------------------------------------------------------------------- */ | | 1133 | /* -------------------------------------------------------------------------- */ |
1031 | | | 1134 | |
1032 | void __asan_register_globals(struct __asan_global *, size_t); | | 1135 | void __asan_register_globals(struct __asan_global *, size_t); |
1033 | void __asan_unregister_globals(struct __asan_global *, size_t); | | 1136 | void __asan_unregister_globals(struct __asan_global *, size_t); |
1034 | | | 1137 | |
1035 | void | | 1138 | void |
1036 | __asan_register_globals(struct __asan_global *globals, size_t n) | | 1139 | __asan_register_globals(struct __asan_global *globals, size_t n) |
1037 | { | | 1140 | { |
1038 | size_t i; | | 1141 | size_t i; |
1039 | | | 1142 | |
1040 | for (i = 0; i < n; i++) { | | 1143 | for (i = 0; i < n; i++) { |
1041 | kasan_mark(globals[i].beg, globals[i].size, | | 1144 | kasan_mark(globals[i].beg, globals[i].size, |
1042 | globals[i].size_with_redzone, KASAN_GENERIC_REDZONE); | | 1145 | globals[i].size_with_redzone, KASAN_GENERIC_REDZONE); |
1043 | } | | 1146 | } |
1044 | } | | 1147 | } |
1045 | | | 1148 | |
1046 | void | | 1149 | void |
1047 | __asan_unregister_globals(struct __asan_global *globals, size_t n) | | 1150 | __asan_unregister_globals(struct __asan_global *globals, size_t n) |
1048 | { | | 1151 | { |
1049 | /* never called */ | | 1152 | /* never called */ |
1050 | } | | 1153 | } |
1051 | | | 1154 | |
1052 | #define ASAN_LOAD_STORE(size) \ | | 1155 | #define ASAN_LOAD_STORE(size) \ |
1053 | void __asan_load##size(unsigned long); \ | | 1156 | void __asan_load##size(unsigned long); \ |
1054 | void __asan_load##size(unsigned long addr) \ | | 1157 | void __asan_load##size(unsigned long addr) \ |
1055 | { \ | | 1158 | { \ |
1056 | kasan_shadow_check(addr, size, false, __RET_ADDR);\ | | 1159 | kasan_shadow_check(addr, size, false, __RET_ADDR);\ |
1057 | } \ | | 1160 | } \ |
1058 | void __asan_load##size##_noabort(unsigned long); \ | | 1161 | void __asan_load##size##_noabort(unsigned long); \ |
1059 | void __asan_load##size##_noabort(unsigned long addr) \ | | 1162 | void __asan_load##size##_noabort(unsigned long addr) \ |
1060 | { \ | | 1163 | { \ |
1061 | kasan_shadow_check(addr, size, false, __RET_ADDR);\ | | 1164 | kasan_shadow_check(addr, size, false, __RET_ADDR);\ |
1062 | } \ | | 1165 | } \ |
1063 | void __asan_store##size(unsigned long); \ | | 1166 | void __asan_store##size(unsigned long); \ |
1064 | void __asan_store##size(unsigned long addr) \ | | 1167 | void __asan_store##size(unsigned long addr) \ |
1065 | { \ | | 1168 | { \ |
1066 | kasan_shadow_check(addr, size, true, __RET_ADDR);\ | | 1169 | kasan_shadow_check(addr, size, true, __RET_ADDR);\ |
1067 | } \ | | 1170 | } \ |
1068 | void __asan_store##size##_noabort(unsigned long); \ | | 1171 | void __asan_store##size##_noabort(unsigned long); \ |
1069 | void __asan_store##size##_noabort(unsigned long addr) \ | | 1172 | void __asan_store##size##_noabort(unsigned long addr) \ |
1070 | { \ | | 1173 | { \ |
1071 | kasan_shadow_check(addr, size, true, __RET_ADDR);\ | | 1174 | kasan_shadow_check(addr, size, true, __RET_ADDR);\ |
1072 | } | | 1175 | } |
1073 | | | 1176 | |
1074 | ASAN_LOAD_STORE(1); | | 1177 | ASAN_LOAD_STORE(1); |
1075 | ASAN_LOAD_STORE(2); | | 1178 | ASAN_LOAD_STORE(2); |
1076 | ASAN_LOAD_STORE(4); | | 1179 | ASAN_LOAD_STORE(4); |
1077 | ASAN_LOAD_STORE(8); | | 1180 | ASAN_LOAD_STORE(8); |
1078 | ASAN_LOAD_STORE(16); | | 1181 | ASAN_LOAD_STORE(16); |
1079 | | | 1182 | |
1080 | void __asan_loadN(unsigned long, size_t); | | 1183 | void __asan_loadN(unsigned long, size_t); |
1081 | void __asan_loadN_noabort(unsigned long, size_t); | | 1184 | void __asan_loadN_noabort(unsigned long, size_t); |
1082 | void __asan_storeN(unsigned long, size_t); | | 1185 | void __asan_storeN(unsigned long, size_t); |
1083 | void __asan_storeN_noabort(unsigned long, size_t); | | 1186 | void __asan_storeN_noabort(unsigned long, size_t); |
1084 | void __asan_handle_no_return(void); | | 1187 | void __asan_handle_no_return(void); |
1085 | | | 1188 | |
1086 | void | | 1189 | void |
1087 | __asan_loadN(unsigned long addr, size_t size) | | 1190 | __asan_loadN(unsigned long addr, size_t size) |
1088 | { | | 1191 | { |
1089 | kasan_shadow_check(addr, size, false, __RET_ADDR); | | 1192 | kasan_shadow_check(addr, size, false, __RET_ADDR); |
1090 | } | | 1193 | } |
1091 | | | 1194 | |
1092 | void | | 1195 | void |
1093 | __asan_loadN_noabort(unsigned long addr, size_t size) | | 1196 | __asan_loadN_noabort(unsigned long addr, size_t size) |
1094 | { | | 1197 | { |
1095 | kasan_shadow_check(addr, size, false, __RET_ADDR); | | 1198 | kasan_shadow_check(addr, size, false, __RET_ADDR); |
1096 | } | | 1199 | } |
1097 | | | 1200 | |
1098 | void | | 1201 | void |
1099 | __asan_storeN(unsigned long addr, size_t size) | | 1202 | __asan_storeN(unsigned long addr, size_t size) |
1100 | { | | 1203 | { |
1101 | kasan_shadow_check(addr, size, true, __RET_ADDR); | | 1204 | kasan_shadow_check(addr, size, true, __RET_ADDR); |
1102 | } | | 1205 | } |
1103 | | | 1206 | |
1104 | void | | 1207 | void |
1105 | __asan_storeN_noabort(unsigned long addr, size_t size) | | 1208 | __asan_storeN_noabort(unsigned long addr, size_t size) |
1106 | { | | 1209 | { |
1107 | kasan_shadow_check(addr, size, true, __RET_ADDR); | | 1210 | kasan_shadow_check(addr, size, true, __RET_ADDR); |
1108 | } | | 1211 | } |
1109 | | | 1212 | |
1110 | void | | 1213 | void |
1111 | __asan_handle_no_return(void) | | 1214 | __asan_handle_no_return(void) |
1112 | { | | 1215 | { |
1113 | /* nothing */ | | 1216 | /* nothing */ |
1114 | } | | 1217 | } |
1115 | | | 1218 | |
1116 | #define ASAN_SET_SHADOW(byte) \ | | 1219 | #define ASAN_SET_SHADOW(byte) \ |
1117 | void __asan_set_shadow_##byte(void *, size_t); \ | | 1220 | void __asan_set_shadow_##byte(void *, size_t); \ |
1118 | void __asan_set_shadow_##byte(void *addr, size_t size) \ | | 1221 | void __asan_set_shadow_##byte(void *addr, size_t size) \ |
1119 | { \ | | 1222 | { \ |
1120 | __builtin_memset((void *)addr, 0x##byte, size); \ | | 1223 | __builtin_memset((void *)addr, 0x##byte, size); \ |
1121 | } | | 1224 | } |
1122 | | | 1225 | |
1123 | ASAN_SET_SHADOW(00); | | 1226 | ASAN_SET_SHADOW(00); |
1124 | ASAN_SET_SHADOW(f1); | | 1227 | ASAN_SET_SHADOW(f1); |
1125 | ASAN_SET_SHADOW(f2); | | 1228 | ASAN_SET_SHADOW(f2); |
1126 | ASAN_SET_SHADOW(f3); | | 1229 | ASAN_SET_SHADOW(f3); |
1127 | ASAN_SET_SHADOW(f5); | | 1230 | ASAN_SET_SHADOW(f5); |
1128 | ASAN_SET_SHADOW(f8); | | 1231 | ASAN_SET_SHADOW(f8); |
1129 | | | 1232 | |
1130 | void __asan_poison_stack_memory(const void *, size_t); | | 1233 | void __asan_poison_stack_memory(const void *, size_t); |
1131 | void __asan_unpoison_stack_memory(const void *, size_t); | | 1234 | void __asan_unpoison_stack_memory(const void *, size_t); |
1132 | | | 1235 | |
1133 | void __asan_poison_stack_memory(const void *addr, size_t size) | | 1236 | void __asan_poison_stack_memory(const void *addr, size_t size) |
1134 | { | | 1237 | { |
1135 | size = roundup(size, KASAN_SHADOW_SCALE_SIZE); | | 1238 | size = roundup(size, KASAN_SHADOW_SCALE_SIZE); |
1136 | kasan_shadow_Nbyte_fill(addr, size, KASAN_USE_AFTER_SCOPE); | | 1239 | kasan_shadow_Nbyte_fill(addr, size, KASAN_USE_AFTER_SCOPE); |
1137 | } | | 1240 | } |
1138 | | | 1241 | |
1139 | void __asan_unpoison_stack_memory(const void *addr, size_t size) | | 1242 | void __asan_unpoison_stack_memory(const void *addr, size_t size) |
1140 | { | | 1243 | { |
1141 | kasan_shadow_Nbyte_markvalid(addr, size); | | 1244 | kasan_shadow_Nbyte_markvalid(addr, size); |
1142 | } | | 1245 | } |