FreeBSD kernel kern code
subr_asan.c
Go to the documentation of this file.
1/* $NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $ */
2
3/*
4 * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net
5 * All rights reserved.
6 *
7 * This code is part of the KASAN subsystem of the NetBSD kernel.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#define SAN_RUNTIME
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD$");
35#if 0
36__KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $");
37#endif
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/asan.h>
42#include <sys/kernel.h>
43#include <sys/stack.h>
44#include <sys/sysctl.h>
45
46#include <machine/asan.h>
47
48/* ASAN constants. Part of the compiler ABI. */
49#define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE - 1)
50#define KASAN_ALLOCA_SCALE_SIZE 32
51
52/* ASAN ABI version. */
53#if defined(__clang__) && (__clang_major__ - 0 >= 6)
54#define ASAN_ABI_VERSION 8
55#elif __GNUC_PREREQ__(7, 1) && !defined(__clang__)
56#define ASAN_ABI_VERSION 8
57#elif __GNUC_PREREQ__(6, 1) && !defined(__clang__)
58#define ASAN_ABI_VERSION 6
59#else
60#error "Unsupported compiler version"
61#endif
62
63#define __RET_ADDR (unsigned long)__builtin_return_address(0)
64
65/* Global variable descriptor. Part of the compiler ABI. */
67 const char *filename;
70};
71
73 const void *beg; /* address of the global variable */
74 size_t size; /* size of the global variable */
75 size_t size_with_redzone; /* size with the redzone */
76 const void *name; /* name of the variable */
77 const void *module_name; /* name of the module where the var is declared */
78 unsigned long has_dynamic_init; /* the var has dyn initializer (c++) */
80#if ASAN_ABI_VERSION >= 7
81 uintptr_t odr_indicator; /* the address of the ODR indicator symbol */
82#endif
83};
84
85FEATURE(kasan, "Kernel address sanitizer");
86
87static SYSCTL_NODE(_debug, OID_AUTO, kasan, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
88 "KASAN options");
89
90static int panic_on_violation = 1;
91SYSCTL_INT(_debug_kasan, OID_AUTO, panic_on_violation, CTLFLAG_RDTUN,
93 "Panic if an invalid access is detected");
94
95static bool kasan_enabled __read_mostly = false;
96
97/* -------------------------------------------------------------------------- */
98
99void
100kasan_shadow_map(vm_offset_t addr, size_t size)
101{
102 size_t sz, npages, i;
103 vm_offset_t sva, eva;
104
105 KASSERT(addr % KASAN_SHADOW_SCALE == 0,
106 ("%s: invalid address %#lx", __func__, addr));
107
108 sz = roundup(size, KASAN_SHADOW_SCALE) / KASAN_SHADOW_SCALE;
109
110 sva = kasan_md_addr_to_shad(addr);
111 eva = kasan_md_addr_to_shad(addr) + sz;
112
113 sva = rounddown(sva, PAGE_SIZE);
114 eva = roundup(eva, PAGE_SIZE);
115
116 npages = (eva - sva) / PAGE_SIZE;
117
118 KASSERT(sva >= KASAN_MIN_ADDRESS && eva < KASAN_MAX_ADDRESS,
119 ("%s: invalid address range %#lx-%#lx", __func__, sva, eva));
120
121 for (i = 0; i < npages; i++)
122 pmap_san_enter(sva + ptoa(i));
123}
124
125void
127{
128 int disabled;
129
130 disabled = 0;
131 TUNABLE_INT_FETCH("debug.kasan.disabled", &disabled);
132 if (disabled)
133 return;
134
135 /* MD initialization. */
136 kasan_md_init();
137
138 /* Now officially enabled. */
139 kasan_enabled = true;
140}
141
142static inline const char *
143kasan_code_name(uint8_t code)
144{
145 switch (code) {
146 case KASAN_GENERIC_REDZONE:
147 return "GenericRedZone";
148 case KASAN_MALLOC_REDZONE:
149 return "MallocRedZone";
150 case KASAN_KMEM_REDZONE:
151 return "KmemRedZone";
152 case KASAN_UMA_FREED:
153 return "UMAUseAfterFree";
154 case KASAN_KSTACK_FREED:
155 return "KernelStack";
156 case KASAN_EXEC_ARGS_FREED:
157 return "ExecKVA";
158 case 1 ... 7:
159 return "RedZonePartial";
160 case KASAN_STACK_LEFT:
161 return "StackLeft";
162 case KASAN_STACK_MID:
163 return "StackMiddle";
164 case KASAN_STACK_RIGHT:
165 return "StackRight";
166 case KASAN_USE_AFTER_RET:
167 return "UseAfterRet";
168 case KASAN_USE_AFTER_SCOPE:
169 return "UseAfterScope";
170 default:
171 return "Unknown";
172 }
173}
174
175#define REPORT(f, ...) do { \
176 if (panic_on_violation) { \
177 kasan_enabled = false; \
178 panic(f, __VA_ARGS__); \
179 } else { \
180 struct stack st; \
181 \
182 stack_save(&st); \
183 printf(f "\n", __VA_ARGS__); \
184 stack_print_ddb(&st); \
185 } \
186} while (0)
187
188static void
189kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc,
190 uint8_t code)
191{
192 REPORT("ASan: Invalid access, %zu-byte %s at %#lx, %s(%x)",
193 size, (write ? "write" : "read"), addr, kasan_code_name(code),
194 code);
195}
196
197static __always_inline void
199{
200 int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr);
201 int8_t last = (addr & KASAN_SHADOW_MASK) + 1;
202
203 *byte = last;
204}
205
206static __always_inline void
207kasan_shadow_Nbyte_markvalid(const void *addr, size_t size)
208{
209 size_t i;
210
211 for (i = 0; i < size; i++) {
212 kasan_shadow_1byte_markvalid((unsigned long)addr + i);
213 }
214}
215
216static __always_inline void
217kasan_shadow_Nbyte_fill(const void *addr, size_t size, uint8_t code)
218{
219 void *shad;
220
221 if (__predict_false(size == 0))
222 return;
223 if (__predict_false(kasan_md_unsupported((vm_offset_t)addr)))
224 return;
225
226 KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0,
227 ("%s: invalid address %p", __func__, addr));
228 KASSERT(size % KASAN_SHADOW_SCALE == 0,
229 ("%s: invalid size %zu", __func__, size));
230
231 shad = (void *)kasan_md_addr_to_shad((uintptr_t)addr);
232 size = size >> KASAN_SHADOW_SCALE_SHIFT;
233
234 __builtin_memset(shad, code, size);
235}
236
237/*
238 * In an area of size 'sz_with_redz', mark the 'size' first bytes as valid,
239 * and the rest as invalid. There are generally two use cases:
240 *
241 * o kasan_mark(addr, origsize, size, code), with origsize < size. This marks
242 * the redzone at the end of the buffer as invalid. If the entire is to be
243 * marked invalid, origsize will be 0.
244 *
245 * o kasan_mark(addr, size, size, 0). This marks the entire buffer as valid.
246 */
247void
248kasan_mark(const void *addr, size_t size, size_t redzsize, uint8_t code)
249{
250 size_t i, n, redz;
251 int8_t *shad;
252
253 if ((vm_offset_t)addr >= DMAP_MIN_ADDRESS &&
254 (vm_offset_t)addr < DMAP_MAX_ADDRESS)
255 return;
256
257 KASSERT((vm_offset_t)addr >= VM_MIN_KERNEL_ADDRESS &&
258 (vm_offset_t)addr < VM_MAX_KERNEL_ADDRESS,
259 ("%s: invalid address %p", __func__, addr));
260 KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0,
261 ("%s: invalid address %p", __func__, addr));
262 redz = redzsize - roundup(size, KASAN_SHADOW_SCALE);
263 KASSERT(redz % KASAN_SHADOW_SCALE == 0,
264 ("%s: invalid size %zu", __func__, redz));
265 shad = (int8_t *)kasan_md_addr_to_shad((uintptr_t)addr);
266
267 /* Chunks of 8 bytes, valid. */
268 n = size / KASAN_SHADOW_SCALE;
269 for (i = 0; i < n; i++) {
270 *shad++ = 0;
271 }
272
273 /* Possibly one chunk, mid. */
274 if ((size & KASAN_SHADOW_MASK) != 0) {
275 *shad++ = (size & KASAN_SHADOW_MASK);
276 }
277
278 /* Chunks of 8 bytes, invalid. */
279 n = redz / KASAN_SHADOW_SCALE;
280 for (i = 0; i < n; i++) {
281 *shad++ = code;
282 }
283}
284
285/* -------------------------------------------------------------------------- */
286
287#define ADDR_CROSSES_SCALE_BOUNDARY(addr, size) \
288 (addr >> KASAN_SHADOW_SCALE_SHIFT) != \
289 ((addr + size - 1) >> KASAN_SHADOW_SCALE_SHIFT)
290
291static __always_inline bool
292kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code)
293{
294 int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr);
295 int8_t last = (addr & KASAN_SHADOW_MASK) + 1;
296
297 if (__predict_true(*byte == 0 || last <= *byte)) {
298 return (true);
299 }
300 *code = *byte;
301 return (false);
302}
303
304static __always_inline bool
305kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code)
306{
307 int8_t *byte, last;
308
310 return (kasan_shadow_1byte_isvalid(addr, code) &&
312 }
313
314 byte = (int8_t *)kasan_md_addr_to_shad(addr);
315 last = ((addr + 1) & KASAN_SHADOW_MASK) + 1;
316
317 if (__predict_true(*byte == 0 || last <= *byte)) {
318 return (true);
319 }
320 *code = *byte;
321 return (false);
322}
323
324static __always_inline bool
325kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code)
326{
327 int8_t *byte, last;
328
330 return (kasan_shadow_2byte_isvalid(addr, code) &&
332 }
333
334 byte = (int8_t *)kasan_md_addr_to_shad(addr);
335 last = ((addr + 3) & KASAN_SHADOW_MASK) + 1;
336
337 if (__predict_true(*byte == 0 || last <= *byte)) {
338 return (true);
339 }
340 *code = *byte;
341 return (false);
342}
343
344static __always_inline bool
345kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code)
346{
347 int8_t *byte, last;
348
350 return (kasan_shadow_4byte_isvalid(addr, code) &&
352 }
353
354 byte = (int8_t *)kasan_md_addr_to_shad(addr);
355 last = ((addr + 7) & KASAN_SHADOW_MASK) + 1;
356
357 if (__predict_true(*byte == 0 || last <= *byte)) {
358 return (true);
359 }
360 *code = *byte;
361 return (false);
362}
363
364static __always_inline bool
365kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code)
366{
367 size_t i;
368
369 for (i = 0; i < size; i++) {
370 if (!kasan_shadow_1byte_isvalid(addr+i, code))
371 return (false);
372 }
373
374 return (true);
375}
376
377static __always_inline void
378kasan_shadow_check(unsigned long addr, size_t size, bool write,
379 unsigned long retaddr)
380{
381 uint8_t code;
382 bool valid;
383
384 if (__predict_false(!kasan_enabled))
385 return;
386 if (__predict_false(size == 0))
387 return;
388 if (__predict_false(kasan_md_unsupported(addr)))
389 return;
390 if (__predict_false(panicstr != NULL))
391 return;
392
393 if (__builtin_constant_p(size)) {
394 switch (size) {
395 case 1:
396 valid = kasan_shadow_1byte_isvalid(addr, &code);
397 break;
398 case 2:
399 valid = kasan_shadow_2byte_isvalid(addr, &code);
400 break;
401 case 4:
402 valid = kasan_shadow_4byte_isvalid(addr, &code);
403 break;
404 case 8:
405 valid = kasan_shadow_8byte_isvalid(addr, &code);
406 break;
407 default:
408 valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
409 break;
410 }
411 } else {
412 valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
413 }
414
415 if (__predict_false(!valid)) {
416 kasan_report(addr, size, write, retaddr, code);
417 }
418}
419
420/* -------------------------------------------------------------------------- */
421
422void *
423kasan_memcpy(void *dst, const void *src, size_t len)
424{
425 kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR);
426 kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR);
427 return (__builtin_memcpy(dst, src, len));
428}
429
430int
431kasan_memcmp(const void *b1, const void *b2, size_t len)
432{
433 kasan_shadow_check((unsigned long)b1, len, false, __RET_ADDR);
434 kasan_shadow_check((unsigned long)b2, len, false, __RET_ADDR);
435 return (__builtin_memcmp(b1, b2, len));
436}
437
438void *
439kasan_memset(void *b, int c, size_t len)
440{
441 kasan_shadow_check((unsigned long)b, len, true, __RET_ADDR);
442 return (__builtin_memset(b, c, len));
443}
444
445void *
446kasan_memmove(void *dst, const void *src, size_t len)
447{
448 kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR);
449 kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR);
450 return (__builtin_memmove(dst, src, len));
451}
452
453size_t
454kasan_strlen(const char *str)
455{
456 const char *s;
457
458 s = str;
459 while (1) {
460 kasan_shadow_check((unsigned long)s, 1, false, __RET_ADDR);
461 if (*s == '\0')
462 break;
463 s++;
464 }
465
466 return (s - str);
467}
468
469char *
470kasan_strcpy(char *dst, const char *src)
471{
472 char *save = dst;
473
474 while (1) {
475 kasan_shadow_check((unsigned long)src, 1, false, __RET_ADDR);
476 kasan_shadow_check((unsigned long)dst, 1, true, __RET_ADDR);
477 *dst = *src;
478 if (*src == '\0')
479 break;
480 src++, dst++;
481 }
482
483 return save;
484}
485
486int
487kasan_strcmp(const char *s1, const char *s2)
488{
489 while (1) {
490 kasan_shadow_check((unsigned long)s1, 1, false, __RET_ADDR);
491 kasan_shadow_check((unsigned long)s2, 1, false, __RET_ADDR);
492 if (*s1 != *s2)
493 break;
494 if (*s1 == '\0')
495 return 0;
496 s1++, s2++;
497 }
498
499 return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
500}
501
502int
503kasan_copyin(const void *uaddr, void *kaddr, size_t len)
504{
505 kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR);
506 return (copyin(uaddr, kaddr, len));
507}
508
509int
510kasan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
511{
512 kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR);
513 return (copyinstr(uaddr, kaddr, len, done));
514}
515
516int
517kasan_copyout(const void *kaddr, void *uaddr, size_t len)
518{
519 kasan_shadow_check((unsigned long)kaddr, len, false, __RET_ADDR);
520 return (copyout(kaddr, uaddr, len));
521}
522
523/* -------------------------------------------------------------------------- */
524
525int
526kasan_fubyte(volatile const void *base)
527{
528 return (fubyte(base));
529}
530
531int
532kasan_fuword16(volatile const void *base)
533{
534 return (fuword16(base));
535}
536
537int
538kasan_fueword(volatile const void *base, long *val)
539{
540 kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR);
541 return (fueword(base, val));
542}
543
544int
545kasan_fueword32(volatile const void *base, int32_t *val)
546{
547 kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR);
548 return (fueword32(base, val));
549}
550
551int
552kasan_fueword64(volatile const void *base, int64_t *val)
553{
554 kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR);
555 return (fueword64(base, val));
556}
557
558int
559kasan_subyte(volatile void *base, int byte)
560{
561 return (subyte(base, byte));
562}
563
564int
565kasan_suword(volatile void *base, long word)
566{
567 return (suword(base, word));
568}
569
570int
571kasan_suword16(volatile void *base, int word)
572{
573 return (suword16(base, word));
574}
575
576int
577kasan_suword32(volatile void *base, int32_t word)
578{
579 return (suword32(base, word));
580}
581
582int
583kasan_suword64(volatile void *base, int64_t word)
584{
585 return (suword64(base, word));
586}
587
588int
589kasan_casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,
590 uint32_t newval)
591{
592 kasan_shadow_check((unsigned long)oldvalp, sizeof(*oldvalp), true,
593 __RET_ADDR);
594 return (casueword32(base, oldval, oldvalp, newval));
595}
596
597int
598kasan_casueword(volatile u_long *base, u_long oldval, u_long *oldvalp,
599 u_long newval)
600{
601 kasan_shadow_check((unsigned long)oldvalp, sizeof(*oldvalp), true,
602 __RET_ADDR);
603 return (casueword(base, oldval, oldvalp, newval));
604}
605
606/* -------------------------------------------------------------------------- */
607
608#include <machine/atomic.h>
609#include <sys/atomic_san.h>
610
611#define _ASAN_ATOMIC_FUNC_ADD(name, type) \
612 void kasan_atomic_add_##name(volatile type *ptr, type val) \
613 { \
614 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
615 __RET_ADDR); \
616 atomic_add_##name(ptr, val); \
617 }
618
619#define ASAN_ATOMIC_FUNC_ADD(name, type) \
620 _ASAN_ATOMIC_FUNC_ADD(name, type) \
621 _ASAN_ATOMIC_FUNC_ADD(acq_##name, type) \
622 _ASAN_ATOMIC_FUNC_ADD(rel_##name, type)
623
624#define _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \
625 void kasan_atomic_subtract_##name(volatile type *ptr, type val) \
626 { \
627 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
628 __RET_ADDR); \
629 atomic_subtract_##name(ptr, val); \
630 }
631
632#define ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \
633 _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \
634 _ASAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type) \
635 _ASAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
636
637#define _ASAN_ATOMIC_FUNC_SET(name, type) \
638 void kasan_atomic_set_##name(volatile type *ptr, type val) \
639 { \
640 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
641 __RET_ADDR); \
642 atomic_set_##name(ptr, val); \
643 }
644
645#define ASAN_ATOMIC_FUNC_SET(name, type) \
646 _ASAN_ATOMIC_FUNC_SET(name, type) \
647 _ASAN_ATOMIC_FUNC_SET(acq_##name, type) \
648 _ASAN_ATOMIC_FUNC_SET(rel_##name, type)
649
650#define _ASAN_ATOMIC_FUNC_CLEAR(name, type) \
651 void kasan_atomic_clear_##name(volatile type *ptr, type val) \
652 { \
653 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
654 __RET_ADDR); \
655 atomic_clear_##name(ptr, val); \
656 }
657
658#define ASAN_ATOMIC_FUNC_CLEAR(name, type) \
659 _ASAN_ATOMIC_FUNC_CLEAR(name, type) \
660 _ASAN_ATOMIC_FUNC_CLEAR(acq_##name, type) \
661 _ASAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
662
663#define ASAN_ATOMIC_FUNC_FETCHADD(name, type) \
664 type kasan_atomic_fetchadd_##name(volatile type *ptr, type val) \
665 { \
666 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
667 __RET_ADDR); \
668 return (atomic_fetchadd_##name(ptr, val)); \
669 }
670
671#define ASAN_ATOMIC_FUNC_READANDCLEAR(name, type) \
672 type kasan_atomic_readandclear_##name(volatile type *ptr) \
673 { \
674 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
675 __RET_ADDR); \
676 return (atomic_readandclear_##name(ptr)); \
677 }
678
679#define ASAN_ATOMIC_FUNC_TESTANDCLEAR(name, type) \
680 int kasan_atomic_testandclear_##name(volatile type *ptr, u_int v) \
681 { \
682 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
683 __RET_ADDR); \
684 return (atomic_testandclear_##name(ptr, v)); \
685 }
686
687#define ASAN_ATOMIC_FUNC_TESTANDSET(name, type) \
688 int kasan_atomic_testandset_##name(volatile type *ptr, u_int v) \
689 { \
690 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
691 __RET_ADDR); \
692 return (atomic_testandset_##name(ptr, v)); \
693 }
694
695#define ASAN_ATOMIC_FUNC_SWAP(name, type) \
696 type kasan_atomic_swap_##name(volatile type *ptr, type val) \
697 { \
698 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
699 __RET_ADDR); \
700 return (atomic_swap_##name(ptr, val)); \
701 }
702
703#define _ASAN_ATOMIC_FUNC_CMPSET(name, type) \
704 int kasan_atomic_cmpset_##name(volatile type *ptr, type oval, \
705 type nval) \
706 { \
707 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
708 __RET_ADDR); \
709 return (atomic_cmpset_##name(ptr, oval, nval)); \
710 }
711
712#define ASAN_ATOMIC_FUNC_CMPSET(name, type) \
713 _ASAN_ATOMIC_FUNC_CMPSET(name, type) \
714 _ASAN_ATOMIC_FUNC_CMPSET(acq_##name, type) \
715 _ASAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
716
717#define _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \
718 int kasan_atomic_fcmpset_##name(volatile type *ptr, type *oval, \
719 type nval) \
720 { \
721 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
722 __RET_ADDR); \
723 return (atomic_fcmpset_##name(ptr, oval, nval)); \
724 }
725
726#define ASAN_ATOMIC_FUNC_FCMPSET(name, type) \
727 _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \
728 _ASAN_ATOMIC_FUNC_FCMPSET(acq_##name, type) \
729 _ASAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
730
731#define ASAN_ATOMIC_FUNC_THREAD_FENCE(name) \
732 void kasan_atomic_thread_fence_##name(void) \
733 { \
734 atomic_thread_fence_##name(); \
735 }
736
737#define _ASAN_ATOMIC_FUNC_LOAD(name, type) \
738 type kasan_atomic_load_##name(volatile type *ptr) \
739 { \
740 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
741 __RET_ADDR); \
742 return (atomic_load_##name(ptr)); \
743 }
744
745#define ASAN_ATOMIC_FUNC_LOAD(name, type) \
746 _ASAN_ATOMIC_FUNC_LOAD(name, type) \
747 _ASAN_ATOMIC_FUNC_LOAD(acq_##name, type)
748
749#define _ASAN_ATOMIC_FUNC_STORE(name, type) \
750 void kasan_atomic_store_##name(volatile type *ptr, type val) \
751 { \
752 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
753 __RET_ADDR); \
754 atomic_store_##name(ptr, val); \
755 }
756
757#define ASAN_ATOMIC_FUNC_STORE(name, type) \
758 _ASAN_ATOMIC_FUNC_STORE(name, type) \
759 _ASAN_ATOMIC_FUNC_STORE(rel_##name, type)
760
767ASAN_ATOMIC_FUNC_ADD(ptr, uintptr_t);
768
776
783ASAN_ATOMIC_FUNC_SET(ptr, uintptr_t);
784
792
797
803
808
813
818ASAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t);
819
827
835
841ASAN_ATOMIC_FUNC_LOAD(short, u_short);
844ASAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t);
845
855
860
861void
863{
864}
865
866/* -------------------------------------------------------------------------- */
867
868#include <sys/bus.h>
869#include <machine/bus.h>
870#include <sys/bus_san.h>
871
872int
873kasan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
874 int flags, bus_space_handle_t *handlep)
875{
876 return (bus_space_map(tag, hnd, size, flags, handlep));
877}
878
879void
880kasan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
881 bus_size_t size)
882{
883 bus_space_unmap(tag, hnd, size);
884}
885
886int
887kasan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
888 bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
889{
890 return (bus_space_subregion(tag, hnd, offset, size, handlep));
891}
892
893void
894kasan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
895 bus_size_t size)
896{
897 bus_space_free(tag, hnd, size);
898}
899
900void
901kasan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
902 bus_size_t offset, bus_size_t size, int flags)
903{
904 bus_space_barrier(tag, hnd, offset, size, flags);
905}
906
907#define ASAN_BUS_READ_FUNC(func, width, type) \
908 type kasan_bus_space_read##func##_##width(bus_space_tag_t tag, \
909 bus_space_handle_t hnd, bus_size_t offset) \
910 { \
911 return (bus_space_read##func##_##width(tag, hnd, \
912 offset)); \
913 } \
914
915#define ASAN_BUS_READ_PTR_FUNC(func, width, type) \
916 void kasan_bus_space_read_##func##_##width(bus_space_tag_t tag, \
917 bus_space_handle_t hnd, bus_size_t size, type *buf, \
918 bus_size_t count) \
919 { \
920 kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
921 false, __RET_ADDR); \
922 bus_space_read_##func##_##width(tag, hnd, size, buf, \
923 count); \
924 }
925
926ASAN_BUS_READ_FUNC(, 1, uint8_t)
927ASAN_BUS_READ_FUNC(_stream, 1, uint8_t)
928ASAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
929ASAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
931ASAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
932
933ASAN_BUS_READ_FUNC(, 2, uint16_t)
934ASAN_BUS_READ_FUNC(_stream, 2, uint16_t)
935ASAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
936ASAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
937ASAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
938ASAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
939
940ASAN_BUS_READ_FUNC(, 4, uint32_t)
941ASAN_BUS_READ_FUNC(_stream, 4, uint32_t)
942ASAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
943ASAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
944ASAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
945ASAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
946
947ASAN_BUS_READ_FUNC(, 8, uint64_t)
948
949#define ASAN_BUS_WRITE_FUNC(func, width, type) \
950 void kasan_bus_space_write##func##_##width(bus_space_tag_t tag, \
951 bus_space_handle_t hnd, bus_size_t offset, type value) \
952 { \
953 bus_space_write##func##_##width(tag, hnd, offset, value);\
954 } \
955
956#define ASAN_BUS_WRITE_PTR_FUNC(func, width, type) \
957 void kasan_bus_space_write_##func##_##width(bus_space_tag_t tag,\
958 bus_space_handle_t hnd, bus_size_t size, const type *buf, \
959 bus_size_t count) \
960 { \
961 kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
962 true, __RET_ADDR); \
963 bus_space_write_##func##_##width(tag, hnd, size, buf, \
964 count); \
965 }
966
967ASAN_BUS_WRITE_FUNC(, 1, uint8_t)
968ASAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
969ASAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
970ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
972ASAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
973
974ASAN_BUS_WRITE_FUNC(, 2, uint16_t)
975ASAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
976ASAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
977ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
979ASAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
980
981ASAN_BUS_WRITE_FUNC(, 4, uint32_t)
982ASAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
983ASAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
984ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
986ASAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
987
988ASAN_BUS_WRITE_FUNC(, 8, uint64_t)
989
990#define ASAN_BUS_SET_FUNC(func, width, type) \
991 void kasan_bus_space_set_##func##_##width(bus_space_tag_t tag, \
992 bus_space_handle_t hnd, bus_size_t offset, type value, \
993 bus_size_t count) \
994 { \
995 bus_space_set_##func##_##width(tag, hnd, offset, value, \
996 count); \
997 }
998
999ASAN_BUS_SET_FUNC(multi, 1, uint8_t)
1000ASAN_BUS_SET_FUNC(region, 1, uint8_t)
1001ASAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
1002ASAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
1003
1004ASAN_BUS_SET_FUNC(multi, 2, uint16_t)
1005ASAN_BUS_SET_FUNC(region, 2, uint16_t)
1006ASAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
1007ASAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
1008
1009ASAN_BUS_SET_FUNC(multi, 4, uint32_t)
1010ASAN_BUS_SET_FUNC(region, 4, uint32_t)
1011ASAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
1012ASAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
1013
1014/* -------------------------------------------------------------------------- */
1015
1016void __asan_register_globals(struct __asan_global *, size_t);
1017void __asan_unregister_globals(struct __asan_global *, size_t);
1018
1019void
1020__asan_register_globals(struct __asan_global *globals, size_t n)
1021{
1022 size_t i;
1023
1024 for (i = 0; i < n; i++) {
1025 kasan_mark(globals[i].beg, globals[i].size,
1026 globals[i].size_with_redzone, KASAN_GENERIC_REDZONE);
1027 }
1028}
1029
1030void
1032{
1033 size_t i;
1034
1035 for (i = 0; i < n; i++) {
1036 kasan_mark(globals[i].beg, globals[i].size_with_redzone,
1037 globals[i].size_with_redzone, 0);
1038 }
1039}
1040
1041#define ASAN_LOAD_STORE(size) \
1042 void __asan_load##size(unsigned long); \
1043 void __asan_load##size(unsigned long addr) \
1044 { \
1045 kasan_shadow_check(addr, size, false, __RET_ADDR);\
1046 } \
1047 void __asan_load##size##_noabort(unsigned long); \
1048 void __asan_load##size##_noabort(unsigned long addr) \
1049 { \
1050 kasan_shadow_check(addr, size, false, __RET_ADDR);\
1051 } \
1052 void __asan_store##size(unsigned long); \
1053 void __asan_store##size(unsigned long addr) \
1054 { \
1055 kasan_shadow_check(addr, size, true, __RET_ADDR);\
1056 } \
1057 void __asan_store##size##_noabort(unsigned long); \
1058 void __asan_store##size##_noabort(unsigned long addr) \
1059 { \
1060 kasan_shadow_check(addr, size, true, __RET_ADDR);\
1061 }
1062
1068
1069void __asan_loadN(unsigned long, size_t);
1070void __asan_loadN_noabort(unsigned long, size_t);
1071void __asan_storeN(unsigned long, size_t);
1072void __asan_storeN_noabort(unsigned long, size_t);
1073void __asan_handle_no_return(void);
1074
1075void
1076__asan_loadN(unsigned long addr, size_t size)
1077{
1078 kasan_shadow_check(addr, size, false, __RET_ADDR);
1079}
1080
1081void
1082__asan_loadN_noabort(unsigned long addr, size_t size)
1083{
1084 kasan_shadow_check(addr, size, false, __RET_ADDR);
1085}
1086
1087void
1088__asan_storeN(unsigned long addr, size_t size)
1089{
1090 kasan_shadow_check(addr, size, true, __RET_ADDR);
1091}
1092
1093void
1094__asan_storeN_noabort(unsigned long addr, size_t size)
1095{
1096 kasan_shadow_check(addr, size, true, __RET_ADDR);
1097}
1098
1099void
1101{
1102 /* nothing */
1103}
1104
1105#define ASAN_SET_SHADOW(byte) \
1106 void __asan_set_shadow_##byte(void *, size_t); \
1107 void __asan_set_shadow_##byte(void *addr, size_t size) \
1108 { \
1109 __builtin_memset((void *)addr, 0x##byte, size); \
1110 }
1111
1118
1119void __asan_poison_stack_memory(const void *, size_t);
1120void __asan_unpoison_stack_memory(const void *, size_t);
1121
1122void
1123__asan_poison_stack_memory(const void *addr, size_t size)
1124{
1125 size = roundup(size, KASAN_SHADOW_SCALE);
1126 kasan_shadow_Nbyte_fill(addr, size, KASAN_USE_AFTER_SCOPE);
1127}
1128
1129void
1130__asan_unpoison_stack_memory(const void *addr, size_t size)
1131{
1133}
1134
1135void __asan_alloca_poison(const void *, size_t);
1136void __asan_allocas_unpoison(const void *, const void *);
1137
1138void
1139__asan_alloca_poison(const void *addr, size_t size)
1140{
1141 const void *l, *r;
1142
1143 KASSERT((vm_offset_t)addr % KASAN_ALLOCA_SCALE_SIZE == 0,
1144 ("%s: invalid address %p", __func__, addr));
1145
1146 l = (const uint8_t *)addr - KASAN_ALLOCA_SCALE_SIZE;
1147 r = (const uint8_t *)addr + roundup(size, KASAN_ALLOCA_SCALE_SIZE);
1148
1150 kasan_mark(addr, size, roundup(size, KASAN_ALLOCA_SCALE_SIZE),
1151 KASAN_STACK_MID);
1152 kasan_shadow_Nbyte_fill(r, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_RIGHT);
1153}
1154
1155void
1156__asan_allocas_unpoison(const void *stkbegin, const void *stkend)
1157{
1158 size_t size;
1159
1160 if (__predict_false(!stkbegin))
1161 return;
1162 if (__predict_false((uintptr_t)stkbegin > (uintptr_t)stkend))
1163 return;
1164 size = (uintptr_t)stkend - (uintptr_t)stkbegin;
1165
1166 kasan_shadow_Nbyte_fill(stkbegin, size, 0);
1167}
1168
1169void __asan_poison_memory_region(const void *addr, size_t size);
1170void __asan_unpoison_memory_region(const void *addr, size_t size);
1171
1172void
1173__asan_poison_memory_region(const void *addr, size_t size)
1174{
1175}
1176
1177void
1178__asan_unpoison_memory_region(const void *addr, size_t size)
1179{
1180}
const char * panicstr
uint64_t * addr
Definition: msi_if.m:89
struct intr_irqsrc ** src
Definition: msi_if.m:76
const void * name
Definition: subr_asan.c:76
size_t size_with_redzone
Definition: subr_asan.c:75
struct __asan_global_source_location * location
Definition: subr_asan.c:79
size_t size
Definition: subr_asan.c:74
unsigned long has_dynamic_init
Definition: subr_asan.c:78
const void * beg
Definition: subr_asan.c:73
const void * module_name
Definition: subr_asan.c:77
void * kasan_memcpy(void *dst, const void *src, size_t len)
Definition: subr_asan.c:423
static __always_inline void kasan_shadow_1byte_markvalid(unsigned long addr)
Definition: subr_asan.c:198
static const char * kasan_code_name(uint8_t code)
Definition: subr_asan.c:143
void kasan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t size)
Definition: subr_asan.c:880
void kasan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t offset, bus_size_t size, int flags)
Definition: subr_asan.c:901
static __always_inline bool kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code)
Definition: subr_asan.c:325
#define ASAN_BUS_SET_FUNC(func, width, type)
Definition: subr_asan.c:990
int kasan_fueword64(volatile const void *base, int64_t *val)
Definition: subr_asan.c:552
static int panic_on_violation
Definition: subr_asan.c:90
#define ASAN_ATOMIC_FUNC_TESTANDSET(name, type)
Definition: subr_asan.c:687
char * kasan_strcpy(char *dst, const char *src)
Definition: subr_asan.c:470
void __asan_loadN(unsigned long, size_t)
Definition: subr_asan.c:1076
int kasan_suword(volatile void *base, long word)
Definition: subr_asan.c:565
void __asan_poison_stack_memory(const void *, size_t)
Definition: subr_asan.c:1123
int kasan_suword32(volatile void *base, int32_t word)
Definition: subr_asan.c:577
#define ASAN_ATOMIC_FUNC_FCMPSET(name, type)
Definition: subr_asan.c:726
void __asan_poison_memory_region(const void *addr, size_t size)
Definition: subr_asan.c:1173
#define ASAN_LOAD_STORE(size)
Definition: subr_asan.c:1041
void __asan_storeN_noabort(unsigned long, size_t)
Definition: subr_asan.c:1094
static __always_inline bool kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code)
Definition: subr_asan.c:345
#define ASAN_BUS_READ_PTR_FUNC(func, width, type)
Definition: subr_asan.c:915
#define ASAN_BUS_READ_FUNC(func, width, type)
Definition: subr_asan.c:907
#define KASAN_ALLOCA_SCALE_SIZE
Definition: subr_asan.c:50
#define ASAN_ATOMIC_FUNC_TESTANDCLEAR(name, type)
Definition: subr_asan.c:679
int kasan_strcmp(const char *s1, const char *s2)
Definition: subr_asan.c:487
static __always_inline bool kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code)
Definition: subr_asan.c:305
int kasan_casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp, uint32_t newval)
Definition: subr_asan.c:589
static __always_inline bool kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code)
Definition: subr_asan.c:365
#define ASAN_ATOMIC_FUNC_ADD(name, type)
Definition: subr_asan.c:619
#define ASAN_ATOMIC_FUNC_THREAD_FENCE(name)
Definition: subr_asan.c:731
int kasan_memcmp(const void *b1, const void *b2, size_t len)
Definition: subr_asan.c:431
void kasan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t size)
Definition: subr_asan.c:894
static __always_inline void kasan_shadow_Nbyte_markvalid(const void *addr, size_t size)
Definition: subr_asan.c:207
FEATURE(kasan, "Kernel address sanitizer")
void kasan_init(void)
Definition: subr_asan.c:126
int kasan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
Definition: subr_asan.c:510
void __asan_alloca_poison(const void *, size_t)
Definition: subr_asan.c:1139
#define REPORT(f,...)
Definition: subr_asan.c:175
#define ADDR_CROSSES_SCALE_BOUNDARY(addr, size)
Definition: subr_asan.c:287
static void kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc, uint8_t code)
Definition: subr_asan.c:189
#define ASAN_ATOMIC_FUNC_SUBTRACT(name, type)
Definition: subr_asan.c:632
__FBSDID("$FreeBSD$")
#define ASAN_ATOMIC_FUNC_STORE(name, type)
Definition: subr_asan.c:757
static bool kasan_enabled __read_mostly
Definition: subr_asan.c:95
int kasan_fueword32(volatile const void *base, int32_t *val)
Definition: subr_asan.c:545
int kasan_copyin(const void *uaddr, void *kaddr, size_t len)
Definition: subr_asan.c:503
#define ASAN_ATOMIC_FUNC_READANDCLEAR(name, type)
Definition: subr_asan.c:671
void __asan_allocas_unpoison(const void *, const void *)
Definition: subr_asan.c:1156
int kasan_subyte(volatile void *base, int byte)
Definition: subr_asan.c:559
#define __RET_ADDR
Definition: subr_asan.c:63
int kasan_suword16(volatile void *base, int word)
Definition: subr_asan.c:571
void * kasan_memset(void *b, int c, size_t len)
Definition: subr_asan.c:439
void __asan_loadN_noabort(unsigned long, size_t)
Definition: subr_asan.c:1082
void __asan_storeN(unsigned long, size_t)
Definition: subr_asan.c:1088
void kasan_mark(const void *addr, size_t size, size_t redzsize, uint8_t code)
Definition: subr_asan.c:248
int kasan_fueword(volatile const void *base, long *val)
Definition: subr_asan.c:538
static __always_inline bool kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code)
Definition: subr_asan.c:292
static SYSCTL_NODE(_debug, OID_AUTO, kasan, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "KASAN options")
int kasan_casueword(volatile u_long *base, u_long oldval, u_long *oldvalp, u_long newval)
Definition: subr_asan.c:598
int kasan_fubyte(volatile const void *base)
Definition: subr_asan.c:526
void __asan_unpoison_stack_memory(const void *, size_t)
Definition: subr_asan.c:1130
#define ASAN_ATOMIC_FUNC_CLEAR(name, type)
Definition: subr_asan.c:658
int kasan_fuword16(volatile const void *base)
Definition: subr_asan.c:532
SYSCTL_INT(_debug_kasan, OID_AUTO, panic_on_violation, CTLFLAG_RDTUN, &panic_on_violation, 0, "Panic if an invalid access is detected")
void __asan_register_globals(struct __asan_global *, size_t)
Definition: subr_asan.c:1020
void __asan_unpoison_memory_region(const void *addr, size_t size)
Definition: subr_asan.c:1178
int kasan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
Definition: subr_asan.c:887
int kasan_copyout(const void *kaddr, void *uaddr, size_t len)
Definition: subr_asan.c:517
#define ASAN_ATOMIC_FUNC_CMPSET(name, type)
Definition: subr_asan.c:712
static __always_inline void kasan_shadow_check(unsigned long addr, size_t size, bool write, unsigned long retaddr)
Definition: subr_asan.c:378
void __asan_handle_no_return(void)
Definition: subr_asan.c:1100
void kasan_shadow_map(vm_offset_t addr, size_t size)
Definition: subr_asan.c:100
void __asan_unregister_globals(struct __asan_global *, size_t)
Definition: subr_asan.c:1031
#define ASAN_ATOMIC_FUNC_LOAD(name, type)
Definition: subr_asan.c:745
static __always_inline void kasan_shadow_Nbyte_fill(const void *addr, size_t size, uint8_t code)
Definition: subr_asan.c:217
int kasan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size, int flags, bus_space_handle_t *handlep)
Definition: subr_asan.c:873
#define ASAN_SET_SHADOW(byte)
Definition: subr_asan.c:1105
#define ASAN_BUS_WRITE_FUNC(func, width, type)
Definition: subr_asan.c:949
#define ASAN_BUS_WRITE_PTR_FUNC(func, width, type)
Definition: subr_asan.c:956
#define ASAN_ATOMIC_FUNC_FETCHADD(name, type)
Definition: subr_asan.c:663
#define KASAN_SHADOW_MASK
Definition: subr_asan.c:49
void kasan_atomic_interrupt_fence(void)
Definition: subr_asan.c:862
#define ASAN_ATOMIC_FUNC_SET(name, type)
Definition: subr_asan.c:645
size_t kasan_strlen(const char *str)
Definition: subr_asan.c:454
#define ASAN_ATOMIC_FUNC_SWAP(name, type)
Definition: subr_asan.c:695
void * kasan_memmove(void *dst, const void *src, size_t len)
Definition: subr_asan.c:446
int kasan_suword64(volatile void *base, int64_t word)
Definition: subr_asan.c:583
uint16_t flags
Definition: subr_stats.c:2