1 /* $NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $ */
4 * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net
7 * This code is part of the KASAN subsystem of the NetBSD kernel.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 __KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $");
39 #include <sys/param.h>
40 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/stack.h>
44 #include <sys/sysctl.h>
46 #include <machine/asan.h>
48 /* ASAN constants. Part of the compiler ABI. */
49 #define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE - 1)
50 #define KASAN_ALLOCA_SCALE_SIZE 32
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
60 #error "Unsupported compiler version"
63 #define __RET_ADDR (unsigned long)__builtin_return_address(0)
65 /* Global variable descriptor. Part of the compiler ABI. */
66 struct __asan_global_source_location {
72 struct __asan_global {
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++) */
79 struct __asan_global_source_location *location;
80 #if ASAN_ABI_VERSION >= 7
81 uintptr_t odr_indicator; /* the address of the ODR indicator symbol */
85 FEATURE(kasan, "Kernel address sanitizer");
87 static SYSCTL_NODE(_debug, OID_AUTO, kasan, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
90 static int panic_on_violation = 1;
91 SYSCTL_INT(_debug_kasan, OID_AUTO, panic_on_violation, CTLFLAG_RDTUN,
92 &panic_on_violation, 0,
93 "Panic if an invalid access is detected");
95 static bool kasan_enabled __read_mostly = false;
97 /* -------------------------------------------------------------------------- */
100 kasan_shadow_map(vm_offset_t addr, size_t size)
102 size_t sz, npages, i;
103 vm_offset_t sva, eva;
105 KASSERT(addr % KASAN_SHADOW_SCALE == 0,
106 ("%s: invalid address %#lx", __func__, addr));
108 sz = roundup(size, KASAN_SHADOW_SCALE) / KASAN_SHADOW_SCALE;
110 sva = kasan_md_addr_to_shad(addr);
111 eva = kasan_md_addr_to_shad(addr) + sz;
113 sva = rounddown(sva, PAGE_SIZE);
114 eva = roundup(eva, PAGE_SIZE);
116 npages = (eva - sva) / PAGE_SIZE;
118 KASSERT(sva >= KASAN_MIN_ADDRESS && eva < KASAN_MAX_ADDRESS,
119 ("%s: invalid address range %#lx-%#lx", __func__, sva, eva));
121 for (i = 0; i < npages; i++)
122 pmap_kasan_enter(sva + ptoa(i));
131 TUNABLE_INT_FETCH("debug.kasan.disabled", &disabled);
135 /* MD initialization. */
138 /* Now officially enabled. */
139 kasan_enabled = true;
142 static inline const char *
143 kasan_code_name(uint8_t 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:
159 return "RedZonePartial";
160 case KASAN_STACK_LEFT:
162 case KASAN_STACK_MID:
163 return "StackMiddle";
164 case KASAN_STACK_RIGHT:
166 case KASAN_USE_AFTER_RET:
167 return "UseAfterRet";
168 case KASAN_USE_AFTER_SCOPE:
169 return "UseAfterScope";
175 #define REPORT(f, ...) do { \
176 if (panic_on_violation) { \
177 kasan_enabled = false; \
178 panic(f, __VA_ARGS__); \
183 printf(f "\n", __VA_ARGS__); \
184 stack_print_ddb(&st); \
189 kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc,
192 REPORT("ASan: Invalid access, %zu-byte %s at %#lx, %s(%x)",
193 size, (write ? "write" : "read"), addr, kasan_code_name(code),
197 static __always_inline void
198 kasan_shadow_1byte_markvalid(unsigned long addr)
200 int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr);
201 int8_t last = (addr & KASAN_SHADOW_MASK) + 1;
206 static __always_inline void
207 kasan_shadow_Nbyte_markvalid(const void *addr, size_t size)
211 for (i = 0; i < size; i++) {
212 kasan_shadow_1byte_markvalid((unsigned long)addr + i);
216 static __always_inline void
217 kasan_shadow_Nbyte_fill(const void *addr, size_t size, uint8_t code)
221 if (__predict_false(size == 0))
223 if (__predict_false(kasan_md_unsupported((vm_offset_t)addr)))
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));
231 shad = (void *)kasan_md_addr_to_shad((uintptr_t)addr);
232 size = size >> KASAN_SHADOW_SCALE_SHIFT;
234 __builtin_memset(shad, code, size);
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:
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.
245 * o kasan_mark(addr, size, size, 0). This marks the entire buffer as valid.
248 kasan_mark(const void *addr, size_t size, size_t redzsize, uint8_t code)
253 if ((vm_offset_t)addr >= DMAP_MIN_ADDRESS &&
254 (vm_offset_t)addr < DMAP_MAX_ADDRESS)
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);
267 /* Chunks of 8 bytes, valid. */
268 n = size / KASAN_SHADOW_SCALE;
269 for (i = 0; i < n; i++) {
273 /* Possibly one chunk, mid. */
274 if ((size & KASAN_SHADOW_MASK) != 0) {
275 *shad++ = (size & KASAN_SHADOW_MASK);
278 /* Chunks of 8 bytes, invalid. */
279 n = redz / KASAN_SHADOW_SCALE;
280 for (i = 0; i < n; i++) {
285 /* -------------------------------------------------------------------------- */
287 #define ADDR_CROSSES_SCALE_BOUNDARY(addr, size) \
288 (addr >> KASAN_SHADOW_SCALE_SHIFT) != \
289 ((addr + size - 1) >> KASAN_SHADOW_SCALE_SHIFT)
291 static __always_inline bool
292 kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code)
294 int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr);
295 int8_t last = (addr & KASAN_SHADOW_MASK) + 1;
297 if (__predict_true(*byte == 0 || last <= *byte)) {
304 static __always_inline bool
305 kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code)
309 if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 2)) {
310 return (kasan_shadow_1byte_isvalid(addr, code) &&
311 kasan_shadow_1byte_isvalid(addr+1, code));
314 byte = (int8_t *)kasan_md_addr_to_shad(addr);
315 last = ((addr + 1) & KASAN_SHADOW_MASK) + 1;
317 if (__predict_true(*byte == 0 || last <= *byte)) {
324 static __always_inline bool
325 kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code)
329 if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 4)) {
330 return (kasan_shadow_2byte_isvalid(addr, code) &&
331 kasan_shadow_2byte_isvalid(addr+2, code));
334 byte = (int8_t *)kasan_md_addr_to_shad(addr);
335 last = ((addr + 3) & KASAN_SHADOW_MASK) + 1;
337 if (__predict_true(*byte == 0 || last <= *byte)) {
344 static __always_inline bool
345 kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code)
349 if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 8)) {
350 return (kasan_shadow_4byte_isvalid(addr, code) &&
351 kasan_shadow_4byte_isvalid(addr+4, code));
354 byte = (int8_t *)kasan_md_addr_to_shad(addr);
355 last = ((addr + 7) & KASAN_SHADOW_MASK) + 1;
357 if (__predict_true(*byte == 0 || last <= *byte)) {
364 static __always_inline bool
365 kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code)
369 for (i = 0; i < size; i++) {
370 if (!kasan_shadow_1byte_isvalid(addr+i, code))
377 static __always_inline void
378 kasan_shadow_check(unsigned long addr, size_t size, bool write,
379 unsigned long retaddr)
384 if (__predict_false(!kasan_enabled))
386 if (__predict_false(size == 0))
388 if (__predict_false(kasan_md_unsupported(addr)))
390 if (__predict_false(panicstr != NULL))
393 if (__builtin_constant_p(size)) {
396 valid = kasan_shadow_1byte_isvalid(addr, &code);
399 valid = kasan_shadow_2byte_isvalid(addr, &code);
402 valid = kasan_shadow_4byte_isvalid(addr, &code);
405 valid = kasan_shadow_8byte_isvalid(addr, &code);
408 valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
412 valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
415 if (__predict_false(!valid)) {
416 kasan_report(addr, size, write, retaddr, code);
420 /* -------------------------------------------------------------------------- */
423 kasan_memcpy(void *dst, const void *src, size_t len)
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));
431 kasan_memcmp(const void *b1, const void *b2, size_t len)
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));
439 kasan_memset(void *b, int c, size_t len)
441 kasan_shadow_check((unsigned long)b, len, true, __RET_ADDR);
442 return (__builtin_memset(b, c, len));
446 kasan_memmove(void *dst, const void *src, size_t len)
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));
454 kasan_strlen(const char *str)
460 kasan_shadow_check((unsigned long)s, 1, false, __RET_ADDR);
470 kasan_strcpy(char *dst, const char *src)
475 kasan_shadow_check((unsigned long)src, 1, false, __RET_ADDR);
476 kasan_shadow_check((unsigned long)dst, 1, true, __RET_ADDR);
487 kasan_strcmp(const char *s1, const char *s2)
490 kasan_shadow_check((unsigned long)s1, 1, false, __RET_ADDR);
491 kasan_shadow_check((unsigned long)s2, 1, false, __RET_ADDR);
499 return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
503 kasan_copyin(const void *uaddr, void *kaddr, size_t len)
505 kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR);
506 return (copyin(uaddr, kaddr, len));
510 kasan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
512 kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR);
513 return (copyinstr(uaddr, kaddr, len, done));
517 kasan_copyout(const void *kaddr, void *uaddr, size_t len)
519 kasan_shadow_check((unsigned long)kaddr, len, false, __RET_ADDR);
520 return (copyout(kaddr, uaddr, len));
523 /* -------------------------------------------------------------------------- */
525 #include <machine/atomic.h>
526 #define ATOMIC_SAN_PREFIX kasan
527 #include <sys/atomic_san.h>
529 #define _ASAN_ATOMIC_FUNC_ADD(name, type) \
530 void kasan_atomic_add_##name(volatile type *ptr, type val) \
532 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
534 atomic_add_##name(ptr, val); \
537 #define ASAN_ATOMIC_FUNC_ADD(name, type) \
538 _ASAN_ATOMIC_FUNC_ADD(name, type) \
539 _ASAN_ATOMIC_FUNC_ADD(acq_##name, type) \
540 _ASAN_ATOMIC_FUNC_ADD(rel_##name, type)
542 #define _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \
543 void kasan_atomic_subtract_##name(volatile type *ptr, type val) \
545 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
547 atomic_subtract_##name(ptr, val); \
550 #define ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \
551 _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \
552 _ASAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type) \
553 _ASAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
555 #define _ASAN_ATOMIC_FUNC_SET(name, type) \
556 void kasan_atomic_set_##name(volatile type *ptr, type val) \
558 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
560 atomic_set_##name(ptr, val); \
563 #define ASAN_ATOMIC_FUNC_SET(name, type) \
564 _ASAN_ATOMIC_FUNC_SET(name, type) \
565 _ASAN_ATOMIC_FUNC_SET(acq_##name, type) \
566 _ASAN_ATOMIC_FUNC_SET(rel_##name, type)
568 #define _ASAN_ATOMIC_FUNC_CLEAR(name, type) \
569 void kasan_atomic_clear_##name(volatile type *ptr, type val) \
571 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
573 atomic_clear_##name(ptr, val); \
576 #define ASAN_ATOMIC_FUNC_CLEAR(name, type) \
577 _ASAN_ATOMIC_FUNC_CLEAR(name, type) \
578 _ASAN_ATOMIC_FUNC_CLEAR(acq_##name, type) \
579 _ASAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
581 #define ASAN_ATOMIC_FUNC_FETCHADD(name, type) \
582 type kasan_atomic_fetchadd_##name(volatile type *ptr, type val) \
584 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
586 return (atomic_fetchadd_##name(ptr, val)); \
589 #define ASAN_ATOMIC_FUNC_READANDCLEAR(name, type) \
590 type kasan_atomic_readandclear_##name(volatile type *ptr) \
592 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
594 return (atomic_readandclear_##name(ptr)); \
597 #define ASAN_ATOMIC_FUNC_TESTANDCLEAR(name, type) \
598 int kasan_atomic_testandclear_##name(volatile type *ptr, u_int v) \
600 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
602 return (atomic_testandclear_##name(ptr, v)); \
605 #define ASAN_ATOMIC_FUNC_TESTANDSET(name, type) \
606 int kasan_atomic_testandset_##name(volatile type *ptr, u_int v) \
608 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
610 return (atomic_testandset_##name(ptr, v)); \
613 #define ASAN_ATOMIC_FUNC_SWAP(name, type) \
614 type kasan_atomic_swap_##name(volatile type *ptr, type val) \
616 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
618 return (atomic_swap_##name(ptr, val)); \
621 #define _ASAN_ATOMIC_FUNC_CMPSET(name, type) \
622 int kasan_atomic_cmpset_##name(volatile type *ptr, type oval, \
625 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
627 return (atomic_cmpset_##name(ptr, oval, nval)); \
630 #define ASAN_ATOMIC_FUNC_CMPSET(name, type) \
631 _ASAN_ATOMIC_FUNC_CMPSET(name, type) \
632 _ASAN_ATOMIC_FUNC_CMPSET(acq_##name, type) \
633 _ASAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
635 #define _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \
636 int kasan_atomic_fcmpset_##name(volatile type *ptr, type *oval, \
639 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
641 return (atomic_fcmpset_##name(ptr, oval, nval)); \
644 #define ASAN_ATOMIC_FUNC_FCMPSET(name, type) \
645 _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \
646 _ASAN_ATOMIC_FUNC_FCMPSET(acq_##name, type) \
647 _ASAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
649 #define ASAN_ATOMIC_FUNC_THREAD_FENCE(name) \
650 void kasan_atomic_thread_fence_##name(void) \
652 atomic_thread_fence_##name(); \
655 #define _ASAN_ATOMIC_FUNC_LOAD(name, type) \
656 type kasan_atomic_load_##name(volatile type *ptr) \
658 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
660 return (atomic_load_##name(ptr)); \
663 #define ASAN_ATOMIC_FUNC_LOAD(name, type) \
664 _ASAN_ATOMIC_FUNC_LOAD(name, type) \
665 _ASAN_ATOMIC_FUNC_LOAD(acq_##name, type)
667 #define _ASAN_ATOMIC_FUNC_STORE(name, type) \
668 void kasan_atomic_store_##name(volatile type *ptr, type val) \
670 kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
672 atomic_store_##name(ptr, val); \
675 #define ASAN_ATOMIC_FUNC_STORE(name, type) \
676 _ASAN_ATOMIC_FUNC_STORE(name, type) \
677 _ASAN_ATOMIC_FUNC_STORE(rel_##name, type)
679 ASAN_ATOMIC_FUNC_ADD(8, uint8_t);
680 ASAN_ATOMIC_FUNC_ADD(16, uint16_t);
681 ASAN_ATOMIC_FUNC_ADD(32, uint32_t);
682 ASAN_ATOMIC_FUNC_ADD(64, uint64_t);
683 ASAN_ATOMIC_FUNC_ADD(int, u_int);
684 ASAN_ATOMIC_FUNC_ADD(long, u_long);
685 ASAN_ATOMIC_FUNC_ADD(ptr, uintptr_t);
687 ASAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t);
688 ASAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t);
689 ASAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t);
690 ASAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t);
691 ASAN_ATOMIC_FUNC_SUBTRACT(int, u_int);
692 ASAN_ATOMIC_FUNC_SUBTRACT(long, u_long);
693 ASAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t);
695 ASAN_ATOMIC_FUNC_SET(8, uint8_t);
696 ASAN_ATOMIC_FUNC_SET(16, uint16_t);
697 ASAN_ATOMIC_FUNC_SET(32, uint32_t);
698 ASAN_ATOMIC_FUNC_SET(64, uint64_t);
699 ASAN_ATOMIC_FUNC_SET(int, u_int);
700 ASAN_ATOMIC_FUNC_SET(long, u_long);
701 ASAN_ATOMIC_FUNC_SET(ptr, uintptr_t);
703 ASAN_ATOMIC_FUNC_CLEAR(8, uint8_t);
704 ASAN_ATOMIC_FUNC_CLEAR(16, uint16_t);
705 ASAN_ATOMIC_FUNC_CLEAR(32, uint32_t);
706 ASAN_ATOMIC_FUNC_CLEAR(64, uint64_t);
707 ASAN_ATOMIC_FUNC_CLEAR(int, u_int);
708 ASAN_ATOMIC_FUNC_CLEAR(long, u_long);
709 ASAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t);
711 ASAN_ATOMIC_FUNC_FETCHADD(32, uint32_t);
712 ASAN_ATOMIC_FUNC_FETCHADD(64, uint64_t);
713 ASAN_ATOMIC_FUNC_FETCHADD(int, u_int);
714 ASAN_ATOMIC_FUNC_FETCHADD(long, u_long);
716 ASAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t);
717 ASAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t);
718 ASAN_ATOMIC_FUNC_READANDCLEAR(int, u_int);
719 ASAN_ATOMIC_FUNC_READANDCLEAR(long, u_long);
720 ASAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t);
722 ASAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t);
723 ASAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t);
724 ASAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int);
725 ASAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long);
727 ASAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t);
728 ASAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t);
729 ASAN_ATOMIC_FUNC_TESTANDSET(int, u_int);
730 ASAN_ATOMIC_FUNC_TESTANDSET(long, u_long);
732 ASAN_ATOMIC_FUNC_SWAP(32, uint32_t);
733 ASAN_ATOMIC_FUNC_SWAP(64, uint64_t);
734 ASAN_ATOMIC_FUNC_SWAP(int, u_int);
735 ASAN_ATOMIC_FUNC_SWAP(long, u_long);
736 ASAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t);
738 ASAN_ATOMIC_FUNC_CMPSET(8, uint8_t);
739 ASAN_ATOMIC_FUNC_CMPSET(16, uint16_t);
740 ASAN_ATOMIC_FUNC_CMPSET(32, uint32_t);
741 ASAN_ATOMIC_FUNC_CMPSET(64, uint64_t);
742 ASAN_ATOMIC_FUNC_CMPSET(int, u_int);
743 ASAN_ATOMIC_FUNC_CMPSET(long, u_long);
744 ASAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t);
746 ASAN_ATOMIC_FUNC_FCMPSET(8, uint8_t);
747 ASAN_ATOMIC_FUNC_FCMPSET(16, uint16_t);
748 ASAN_ATOMIC_FUNC_FCMPSET(32, uint32_t);
749 ASAN_ATOMIC_FUNC_FCMPSET(64, uint64_t);
750 ASAN_ATOMIC_FUNC_FCMPSET(int, u_int);
751 ASAN_ATOMIC_FUNC_FCMPSET(long, u_long);
752 ASAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t);
754 ASAN_ATOMIC_FUNC_LOAD(8, uint8_t);
755 ASAN_ATOMIC_FUNC_LOAD(16, uint16_t);
756 ASAN_ATOMIC_FUNC_LOAD(32, uint32_t);
757 ASAN_ATOMIC_FUNC_LOAD(64, uint64_t);
758 ASAN_ATOMIC_FUNC_LOAD(char, u_char);
759 ASAN_ATOMIC_FUNC_LOAD(short, u_short);
760 ASAN_ATOMIC_FUNC_LOAD(int, u_int);
761 ASAN_ATOMIC_FUNC_LOAD(long, u_long);
762 ASAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t);
764 ASAN_ATOMIC_FUNC_STORE(8, uint8_t);
765 ASAN_ATOMIC_FUNC_STORE(16, uint16_t);
766 ASAN_ATOMIC_FUNC_STORE(32, uint32_t);
767 ASAN_ATOMIC_FUNC_STORE(64, uint64_t);
768 ASAN_ATOMIC_FUNC_STORE(char, u_char);
769 ASAN_ATOMIC_FUNC_STORE(short, u_short);
770 ASAN_ATOMIC_FUNC_STORE(int, u_int);
771 ASAN_ATOMIC_FUNC_STORE(long, u_long);
772 ASAN_ATOMIC_FUNC_STORE(ptr, uintptr_t);
774 ASAN_ATOMIC_FUNC_THREAD_FENCE(acq);
775 ASAN_ATOMIC_FUNC_THREAD_FENCE(rel);
776 ASAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel);
777 ASAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst);
780 kasan_atomic_interrupt_fence(void)
784 /* -------------------------------------------------------------------------- */
787 #include <machine/bus.h>
788 #define BUS_SAN_PREFIX kasan
789 #include <sys/bus_san.h>
792 kasan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
793 int flags, bus_space_handle_t *handlep)
795 return (bus_space_map(tag, hnd, size, flags, handlep));
799 kasan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
802 bus_space_unmap(tag, hnd, size);
806 kasan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
807 bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
809 return (bus_space_subregion(tag, hnd, offset, size, handlep));
813 kasan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
816 bus_space_free(tag, hnd, size);
820 kasan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
821 bus_size_t offset, bus_size_t size, int flags)
823 bus_space_barrier(tag, hnd, offset, size, flags);
826 #define ASAN_BUS_READ_FUNC(func, width, type) \
827 type kasan_bus_space_read##func##_##width(bus_space_tag_t tag, \
828 bus_space_handle_t hnd, bus_size_t offset) \
830 return (bus_space_read##func##_##width(tag, hnd, \
834 #define ASAN_BUS_READ_PTR_FUNC(func, width, type) \
835 void kasan_bus_space_read_##func##_##width(bus_space_tag_t tag, \
836 bus_space_handle_t hnd, bus_size_t size, type *buf, \
839 kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
840 false, __RET_ADDR); \
841 bus_space_read_##func##_##width(tag, hnd, size, buf, \
845 ASAN_BUS_READ_FUNC(, 1, uint8_t)
846 ASAN_BUS_READ_FUNC(_stream, 1, uint8_t)
847 ASAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
848 ASAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
849 ASAN_BUS_READ_PTR_FUNC(region, 1, uint8_t)
850 ASAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
852 ASAN_BUS_READ_FUNC(, 2, uint16_t)
853 ASAN_BUS_READ_FUNC(_stream, 2, uint16_t)
854 ASAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
855 ASAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
856 ASAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
857 ASAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
859 ASAN_BUS_READ_FUNC(, 4, uint32_t)
860 ASAN_BUS_READ_FUNC(_stream, 4, uint32_t)
861 ASAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
862 ASAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
863 ASAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
864 ASAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
866 ASAN_BUS_READ_FUNC(, 8, uint64_t)
868 #define ASAN_BUS_WRITE_FUNC(func, width, type) \
869 void kasan_bus_space_write##func##_##width(bus_space_tag_t tag, \
870 bus_space_handle_t hnd, bus_size_t offset, type value) \
872 bus_space_write##func##_##width(tag, hnd, offset, value);\
875 #define ASAN_BUS_WRITE_PTR_FUNC(func, width, type) \
876 void kasan_bus_space_write_##func##_##width(bus_space_tag_t tag,\
877 bus_space_handle_t hnd, bus_size_t size, const type *buf, \
880 kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
882 bus_space_write_##func##_##width(tag, hnd, size, buf, \
886 ASAN_BUS_WRITE_FUNC(, 1, uint8_t)
887 ASAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
888 ASAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
889 ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
890 ASAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t)
891 ASAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
893 ASAN_BUS_WRITE_FUNC(, 2, uint16_t)
894 ASAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
895 ASAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
896 ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
897 ASAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t)
898 ASAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
900 ASAN_BUS_WRITE_FUNC(, 4, uint32_t)
901 ASAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
902 ASAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
903 ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
904 ASAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t)
905 ASAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
907 ASAN_BUS_WRITE_FUNC(, 8, uint64_t)
909 #define ASAN_BUS_SET_FUNC(func, width, type) \
910 void kasan_bus_space_set_##func##_##width(bus_space_tag_t tag, \
911 bus_space_handle_t hnd, bus_size_t offset, type value, \
914 bus_space_set_##func##_##width(tag, hnd, offset, value, \
918 ASAN_BUS_SET_FUNC(multi, 1, uint8_t)
919 ASAN_BUS_SET_FUNC(region, 1, uint8_t)
920 ASAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
921 ASAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
923 ASAN_BUS_SET_FUNC(multi, 2, uint16_t)
924 ASAN_BUS_SET_FUNC(region, 2, uint16_t)
925 ASAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
926 ASAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
928 ASAN_BUS_SET_FUNC(multi, 4, uint32_t)
929 ASAN_BUS_SET_FUNC(region, 4, uint32_t)
930 ASAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
931 ASAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
933 /* -------------------------------------------------------------------------- */
935 void __asan_register_globals(struct __asan_global *, size_t);
936 void __asan_unregister_globals(struct __asan_global *, size_t);
939 __asan_register_globals(struct __asan_global *globals, size_t n)
943 for (i = 0; i < n; i++) {
944 kasan_mark(globals[i].beg, globals[i].size,
945 globals[i].size_with_redzone, KASAN_GENERIC_REDZONE);
950 __asan_unregister_globals(struct __asan_global *globals, size_t n)
954 for (i = 0; i < n; i++) {
955 kasan_mark(globals[i].beg, globals[i].size_with_redzone,
956 globals[i].size_with_redzone, 0);
960 #define ASAN_LOAD_STORE(size) \
961 void __asan_load##size(unsigned long); \
962 void __asan_load##size(unsigned long addr) \
964 kasan_shadow_check(addr, size, false, __RET_ADDR);\
966 void __asan_load##size##_noabort(unsigned long); \
967 void __asan_load##size##_noabort(unsigned long addr) \
969 kasan_shadow_check(addr, size, false, __RET_ADDR);\
971 void __asan_store##size(unsigned long); \
972 void __asan_store##size(unsigned long addr) \
974 kasan_shadow_check(addr, size, true, __RET_ADDR);\
976 void __asan_store##size##_noabort(unsigned long); \
977 void __asan_store##size##_noabort(unsigned long addr) \
979 kasan_shadow_check(addr, size, true, __RET_ADDR);\
988 void __asan_loadN(unsigned long, size_t);
989 void __asan_loadN_noabort(unsigned long, size_t);
990 void __asan_storeN(unsigned long, size_t);
991 void __asan_storeN_noabort(unsigned long, size_t);
992 void __asan_handle_no_return(void);
995 __asan_loadN(unsigned long addr, size_t size)
997 kasan_shadow_check(addr, size, false, __RET_ADDR);
1001 __asan_loadN_noabort(unsigned long addr, size_t size)
1003 kasan_shadow_check(addr, size, false, __RET_ADDR);
1007 __asan_storeN(unsigned long addr, size_t size)
1009 kasan_shadow_check(addr, size, true, __RET_ADDR);
1013 __asan_storeN_noabort(unsigned long addr, size_t size)
1015 kasan_shadow_check(addr, size, true, __RET_ADDR);
1019 __asan_handle_no_return(void)
1024 #define ASAN_SET_SHADOW(byte) \
1025 void __asan_set_shadow_##byte(void *, size_t); \
1026 void __asan_set_shadow_##byte(void *addr, size_t size) \
1028 __builtin_memset((void *)addr, 0x##byte, size); \
1031 ASAN_SET_SHADOW(00);
1032 ASAN_SET_SHADOW(f1);
1033 ASAN_SET_SHADOW(f2);
1034 ASAN_SET_SHADOW(f3);
1035 ASAN_SET_SHADOW(f5);
1036 ASAN_SET_SHADOW(f8);
1038 void __asan_poison_stack_memory(const void *, size_t);
1039 void __asan_unpoison_stack_memory(const void *, size_t);
1042 __asan_poison_stack_memory(const void *addr, size_t size)
1044 size = roundup(size, KASAN_SHADOW_SCALE);
1045 kasan_shadow_Nbyte_fill(addr, size, KASAN_USE_AFTER_SCOPE);
1049 __asan_unpoison_stack_memory(const void *addr, size_t size)
1051 kasan_shadow_Nbyte_markvalid(addr, size);
1054 void __asan_alloca_poison(const void *, size_t);
1055 void __asan_allocas_unpoison(const void *, const void *);
1058 __asan_alloca_poison(const void *addr, size_t size)
1062 KASSERT((vm_offset_t)addr % KASAN_ALLOCA_SCALE_SIZE == 0,
1063 ("%s: invalid address %p", __func__, addr));
1065 l = (const uint8_t *)addr - KASAN_ALLOCA_SCALE_SIZE;
1066 r = (const uint8_t *)addr + roundup(size, KASAN_ALLOCA_SCALE_SIZE);
1068 kasan_shadow_Nbyte_fill(l, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_LEFT);
1069 kasan_mark(addr, size, roundup(size, KASAN_ALLOCA_SCALE_SIZE),
1071 kasan_shadow_Nbyte_fill(r, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_RIGHT);
1075 __asan_allocas_unpoison(const void *stkbegin, const void *stkend)
1079 if (__predict_false(!stkbegin))
1081 if (__predict_false((uintptr_t)stkbegin > (uintptr_t)stkend))
1083 size = (uintptr_t)stkend - (uintptr_t)stkbegin;
1085 kasan_shadow_Nbyte_fill(stkbegin, size, 0);
1088 void __asan_poison_memory_region(const void *addr, size_t size);
1089 void __asan_unpoison_memory_region(const void *addr, size_t size);
1092 __asan_poison_memory_region(const void *addr, size_t size)
1097 __asan_unpoison_memory_region(const void *addr, size_t size)