138da497aSMark Johnston /* $NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $ */
238da497aSMark Johnston
338da497aSMark Johnston /*
438da497aSMark Johnston * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net
538da497aSMark Johnston * All rights reserved.
638da497aSMark Johnston *
738da497aSMark Johnston * This code is part of the KASAN subsystem of the NetBSD kernel.
838da497aSMark Johnston *
938da497aSMark Johnston * Redistribution and use in source and binary forms, with or without
1038da497aSMark Johnston * modification, are permitted provided that the following conditions
1138da497aSMark Johnston * are met:
1238da497aSMark Johnston * 1. Redistributions of source code must retain the above copyright
1338da497aSMark Johnston * notice, this list of conditions and the following disclaimer.
1438da497aSMark Johnston * 2. Redistributions in binary form must reproduce the above copyright
1538da497aSMark Johnston * notice, this list of conditions and the following disclaimer in the
1638da497aSMark Johnston * documentation and/or other materials provided with the distribution.
1738da497aSMark Johnston *
1838da497aSMark Johnston * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1938da497aSMark Johnston * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2038da497aSMark Johnston * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2138da497aSMark Johnston * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2238da497aSMark Johnston * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2338da497aSMark Johnston * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2438da497aSMark Johnston * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2538da497aSMark Johnston * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2638da497aSMark Johnston * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2738da497aSMark Johnston * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2838da497aSMark Johnston * SUCH DAMAGE.
2938da497aSMark Johnston */
3038da497aSMark Johnston
3138da497aSMark Johnston #define SAN_RUNTIME
3238da497aSMark Johnston
3338da497aSMark Johnston #include <sys/cdefs.h>
3438da497aSMark Johnston #if 0
3538da497aSMark Johnston __KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $");
3638da497aSMark Johnston #endif
3738da497aSMark Johnston
3838da497aSMark Johnston #include <sys/param.h>
3938da497aSMark Johnston #include <sys/systm.h>
4038da497aSMark Johnston #include <sys/asan.h>
4138da497aSMark Johnston #include <sys/kernel.h>
42800da341SMark Johnston #include <sys/proc.h>
4338da497aSMark Johnston #include <sys/stack.h>
4438da497aSMark Johnston #include <sys/sysctl.h>
4538da497aSMark Johnston
4638da497aSMark Johnston #include <machine/asan.h>
47818cae0fSMitchell Horne #include <machine/bus.h>
4838da497aSMark Johnston
4938da497aSMark Johnston /* ASAN constants. Part of the compiler ABI. */
5038da497aSMark Johnston #define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE - 1)
5138da497aSMark Johnston #define KASAN_ALLOCA_SCALE_SIZE 32
5238da497aSMark Johnston
5338da497aSMark Johnston /* ASAN ABI version. */
5438da497aSMark Johnston #if defined(__clang__) && (__clang_major__ - 0 >= 6)
5538da497aSMark Johnston #define ASAN_ABI_VERSION 8
5638da497aSMark Johnston #elif __GNUC_PREREQ__(7, 1) && !defined(__clang__)
5738da497aSMark Johnston #define ASAN_ABI_VERSION 8
5838da497aSMark Johnston #elif __GNUC_PREREQ__(6, 1) && !defined(__clang__)
5938da497aSMark Johnston #define ASAN_ABI_VERSION 6
6038da497aSMark Johnston #else
6138da497aSMark Johnston #error "Unsupported compiler version"
6238da497aSMark Johnston #endif
6338da497aSMark Johnston
6438da497aSMark Johnston #define __RET_ADDR (unsigned long)__builtin_return_address(0)
6538da497aSMark Johnston
6638da497aSMark Johnston /* Global variable descriptor. Part of the compiler ABI. */
6738da497aSMark Johnston struct __asan_global_source_location {
6838da497aSMark Johnston const char *filename;
6938da497aSMark Johnston int line_no;
7038da497aSMark Johnston int column_no;
7138da497aSMark Johnston };
7238da497aSMark Johnston
7338da497aSMark Johnston struct __asan_global {
7438da497aSMark Johnston const void *beg; /* address of the global variable */
7538da497aSMark Johnston size_t size; /* size of the global variable */
7638da497aSMark Johnston size_t size_with_redzone; /* size with the redzone */
7738da497aSMark Johnston const void *name; /* name of the variable */
7838da497aSMark Johnston const void *module_name; /* name of the module where the var is declared */
7938da497aSMark Johnston unsigned long has_dynamic_init; /* the var has dyn initializer (c++) */
8038da497aSMark Johnston struct __asan_global_source_location *location;
8138da497aSMark Johnston #if ASAN_ABI_VERSION >= 7
8238da497aSMark Johnston uintptr_t odr_indicator; /* the address of the ODR indicator symbol */
8338da497aSMark Johnston #endif
8438da497aSMark Johnston };
8538da497aSMark Johnston
8638da497aSMark Johnston FEATURE(kasan, "Kernel address sanitizer");
8738da497aSMark Johnston
8838da497aSMark Johnston static SYSCTL_NODE(_debug, OID_AUTO, kasan, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
8938da497aSMark Johnston "KASAN options");
9038da497aSMark Johnston
9138da497aSMark Johnston static int panic_on_violation = 1;
9238da497aSMark Johnston SYSCTL_INT(_debug_kasan, OID_AUTO, panic_on_violation, CTLFLAG_RDTUN,
9338da497aSMark Johnston &panic_on_violation, 0,
9438da497aSMark Johnston "Panic if an invalid access is detected");
9538da497aSMark Johnston
96db5d0bc8SZhenlei Huang #define kasan_enabled (!kasan_disabled)
97db5d0bc8SZhenlei Huang static bool kasan_disabled __read_mostly = true;
98db5d0bc8SZhenlei Huang SYSCTL_BOOL(_debug_kasan, OID_AUTO, disabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
99db5d0bc8SZhenlei Huang &kasan_disabled, 0, "KASAN is disabled");
10038da497aSMark Johnston
10138da497aSMark Johnston /* -------------------------------------------------------------------------- */
10238da497aSMark Johnston
10338da497aSMark Johnston void
kasan_shadow_map(vm_offset_t addr,size_t size)10420e3b9d8SMark Johnston kasan_shadow_map(vm_offset_t addr, size_t size)
10538da497aSMark Johnston {
10638da497aSMark Johnston size_t sz, npages, i;
10738da497aSMark Johnston vm_offset_t sva, eva;
10838da497aSMark Johnston
10920e3b9d8SMark Johnston KASSERT(addr % KASAN_SHADOW_SCALE == 0,
11020e3b9d8SMark Johnston ("%s: invalid address %#lx", __func__, addr));
11138da497aSMark Johnston
11238da497aSMark Johnston sz = roundup(size, KASAN_SHADOW_SCALE) / KASAN_SHADOW_SCALE;
11338da497aSMark Johnston
11420e3b9d8SMark Johnston sva = kasan_md_addr_to_shad(addr);
11520e3b9d8SMark Johnston eva = kasan_md_addr_to_shad(addr) + sz;
11638da497aSMark Johnston
11738da497aSMark Johnston sva = rounddown(sva, PAGE_SIZE);
11838da497aSMark Johnston eva = roundup(eva, PAGE_SIZE);
11938da497aSMark Johnston
12038da497aSMark Johnston npages = (eva - sva) / PAGE_SIZE;
12138da497aSMark Johnston
12238da497aSMark Johnston KASSERT(sva >= KASAN_MIN_ADDRESS && eva < KASAN_MAX_ADDRESS,
12338da497aSMark Johnston ("%s: invalid address range %#lx-%#lx", __func__, sva, eva));
12438da497aSMark Johnston
12538da497aSMark Johnston for (i = 0; i < npages; i++)
126175d3380SMark Johnston pmap_san_enter(sva + ptoa(i));
12738da497aSMark Johnston }
12838da497aSMark Johnston
12938da497aSMark Johnston void
kasan_init(void)13038da497aSMark Johnston kasan_init(void)
13138da497aSMark Johnston {
13238da497aSMark Johnston int disabled;
13338da497aSMark Johnston
13438da497aSMark Johnston disabled = 0;
13538da497aSMark Johnston TUNABLE_INT_FETCH("debug.kasan.disabled", &disabled);
13638da497aSMark Johnston if (disabled)
13738da497aSMark Johnston return;
13838da497aSMark Johnston
13938da497aSMark Johnston /* MD initialization. */
14038da497aSMark Johnston kasan_md_init();
14138da497aSMark Johnston
14238da497aSMark Johnston /* Now officially enabled. */
143db5d0bc8SZhenlei Huang kasan_disabled = false;
14438da497aSMark Johnston }
14538da497aSMark Johnston
146756bc3adSMark Johnston void
kasan_init_early(vm_offset_t stack,size_t size)147756bc3adSMark Johnston kasan_init_early(vm_offset_t stack, size_t size)
148756bc3adSMark Johnston {
149756bc3adSMark Johnston kasan_md_init_early(stack, size);
150756bc3adSMark Johnston }
151756bc3adSMark Johnston
15238da497aSMark Johnston static inline const char *
kasan_code_name(uint8_t code)15338da497aSMark Johnston kasan_code_name(uint8_t code)
15438da497aSMark Johnston {
15538da497aSMark Johnston switch (code) {
15638da497aSMark Johnston case KASAN_GENERIC_REDZONE:
15738da497aSMark Johnston return "GenericRedZone";
15838da497aSMark Johnston case KASAN_MALLOC_REDZONE:
15938da497aSMark Johnston return "MallocRedZone";
16038da497aSMark Johnston case KASAN_KMEM_REDZONE:
16138da497aSMark Johnston return "KmemRedZone";
16238da497aSMark Johnston case KASAN_UMA_FREED:
16338da497aSMark Johnston return "UMAUseAfterFree";
16438da497aSMark Johnston case KASAN_KSTACK_FREED:
16538da497aSMark Johnston return "KernelStack";
166f1c3adefSMark Johnston case KASAN_EXEC_ARGS_FREED:
167f1c3adefSMark Johnston return "ExecKVA";
16838da497aSMark Johnston case 1 ... 7:
16938da497aSMark Johnston return "RedZonePartial";
17038da497aSMark Johnston case KASAN_STACK_LEFT:
17138da497aSMark Johnston return "StackLeft";
17238da497aSMark Johnston case KASAN_STACK_MID:
17338da497aSMark Johnston return "StackMiddle";
17438da497aSMark Johnston case KASAN_STACK_RIGHT:
17538da497aSMark Johnston return "StackRight";
17638da497aSMark Johnston case KASAN_USE_AFTER_RET:
17738da497aSMark Johnston return "UseAfterRet";
17838da497aSMark Johnston case KASAN_USE_AFTER_SCOPE:
17938da497aSMark Johnston return "UseAfterScope";
18038da497aSMark Johnston default:
18138da497aSMark Johnston return "Unknown";
18238da497aSMark Johnston }
18338da497aSMark Johnston }
18438da497aSMark Johnston
18538da497aSMark Johnston #define REPORT(f, ...) do { \
18638da497aSMark Johnston if (panic_on_violation) { \
187db5d0bc8SZhenlei Huang kasan_disabled = true; \
18838da497aSMark Johnston panic(f, __VA_ARGS__); \
18938da497aSMark Johnston } else { \
19038da497aSMark Johnston struct stack st; \
19138da497aSMark Johnston \
19238da497aSMark Johnston stack_save(&st); \
19338da497aSMark Johnston printf(f "\n", __VA_ARGS__); \
19438da497aSMark Johnston stack_print_ddb(&st); \
19538da497aSMark Johnston } \
19638da497aSMark Johnston } while (0)
19738da497aSMark Johnston
19838da497aSMark Johnston static void
kasan_report(unsigned long addr,size_t size,bool write,unsigned long pc,uint8_t code)19938da497aSMark Johnston kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc,
20038da497aSMark Johnston uint8_t code)
20138da497aSMark Johnston {
20238da497aSMark Johnston REPORT("ASan: Invalid access, %zu-byte %s at %#lx, %s(%x)",
20338da497aSMark Johnston size, (write ? "write" : "read"), addr, kasan_code_name(code),
20438da497aSMark Johnston code);
20538da497aSMark Johnston }
20638da497aSMark Johnston
20738da497aSMark Johnston static __always_inline void
kasan_shadow_1byte_markvalid(unsigned long addr)20838da497aSMark Johnston kasan_shadow_1byte_markvalid(unsigned long addr)
20938da497aSMark Johnston {
21038da497aSMark Johnston int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr);
21138da497aSMark Johnston int8_t last = (addr & KASAN_SHADOW_MASK) + 1;
21238da497aSMark Johnston
21338da497aSMark Johnston *byte = last;
21438da497aSMark Johnston }
21538da497aSMark Johnston
21638da497aSMark Johnston static __always_inline void
kasan_shadow_Nbyte_markvalid(const void * addr,size_t size)21738da497aSMark Johnston kasan_shadow_Nbyte_markvalid(const void *addr, size_t size)
21838da497aSMark Johnston {
21938da497aSMark Johnston size_t i;
22038da497aSMark Johnston
22138da497aSMark Johnston for (i = 0; i < size; i++) {
22238da497aSMark Johnston kasan_shadow_1byte_markvalid((unsigned long)addr + i);
22338da497aSMark Johnston }
22438da497aSMark Johnston }
22538da497aSMark Johnston
22638da497aSMark Johnston static __always_inline void
kasan_shadow_Nbyte_fill(const void * addr,size_t size,uint8_t code)22738da497aSMark Johnston kasan_shadow_Nbyte_fill(const void *addr, size_t size, uint8_t code)
22838da497aSMark Johnston {
22938da497aSMark Johnston void *shad;
23038da497aSMark Johnston
23138da497aSMark Johnston if (__predict_false(size == 0))
23238da497aSMark Johnston return;
23338da497aSMark Johnston if (__predict_false(kasan_md_unsupported((vm_offset_t)addr)))
23438da497aSMark Johnston return;
23538da497aSMark Johnston
23638da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0,
23738da497aSMark Johnston ("%s: invalid address %p", __func__, addr));
23838da497aSMark Johnston KASSERT(size % KASAN_SHADOW_SCALE == 0,
23938da497aSMark Johnston ("%s: invalid size %zu", __func__, size));
24038da497aSMark Johnston
24138da497aSMark Johnston shad = (void *)kasan_md_addr_to_shad((uintptr_t)addr);
24238da497aSMark Johnston size = size >> KASAN_SHADOW_SCALE_SHIFT;
24338da497aSMark Johnston
24438da497aSMark Johnston __builtin_memset(shad, code, size);
24538da497aSMark Johnston }
24638da497aSMark Johnston
24738da497aSMark Johnston /*
24838da497aSMark Johnston * In an area of size 'sz_with_redz', mark the 'size' first bytes as valid,
24938da497aSMark Johnston * and the rest as invalid. There are generally two use cases:
25038da497aSMark Johnston *
25138da497aSMark Johnston * o kasan_mark(addr, origsize, size, code), with origsize < size. This marks
25238da497aSMark Johnston * the redzone at the end of the buffer as invalid. If the entire is to be
25338da497aSMark Johnston * marked invalid, origsize will be 0.
25438da497aSMark Johnston *
25538da497aSMark Johnston * o kasan_mark(addr, size, size, 0). This marks the entire buffer as valid.
25638da497aSMark Johnston */
25738da497aSMark Johnston void
kasan_mark(const void * addr,size_t size,size_t redzsize,uint8_t code)25838da497aSMark Johnston kasan_mark(const void *addr, size_t size, size_t redzsize, uint8_t code)
25938da497aSMark Johnston {
26038da497aSMark Johnston size_t i, n, redz;
26138da497aSMark Johnston int8_t *shad;
26238da497aSMark Johnston
263f2963b53SMitchell Horne if (__predict_false(!kasan_enabled))
264f2963b53SMitchell Horne return;
265f2963b53SMitchell Horne
26638da497aSMark Johnston if ((vm_offset_t)addr >= DMAP_MIN_ADDRESS &&
26738da497aSMark Johnston (vm_offset_t)addr < DMAP_MAX_ADDRESS)
26838da497aSMark Johnston return;
26938da497aSMark Johnston
27038da497aSMark Johnston KASSERT((vm_offset_t)addr >= VM_MIN_KERNEL_ADDRESS &&
27138da497aSMark Johnston (vm_offset_t)addr < VM_MAX_KERNEL_ADDRESS,
27238da497aSMark Johnston ("%s: invalid address %p", __func__, addr));
27338da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0,
27438da497aSMark Johnston ("%s: invalid address %p", __func__, addr));
27538da497aSMark Johnston redz = redzsize - roundup(size, KASAN_SHADOW_SCALE);
27638da497aSMark Johnston KASSERT(redz % KASAN_SHADOW_SCALE == 0,
27738da497aSMark Johnston ("%s: invalid size %zu", __func__, redz));
27838da497aSMark Johnston shad = (int8_t *)kasan_md_addr_to_shad((uintptr_t)addr);
27938da497aSMark Johnston
28038da497aSMark Johnston /* Chunks of 8 bytes, valid. */
28138da497aSMark Johnston n = size / KASAN_SHADOW_SCALE;
28238da497aSMark Johnston for (i = 0; i < n; i++) {
28338da497aSMark Johnston *shad++ = 0;
28438da497aSMark Johnston }
28538da497aSMark Johnston
28638da497aSMark Johnston /* Possibly one chunk, mid. */
28738da497aSMark Johnston if ((size & KASAN_SHADOW_MASK) != 0) {
28838da497aSMark Johnston *shad++ = (size & KASAN_SHADOW_MASK);
28938da497aSMark Johnston }
29038da497aSMark Johnston
29138da497aSMark Johnston /* Chunks of 8 bytes, invalid. */
29238da497aSMark Johnston n = redz / KASAN_SHADOW_SCALE;
29338da497aSMark Johnston for (i = 0; i < n; i++) {
29438da497aSMark Johnston *shad++ = code;
29538da497aSMark Johnston }
29638da497aSMark Johnston }
29738da497aSMark Johnston
298800da341SMark Johnston void
kasan_thread_alloc(struct thread * td)299800da341SMark Johnston kasan_thread_alloc(struct thread *td)
300800da341SMark Johnston {
301800da341SMark Johnston if (td->td_kstack != 0) {
302800da341SMark Johnston kasan_mark((void *)td->td_kstack, ptoa(td->td_kstack_pages),
303800da341SMark Johnston ptoa(td->td_kstack_pages), 0);
304800da341SMark Johnston }
305800da341SMark Johnston }
306800da341SMark Johnston
30738da497aSMark Johnston /* -------------------------------------------------------------------------- */
30838da497aSMark Johnston
30938da497aSMark Johnston #define ADDR_CROSSES_SCALE_BOUNDARY(addr, size) \
31038da497aSMark Johnston (addr >> KASAN_SHADOW_SCALE_SHIFT) != \
31138da497aSMark Johnston ((addr + size - 1) >> KASAN_SHADOW_SCALE_SHIFT)
31238da497aSMark Johnston
31338da497aSMark Johnston static __always_inline bool
kasan_shadow_1byte_isvalid(unsigned long addr,uint8_t * code)31438da497aSMark Johnston kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code)
31538da497aSMark Johnston {
31638da497aSMark Johnston int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr);
31738da497aSMark Johnston int8_t last = (addr & KASAN_SHADOW_MASK) + 1;
31838da497aSMark Johnston
31938da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) {
32038da497aSMark Johnston return (true);
32138da497aSMark Johnston }
32238da497aSMark Johnston *code = *byte;
32338da497aSMark Johnston return (false);
32438da497aSMark Johnston }
32538da497aSMark Johnston
32638da497aSMark Johnston static __always_inline bool
kasan_shadow_2byte_isvalid(unsigned long addr,uint8_t * code)32738da497aSMark Johnston kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code)
32838da497aSMark Johnston {
32938da497aSMark Johnston int8_t *byte, last;
33038da497aSMark Johnston
33138da497aSMark Johnston if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 2)) {
33238da497aSMark Johnston return (kasan_shadow_1byte_isvalid(addr, code) &&
33338da497aSMark Johnston kasan_shadow_1byte_isvalid(addr+1, code));
33438da497aSMark Johnston }
33538da497aSMark Johnston
33638da497aSMark Johnston byte = (int8_t *)kasan_md_addr_to_shad(addr);
33738da497aSMark Johnston last = ((addr + 1) & KASAN_SHADOW_MASK) + 1;
33838da497aSMark Johnston
33938da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) {
34038da497aSMark Johnston return (true);
34138da497aSMark Johnston }
34238da497aSMark Johnston *code = *byte;
34338da497aSMark Johnston return (false);
34438da497aSMark Johnston }
34538da497aSMark Johnston
34638da497aSMark Johnston static __always_inline bool
kasan_shadow_4byte_isvalid(unsigned long addr,uint8_t * code)34738da497aSMark Johnston kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code)
34838da497aSMark Johnston {
34938da497aSMark Johnston int8_t *byte, last;
35038da497aSMark Johnston
35138da497aSMark Johnston if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 4)) {
35238da497aSMark Johnston return (kasan_shadow_2byte_isvalid(addr, code) &&
35338da497aSMark Johnston kasan_shadow_2byte_isvalid(addr+2, code));
35438da497aSMark Johnston }
35538da497aSMark Johnston
35638da497aSMark Johnston byte = (int8_t *)kasan_md_addr_to_shad(addr);
35738da497aSMark Johnston last = ((addr + 3) & KASAN_SHADOW_MASK) + 1;
35838da497aSMark Johnston
35938da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) {
36038da497aSMark Johnston return (true);
36138da497aSMark Johnston }
36238da497aSMark Johnston *code = *byte;
36338da497aSMark Johnston return (false);
36438da497aSMark Johnston }
36538da497aSMark Johnston
36638da497aSMark Johnston static __always_inline bool
kasan_shadow_8byte_isvalid(unsigned long addr,uint8_t * code)36738da497aSMark Johnston kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code)
36838da497aSMark Johnston {
36938da497aSMark Johnston int8_t *byte, last;
37038da497aSMark Johnston
37138da497aSMark Johnston if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 8)) {
37238da497aSMark Johnston return (kasan_shadow_4byte_isvalid(addr, code) &&
37338da497aSMark Johnston kasan_shadow_4byte_isvalid(addr+4, code));
37438da497aSMark Johnston }
37538da497aSMark Johnston
37638da497aSMark Johnston byte = (int8_t *)kasan_md_addr_to_shad(addr);
37738da497aSMark Johnston last = ((addr + 7) & KASAN_SHADOW_MASK) + 1;
37838da497aSMark Johnston
37938da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) {
38038da497aSMark Johnston return (true);
38138da497aSMark Johnston }
38238da497aSMark Johnston *code = *byte;
38338da497aSMark Johnston return (false);
38438da497aSMark Johnston }
38538da497aSMark Johnston
38638da497aSMark Johnston static __always_inline bool
kasan_shadow_Nbyte_isvalid(unsigned long addr,size_t size,uint8_t * code)38738da497aSMark Johnston kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code)
38838da497aSMark Johnston {
38938da497aSMark Johnston size_t i;
39038da497aSMark Johnston
39138da497aSMark Johnston for (i = 0; i < size; i++) {
39238da497aSMark Johnston if (!kasan_shadow_1byte_isvalid(addr+i, code))
39338da497aSMark Johnston return (false);
39438da497aSMark Johnston }
39538da497aSMark Johnston
39638da497aSMark Johnston return (true);
39738da497aSMark Johnston }
39838da497aSMark Johnston
39938da497aSMark Johnston static __always_inline void
kasan_shadow_check(unsigned long addr,size_t size,bool write,unsigned long retaddr)40038da497aSMark Johnston kasan_shadow_check(unsigned long addr, size_t size, bool write,
40138da497aSMark Johnston unsigned long retaddr)
40238da497aSMark Johnston {
40338da497aSMark Johnston uint8_t code;
40438da497aSMark Johnston bool valid;
40538da497aSMark Johnston
40638da497aSMark Johnston if (__predict_false(!kasan_enabled))
40738da497aSMark Johnston return;
40837cef001SMark Johnston if (__predict_false(curthread != NULL &&
40937cef001SMark Johnston (curthread->td_pflags2 & TDP2_SAN_QUIET) != 0))
41037cef001SMark Johnston return;
41138da497aSMark Johnston if (__predict_false(size == 0))
41238da497aSMark Johnston return;
41338da497aSMark Johnston if (__predict_false(kasan_md_unsupported(addr)))
41438da497aSMark Johnston return;
41535eb9b10SMitchell Horne if (KERNEL_PANICKED())
41638da497aSMark Johnston return;
41738da497aSMark Johnston
41838da497aSMark Johnston if (__builtin_constant_p(size)) {
41938da497aSMark Johnston switch (size) {
42038da497aSMark Johnston case 1:
42138da497aSMark Johnston valid = kasan_shadow_1byte_isvalid(addr, &code);
42238da497aSMark Johnston break;
42338da497aSMark Johnston case 2:
42438da497aSMark Johnston valid = kasan_shadow_2byte_isvalid(addr, &code);
42538da497aSMark Johnston break;
42638da497aSMark Johnston case 4:
42738da497aSMark Johnston valid = kasan_shadow_4byte_isvalid(addr, &code);
42838da497aSMark Johnston break;
42938da497aSMark Johnston case 8:
43038da497aSMark Johnston valid = kasan_shadow_8byte_isvalid(addr, &code);
43138da497aSMark Johnston break;
43238da497aSMark Johnston default:
43338da497aSMark Johnston valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
43438da497aSMark Johnston break;
43538da497aSMark Johnston }
43638da497aSMark Johnston } else {
43738da497aSMark Johnston valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
43838da497aSMark Johnston }
43938da497aSMark Johnston
44038da497aSMark Johnston if (__predict_false(!valid)) {
44138da497aSMark Johnston kasan_report(addr, size, write, retaddr, code);
44238da497aSMark Johnston }
44338da497aSMark Johnston }
44438da497aSMark Johnston
44538da497aSMark Johnston /* -------------------------------------------------------------------------- */
44638da497aSMark Johnston
44738da497aSMark Johnston void *
kasan_memcpy(void * dst,const void * src,size_t len)44838da497aSMark Johnston kasan_memcpy(void *dst, const void *src, size_t len)
44938da497aSMark Johnston {
45038da497aSMark Johnston kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR);
45138da497aSMark Johnston kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR);
45238da497aSMark Johnston return (__builtin_memcpy(dst, src, len));
45338da497aSMark Johnston }
45438da497aSMark Johnston
45538da497aSMark Johnston int
kasan_memcmp(const void * b1,const void * b2,size_t len)45638da497aSMark Johnston kasan_memcmp(const void *b1, const void *b2, size_t len)
45738da497aSMark Johnston {
45838da497aSMark Johnston kasan_shadow_check((unsigned long)b1, len, false, __RET_ADDR);
45938da497aSMark Johnston kasan_shadow_check((unsigned long)b2, len, false, __RET_ADDR);
46038da497aSMark Johnston return (__builtin_memcmp(b1, b2, len));
46138da497aSMark Johnston }
46238da497aSMark Johnston
46338da497aSMark Johnston void *
kasan_memset(void * b,int c,size_t len)46438da497aSMark Johnston kasan_memset(void *b, int c, size_t len)
46538da497aSMark Johnston {
46638da497aSMark Johnston kasan_shadow_check((unsigned long)b, len, true, __RET_ADDR);
46738da497aSMark Johnston return (__builtin_memset(b, c, len));
46838da497aSMark Johnston }
46938da497aSMark Johnston
47038da497aSMark Johnston void *
kasan_memmove(void * dst,const void * src,size_t len)47138da497aSMark Johnston kasan_memmove(void *dst, const void *src, size_t len)
47238da497aSMark Johnston {
47338da497aSMark Johnston kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR);
47438da497aSMark Johnston kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR);
47538da497aSMark Johnston return (__builtin_memmove(dst, src, len));
47638da497aSMark Johnston }
47738da497aSMark Johnston
47838da497aSMark Johnston size_t
kasan_strlen(const char * str)47938da497aSMark Johnston kasan_strlen(const char *str)
48038da497aSMark Johnston {
48138da497aSMark Johnston const char *s;
48238da497aSMark Johnston
48338da497aSMark Johnston s = str;
48438da497aSMark Johnston while (1) {
48538da497aSMark Johnston kasan_shadow_check((unsigned long)s, 1, false, __RET_ADDR);
48638da497aSMark Johnston if (*s == '\0')
48738da497aSMark Johnston break;
48838da497aSMark Johnston s++;
48938da497aSMark Johnston }
49038da497aSMark Johnston
49138da497aSMark Johnston return (s - str);
49238da497aSMark Johnston }
49338da497aSMark Johnston
49438da497aSMark Johnston char *
kasan_strcpy(char * dst,const char * src)49538da497aSMark Johnston kasan_strcpy(char *dst, const char *src)
49638da497aSMark Johnston {
49738da497aSMark Johnston char *save = dst;
49838da497aSMark Johnston
49938da497aSMark Johnston while (1) {
50038da497aSMark Johnston kasan_shadow_check((unsigned long)src, 1, false, __RET_ADDR);
50138da497aSMark Johnston kasan_shadow_check((unsigned long)dst, 1, true, __RET_ADDR);
50238da497aSMark Johnston *dst = *src;
50338da497aSMark Johnston if (*src == '\0')
50438da497aSMark Johnston break;
50538da497aSMark Johnston src++, dst++;
50638da497aSMark Johnston }
50738da497aSMark Johnston
50838da497aSMark Johnston return save;
50938da497aSMark Johnston }
51038da497aSMark Johnston
51138da497aSMark Johnston int
kasan_strcmp(const char * s1,const char * s2)51238da497aSMark Johnston kasan_strcmp(const char *s1, const char *s2)
51338da497aSMark Johnston {
51438da497aSMark Johnston while (1) {
51538da497aSMark Johnston kasan_shadow_check((unsigned long)s1, 1, false, __RET_ADDR);
51638da497aSMark Johnston kasan_shadow_check((unsigned long)s2, 1, false, __RET_ADDR);
51738da497aSMark Johnston if (*s1 != *s2)
51838da497aSMark Johnston break;
51938da497aSMark Johnston if (*s1 == '\0')
52038da497aSMark Johnston return 0;
52138da497aSMark Johnston s1++, s2++;
52238da497aSMark Johnston }
52338da497aSMark Johnston
52438da497aSMark Johnston return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
52538da497aSMark Johnston }
52638da497aSMark Johnston
52738da497aSMark Johnston int
kasan_copyin(const void * uaddr,void * kaddr,size_t len)52838da497aSMark Johnston kasan_copyin(const void *uaddr, void *kaddr, size_t len)
52938da497aSMark Johnston {
53038da497aSMark Johnston kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR);
53138da497aSMark Johnston return (copyin(uaddr, kaddr, len));
53238da497aSMark Johnston }
53338da497aSMark Johnston
53438da497aSMark Johnston int
kasan_copyinstr(const void * uaddr,void * kaddr,size_t len,size_t * done)53538da497aSMark Johnston kasan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
53638da497aSMark Johnston {
53738da497aSMark Johnston kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR);
53838da497aSMark Johnston return (copyinstr(uaddr, kaddr, len, done));
53938da497aSMark Johnston }
54038da497aSMark Johnston
54138da497aSMark Johnston int
kasan_copyout(const void * kaddr,void * uaddr,size_t len)54238da497aSMark Johnston kasan_copyout(const void *kaddr, void *uaddr, size_t len)
54338da497aSMark Johnston {
54438da497aSMark Johnston kasan_shadow_check((unsigned long)kaddr, len, false, __RET_ADDR);
54538da497aSMark Johnston return (copyout(kaddr, uaddr, len));
54638da497aSMark Johnston }
54738da497aSMark Johnston
54838da497aSMark Johnston /* -------------------------------------------------------------------------- */
54938da497aSMark Johnston
5506f179693SMark Johnston int
kasan_fubyte(volatile const void * base)5516f179693SMark Johnston kasan_fubyte(volatile const void *base)
5526f179693SMark Johnston {
5536f179693SMark Johnston return (fubyte(base));
5546f179693SMark Johnston }
5556f179693SMark Johnston
5566f179693SMark Johnston int
kasan_fuword16(volatile const void * base)5576f179693SMark Johnston kasan_fuword16(volatile const void *base)
5586f179693SMark Johnston {
5596f179693SMark Johnston return (fuword16(base));
5606f179693SMark Johnston }
5616f179693SMark Johnston
5626f179693SMark Johnston int
kasan_fueword(volatile const void * base,long * val)5636f179693SMark Johnston kasan_fueword(volatile const void *base, long *val)
5646f179693SMark Johnston {
5656f179693SMark Johnston kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR);
5666f179693SMark Johnston return (fueword(base, val));
5676f179693SMark Johnston }
5686f179693SMark Johnston
5696f179693SMark Johnston int
kasan_fueword32(volatile const void * base,int32_t * val)5706f179693SMark Johnston kasan_fueword32(volatile const void *base, int32_t *val)
5716f179693SMark Johnston {
5726f179693SMark Johnston kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR);
5736f179693SMark Johnston return (fueword32(base, val));
5746f179693SMark Johnston }
5756f179693SMark Johnston
5766f179693SMark Johnston int
kasan_fueword64(volatile const void * base,int64_t * val)5776f179693SMark Johnston kasan_fueword64(volatile const void *base, int64_t *val)
5786f179693SMark Johnston {
5796f179693SMark Johnston kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR);
5806f179693SMark Johnston return (fueword64(base, val));
5816f179693SMark Johnston }
5826f179693SMark Johnston
5836f179693SMark Johnston int
kasan_subyte(volatile void * base,int byte)5846f179693SMark Johnston kasan_subyte(volatile void *base, int byte)
5856f179693SMark Johnston {
5866f179693SMark Johnston return (subyte(base, byte));
5876f179693SMark Johnston }
5886f179693SMark Johnston
5896f179693SMark Johnston int
kasan_suword(volatile void * base,long word)5906f179693SMark Johnston kasan_suword(volatile void *base, long word)
5916f179693SMark Johnston {
5926f179693SMark Johnston return (suword(base, word));
5936f179693SMark Johnston }
5946f179693SMark Johnston
5956f179693SMark Johnston int
kasan_suword16(volatile void * base,int word)5966f179693SMark Johnston kasan_suword16(volatile void *base, int word)
5976f179693SMark Johnston {
5986f179693SMark Johnston return (suword16(base, word));
5996f179693SMark Johnston }
6006f179693SMark Johnston
6016f179693SMark Johnston int
kasan_suword32(volatile void * base,int32_t word)6026f179693SMark Johnston kasan_suword32(volatile void *base, int32_t word)
6036f179693SMark Johnston {
6046f179693SMark Johnston return (suword32(base, word));
6056f179693SMark Johnston }
6066f179693SMark Johnston
6076f179693SMark Johnston int
kasan_suword64(volatile void * base,int64_t word)6086f179693SMark Johnston kasan_suword64(volatile void *base, int64_t word)
6096f179693SMark Johnston {
6106f179693SMark Johnston return (suword64(base, word));
6116f179693SMark Johnston }
6126f179693SMark Johnston
6136f179693SMark Johnston int
kasan_casueword32(volatile uint32_t * base,uint32_t oldval,uint32_t * oldvalp,uint32_t newval)6146f179693SMark Johnston kasan_casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,
6156f179693SMark Johnston uint32_t newval)
6166f179693SMark Johnston {
6176f179693SMark Johnston kasan_shadow_check((unsigned long)oldvalp, sizeof(*oldvalp), true,
6186f179693SMark Johnston __RET_ADDR);
6196f179693SMark Johnston return (casueword32(base, oldval, oldvalp, newval));
6206f179693SMark Johnston }
6216f179693SMark Johnston
6226f179693SMark Johnston int
kasan_casueword(volatile u_long * base,u_long oldval,u_long * oldvalp,u_long newval)6236f179693SMark Johnston kasan_casueword(volatile u_long *base, u_long oldval, u_long *oldvalp,
6246f179693SMark Johnston u_long newval)
6256f179693SMark Johnston {
6266f179693SMark Johnston kasan_shadow_check((unsigned long)oldvalp, sizeof(*oldvalp), true,
6276f179693SMark Johnston __RET_ADDR);
6286f179693SMark Johnston return (casueword(base, oldval, oldvalp, newval));
6296f179693SMark Johnston }
6306f179693SMark Johnston
6316f179693SMark Johnston /* -------------------------------------------------------------------------- */
6326f179693SMark Johnston
63338da497aSMark Johnston #include <machine/atomic.h>
63438da497aSMark Johnston #include <sys/atomic_san.h>
63538da497aSMark Johnston
63638da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_ADD(name, type) \
63738da497aSMark Johnston void kasan_atomic_add_##name(volatile type *ptr, type val) \
63838da497aSMark Johnston { \
63938da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
64038da497aSMark Johnston __RET_ADDR); \
64138da497aSMark Johnston atomic_add_##name(ptr, val); \
64238da497aSMark Johnston }
64338da497aSMark Johnston
64438da497aSMark Johnston #define ASAN_ATOMIC_FUNC_ADD(name, type) \
64538da497aSMark Johnston _ASAN_ATOMIC_FUNC_ADD(name, type) \
64638da497aSMark Johnston _ASAN_ATOMIC_FUNC_ADD(acq_##name, type) \
64738da497aSMark Johnston _ASAN_ATOMIC_FUNC_ADD(rel_##name, type)
64838da497aSMark Johnston
64938da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \
65038da497aSMark Johnston void kasan_atomic_subtract_##name(volatile type *ptr, type val) \
65138da497aSMark Johnston { \
65238da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
65338da497aSMark Johnston __RET_ADDR); \
65438da497aSMark Johnston atomic_subtract_##name(ptr, val); \
65538da497aSMark Johnston }
65638da497aSMark Johnston
65738da497aSMark Johnston #define ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \
65838da497aSMark Johnston _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \
65938da497aSMark Johnston _ASAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type) \
66038da497aSMark Johnston _ASAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
66138da497aSMark Johnston
66238da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_SET(name, type) \
66338da497aSMark Johnston void kasan_atomic_set_##name(volatile type *ptr, type val) \
66438da497aSMark Johnston { \
66538da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
66638da497aSMark Johnston __RET_ADDR); \
66738da497aSMark Johnston atomic_set_##name(ptr, val); \
66838da497aSMark Johnston }
66938da497aSMark Johnston
67038da497aSMark Johnston #define ASAN_ATOMIC_FUNC_SET(name, type) \
67138da497aSMark Johnston _ASAN_ATOMIC_FUNC_SET(name, type) \
67238da497aSMark Johnston _ASAN_ATOMIC_FUNC_SET(acq_##name, type) \
67338da497aSMark Johnston _ASAN_ATOMIC_FUNC_SET(rel_##name, type)
67438da497aSMark Johnston
67538da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_CLEAR(name, type) \
67638da497aSMark Johnston void kasan_atomic_clear_##name(volatile type *ptr, type val) \
67738da497aSMark Johnston { \
67838da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
67938da497aSMark Johnston __RET_ADDR); \
68038da497aSMark Johnston atomic_clear_##name(ptr, val); \
68138da497aSMark Johnston }
68238da497aSMark Johnston
68338da497aSMark Johnston #define ASAN_ATOMIC_FUNC_CLEAR(name, type) \
68438da497aSMark Johnston _ASAN_ATOMIC_FUNC_CLEAR(name, type) \
68538da497aSMark Johnston _ASAN_ATOMIC_FUNC_CLEAR(acq_##name, type) \
68638da497aSMark Johnston _ASAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
68738da497aSMark Johnston
68838da497aSMark Johnston #define ASAN_ATOMIC_FUNC_FETCHADD(name, type) \
68938da497aSMark Johnston type kasan_atomic_fetchadd_##name(volatile type *ptr, type val) \
69038da497aSMark Johnston { \
69138da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
69238da497aSMark Johnston __RET_ADDR); \
69338da497aSMark Johnston return (atomic_fetchadd_##name(ptr, val)); \
69438da497aSMark Johnston }
69538da497aSMark Johnston
69638da497aSMark Johnston #define ASAN_ATOMIC_FUNC_READANDCLEAR(name, type) \
69738da497aSMark Johnston type kasan_atomic_readandclear_##name(volatile type *ptr) \
69838da497aSMark Johnston { \
69938da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
70038da497aSMark Johnston __RET_ADDR); \
70138da497aSMark Johnston return (atomic_readandclear_##name(ptr)); \
70238da497aSMark Johnston }
70338da497aSMark Johnston
70438da497aSMark Johnston #define ASAN_ATOMIC_FUNC_TESTANDCLEAR(name, type) \
70538da497aSMark Johnston int kasan_atomic_testandclear_##name(volatile type *ptr, u_int v) \
70638da497aSMark Johnston { \
70738da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
70838da497aSMark Johnston __RET_ADDR); \
70938da497aSMark Johnston return (atomic_testandclear_##name(ptr, v)); \
71038da497aSMark Johnston }
71138da497aSMark Johnston
71238da497aSMark Johnston #define ASAN_ATOMIC_FUNC_TESTANDSET(name, type) \
71338da497aSMark Johnston int kasan_atomic_testandset_##name(volatile type *ptr, u_int v) \
71438da497aSMark Johnston { \
71538da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
71638da497aSMark Johnston __RET_ADDR); \
71738da497aSMark Johnston return (atomic_testandset_##name(ptr, v)); \
71838da497aSMark Johnston }
71938da497aSMark Johnston
72038da497aSMark Johnston #define ASAN_ATOMIC_FUNC_SWAP(name, type) \
72138da497aSMark Johnston type kasan_atomic_swap_##name(volatile type *ptr, type val) \
72238da497aSMark Johnston { \
72338da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
72438da497aSMark Johnston __RET_ADDR); \
72538da497aSMark Johnston return (atomic_swap_##name(ptr, val)); \
72638da497aSMark Johnston }
72738da497aSMark Johnston
72838da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_CMPSET(name, type) \
72938da497aSMark Johnston int kasan_atomic_cmpset_##name(volatile type *ptr, type oval, \
73038da497aSMark Johnston type nval) \
73138da497aSMark Johnston { \
73238da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
73338da497aSMark Johnston __RET_ADDR); \
73438da497aSMark Johnston return (atomic_cmpset_##name(ptr, oval, nval)); \
73538da497aSMark Johnston }
73638da497aSMark Johnston
73738da497aSMark Johnston #define ASAN_ATOMIC_FUNC_CMPSET(name, type) \
73838da497aSMark Johnston _ASAN_ATOMIC_FUNC_CMPSET(name, type) \
73938da497aSMark Johnston _ASAN_ATOMIC_FUNC_CMPSET(acq_##name, type) \
74038da497aSMark Johnston _ASAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
74138da497aSMark Johnston
74238da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \
74338da497aSMark Johnston int kasan_atomic_fcmpset_##name(volatile type *ptr, type *oval, \
74438da497aSMark Johnston type nval) \
74538da497aSMark Johnston { \
74638da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
74738da497aSMark Johnston __RET_ADDR); \
74838da497aSMark Johnston return (atomic_fcmpset_##name(ptr, oval, nval)); \
74938da497aSMark Johnston }
75038da497aSMark Johnston
75138da497aSMark Johnston #define ASAN_ATOMIC_FUNC_FCMPSET(name, type) \
75238da497aSMark Johnston _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \
75338da497aSMark Johnston _ASAN_ATOMIC_FUNC_FCMPSET(acq_##name, type) \
75438da497aSMark Johnston _ASAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
75538da497aSMark Johnston
75638da497aSMark Johnston #define ASAN_ATOMIC_FUNC_THREAD_FENCE(name) \
75738da497aSMark Johnston void kasan_atomic_thread_fence_##name(void) \
75838da497aSMark Johnston { \
75938da497aSMark Johnston atomic_thread_fence_##name(); \
76038da497aSMark Johnston }
76138da497aSMark Johnston
76238da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_LOAD(name, type) \
763*fa5f4c10SMark Johnston type kasan_atomic_load_##name(const volatile type *ptr) \
76438da497aSMark Johnston { \
76538da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
76638da497aSMark Johnston __RET_ADDR); \
76738da497aSMark Johnston return (atomic_load_##name(ptr)); \
76838da497aSMark Johnston }
76938da497aSMark Johnston
77038da497aSMark Johnston #define ASAN_ATOMIC_FUNC_LOAD(name, type) \
77138da497aSMark Johnston _ASAN_ATOMIC_FUNC_LOAD(name, type) \
77238da497aSMark Johnston _ASAN_ATOMIC_FUNC_LOAD(acq_##name, type)
77338da497aSMark Johnston
77438da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_STORE(name, type) \
77538da497aSMark Johnston void kasan_atomic_store_##name(volatile type *ptr, type val) \
77638da497aSMark Johnston { \
77738da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \
77838da497aSMark Johnston __RET_ADDR); \
77938da497aSMark Johnston atomic_store_##name(ptr, val); \
78038da497aSMark Johnston }
78138da497aSMark Johnston
78238da497aSMark Johnston #define ASAN_ATOMIC_FUNC_STORE(name, type) \
78338da497aSMark Johnston _ASAN_ATOMIC_FUNC_STORE(name, type) \
78438da497aSMark Johnston _ASAN_ATOMIC_FUNC_STORE(rel_##name, type)
78538da497aSMark Johnston
78638da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(8, uint8_t);
78738da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(16, uint16_t);
78838da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(32, uint32_t);
78938da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(64, uint64_t);
79038da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(int, u_int);
79138da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(long, u_long);
79238da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(ptr, uintptr_t);
79338da497aSMark Johnston
79438da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t);
79538da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t);
79638da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t);
79738da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t);
79838da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(int, u_int);
79938da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(long, u_long);
80038da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t);
80138da497aSMark Johnston
80238da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(8, uint8_t);
80338da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(16, uint16_t);
80438da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(32, uint32_t);
80538da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(64, uint64_t);
80638da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(int, u_int);
80738da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(long, u_long);
80838da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(ptr, uintptr_t);
80938da497aSMark Johnston
81038da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(8, uint8_t);
81138da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(16, uint16_t);
81238da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(32, uint32_t);
81338da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(64, uint64_t);
81438da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(int, u_int);
81538da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(long, u_long);
81638da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t);
81738da497aSMark Johnston
81838da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(32, uint32_t);
81938da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(64, uint64_t);
82038da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(int, u_int);
82138da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(long, u_long);
82238da497aSMark Johnston
82338da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t);
82438da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t);
82538da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(int, u_int);
82638da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(long, u_long);
82738da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t);
82838da497aSMark Johnston
82938da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t);
83038da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t);
83138da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int);
83238da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long);
833a80b9ee1SJohn Baldwin ASAN_ATOMIC_FUNC_TESTANDCLEAR(ptr, uintptr_t);
83438da497aSMark Johnston
83538da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t);
83638da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t);
83738da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(int, u_int);
83838da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(long, u_long);
839a80b9ee1SJohn Baldwin ASAN_ATOMIC_FUNC_TESTANDSET(ptr, uintptr_t);
84038da497aSMark Johnston
84138da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(32, uint32_t);
84238da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(64, uint64_t);
84338da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(int, u_int);
84438da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(long, u_long);
84538da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t);
84638da497aSMark Johnston
84738da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(8, uint8_t);
84838da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(16, uint16_t);
84938da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(32, uint32_t);
85038da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(64, uint64_t);
85138da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(int, u_int);
85238da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(long, u_long);
85338da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t);
85438da497aSMark Johnston
85538da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(8, uint8_t);
85638da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(16, uint16_t);
85738da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(32, uint32_t);
85838da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(64, uint64_t);
85938da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(int, u_int);
86038da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(long, u_long);
86138da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t);
86238da497aSMark Johnston
8631f6b6cf1SMark Johnston _ASAN_ATOMIC_FUNC_LOAD(bool, bool);
86438da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(8, uint8_t);
86538da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(16, uint16_t);
86638da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(32, uint32_t);
86738da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(64, uint64_t);
86838da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(char, u_char);
86938da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(short, u_short);
87038da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(int, u_int);
87138da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(long, u_long);
87238da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t);
87338da497aSMark Johnston
8741f6b6cf1SMark Johnston _ASAN_ATOMIC_FUNC_STORE(bool, bool);
87538da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(8, uint8_t);
87638da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(16, uint16_t);
87738da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(32, uint32_t);
87838da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(64, uint64_t);
87938da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(char, u_char);
88038da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(short, u_short);
88138da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(int, u_int);
88238da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(long, u_long);
88338da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(ptr, uintptr_t);
88438da497aSMark Johnston
88538da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(acq);
88638da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(rel);
88738da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel);
88838da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst);
88938da497aSMark Johnston
89038da497aSMark Johnston void
kasan_atomic_interrupt_fence(void)89138da497aSMark Johnston kasan_atomic_interrupt_fence(void)
89238da497aSMark Johnston {
89338da497aSMark Johnston }
89438da497aSMark Johnston
89538da497aSMark Johnston /* -------------------------------------------------------------------------- */
89638da497aSMark Johnston
89738da497aSMark Johnston #include <sys/bus.h>
89838da497aSMark Johnston #include <machine/bus.h>
89938da497aSMark Johnston #include <sys/bus_san.h>
90038da497aSMark Johnston
90138da497aSMark Johnston 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)90238da497aSMark Johnston kasan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
90338da497aSMark Johnston int flags, bus_space_handle_t *handlep)
90438da497aSMark Johnston {
90538da497aSMark Johnston return (bus_space_map(tag, hnd, size, flags, handlep));
90638da497aSMark Johnston }
90738da497aSMark Johnston
90838da497aSMark Johnston void
kasan_bus_space_unmap(bus_space_tag_t tag,bus_space_handle_t hnd,bus_size_t size)90938da497aSMark Johnston kasan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
91038da497aSMark Johnston bus_size_t size)
91138da497aSMark Johnston {
91238da497aSMark Johnston bus_space_unmap(tag, hnd, size);
91338da497aSMark Johnston }
91438da497aSMark Johnston
91538da497aSMark Johnston 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)91638da497aSMark Johnston kasan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
91738da497aSMark Johnston bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
91838da497aSMark Johnston {
91938da497aSMark Johnston return (bus_space_subregion(tag, hnd, offset, size, handlep));
92038da497aSMark Johnston }
92138da497aSMark Johnston
92238da497aSMark Johnston void
kasan_bus_space_free(bus_space_tag_t tag,bus_space_handle_t hnd,bus_size_t size)92338da497aSMark Johnston kasan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
92438da497aSMark Johnston bus_size_t size)
92538da497aSMark Johnston {
92638da497aSMark Johnston bus_space_free(tag, hnd, size);
92738da497aSMark Johnston }
92838da497aSMark Johnston
92938da497aSMark Johnston 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)93038da497aSMark Johnston kasan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
93138da497aSMark Johnston bus_size_t offset, bus_size_t size, int flags)
93238da497aSMark Johnston {
93338da497aSMark Johnston bus_space_barrier(tag, hnd, offset, size, flags);
93438da497aSMark Johnston }
93538da497aSMark Johnston
93638da497aSMark Johnston #define ASAN_BUS_READ_FUNC(func, width, type) \
93738da497aSMark Johnston type kasan_bus_space_read##func##_##width(bus_space_tag_t tag, \
93838da497aSMark Johnston bus_space_handle_t hnd, bus_size_t offset) \
93938da497aSMark Johnston { \
94038da497aSMark Johnston return (bus_space_read##func##_##width(tag, hnd, \
94138da497aSMark Johnston offset)); \
94238da497aSMark Johnston } \
94338da497aSMark Johnston
94438da497aSMark Johnston #define ASAN_BUS_READ_PTR_FUNC(func, width, type) \
94538da497aSMark Johnston void kasan_bus_space_read_##func##_##width(bus_space_tag_t tag, \
94638da497aSMark Johnston bus_space_handle_t hnd, bus_size_t size, type *buf, \
94738da497aSMark Johnston bus_size_t count) \
94838da497aSMark Johnston { \
94938da497aSMark Johnston kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
95038da497aSMark Johnston false, __RET_ADDR); \
95138da497aSMark Johnston bus_space_read_##func##_##width(tag, hnd, size, buf, \
95238da497aSMark Johnston count); \
95338da497aSMark Johnston }
95438da497aSMark Johnston
95538da497aSMark Johnston ASAN_BUS_READ_FUNC(, 1, uint8_t)
95638da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 1, uint8_t)
95738da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
95838da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
95938da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 1, uint8_t)
96038da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
96138da497aSMark Johnston
96238da497aSMark Johnston ASAN_BUS_READ_FUNC(, 2, uint16_t)
96338da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 2, uint16_t)
96438da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
96538da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
96638da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
96738da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
96838da497aSMark Johnston
96938da497aSMark Johnston ASAN_BUS_READ_FUNC(, 4, uint32_t)
97038da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 4, uint32_t)
97138da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
97238da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
97338da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
97438da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
97538da497aSMark Johnston
97638da497aSMark Johnston ASAN_BUS_READ_FUNC(, 8, uint64_t)
97742742fe7SBjoern A. Zeeb #if defined(__aarch64__)
97842742fe7SBjoern A. Zeeb ASAN_BUS_READ_FUNC(_stream, 8, uint64_t)
97942742fe7SBjoern A. Zeeb ASAN_BUS_READ_PTR_FUNC(multi, 8, uint64_t)
98042742fe7SBjoern A. Zeeb ASAN_BUS_READ_PTR_FUNC(multi_stream, 8, uint64_t)
98142742fe7SBjoern A. Zeeb ASAN_BUS_READ_PTR_FUNC(region, 8, uint64_t)
98242742fe7SBjoern A. Zeeb ASAN_BUS_READ_PTR_FUNC(region_stream, 8, uint64_t)
98342742fe7SBjoern A. Zeeb #endif
98438da497aSMark Johnston
98538da497aSMark Johnston #define ASAN_BUS_WRITE_FUNC(func, width, type) \
98638da497aSMark Johnston void kasan_bus_space_write##func##_##width(bus_space_tag_t tag, \
98738da497aSMark Johnston bus_space_handle_t hnd, bus_size_t offset, type value) \
98838da497aSMark Johnston { \
98938da497aSMark Johnston bus_space_write##func##_##width(tag, hnd, offset, value);\
99038da497aSMark Johnston } \
99138da497aSMark Johnston
99238da497aSMark Johnston #define ASAN_BUS_WRITE_PTR_FUNC(func, width, type) \
99338da497aSMark Johnston void kasan_bus_space_write_##func##_##width(bus_space_tag_t tag,\
99438da497aSMark Johnston bus_space_handle_t hnd, bus_size_t size, const type *buf, \
99538da497aSMark Johnston bus_size_t count) \
99638da497aSMark Johnston { \
99738da497aSMark Johnston kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
99838da497aSMark Johnston true, __RET_ADDR); \
99938da497aSMark Johnston bus_space_write_##func##_##width(tag, hnd, size, buf, \
100038da497aSMark Johnston count); \
100138da497aSMark Johnston }
100238da497aSMark Johnston
100338da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 1, uint8_t)
100438da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
100538da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
100638da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
100738da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t)
100838da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
100938da497aSMark Johnston
101038da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 2, uint16_t)
101138da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
101238da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
101338da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
101438da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t)
101538da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
101638da497aSMark Johnston
101738da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 4, uint32_t)
101838da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
101938da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
102038da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
102138da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t)
102238da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
102338da497aSMark Johnston
102438da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 8, uint64_t)
102538da497aSMark Johnston
102638da497aSMark Johnston #define ASAN_BUS_SET_FUNC(func, width, type) \
102738da497aSMark Johnston void kasan_bus_space_set_##func##_##width(bus_space_tag_t tag, \
102838da497aSMark Johnston bus_space_handle_t hnd, bus_size_t offset, type value, \
102938da497aSMark Johnston bus_size_t count) \
103038da497aSMark Johnston { \
103138da497aSMark Johnston bus_space_set_##func##_##width(tag, hnd, offset, value, \
103238da497aSMark Johnston count); \
103338da497aSMark Johnston }
103438da497aSMark Johnston
103538da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 1, uint8_t)
103638da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 1, uint8_t)
103738da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
103838da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
103938da497aSMark Johnston
104038da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 2, uint16_t)
104138da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 2, uint16_t)
104238da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
104338da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
104438da497aSMark Johnston
104538da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 4, uint32_t)
104638da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 4, uint32_t)
104738da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
104838da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
104938da497aSMark Johnston
1050818cae0fSMitchell Horne #define ASAN_BUS_PEEK_FUNC(width, type) \
1051818cae0fSMitchell Horne int kasan_bus_space_peek_##width(bus_space_tag_t tag, \
1052818cae0fSMitchell Horne bus_space_handle_t hnd, bus_size_t offset, type *valuep) \
1053818cae0fSMitchell Horne { \
1054818cae0fSMitchell Horne return (bus_space_peek_##width(tag, hnd, offset, \
1055818cae0fSMitchell Horne valuep)); \
1056818cae0fSMitchell Horne }
1057818cae0fSMitchell Horne
1058818cae0fSMitchell Horne ASAN_BUS_PEEK_FUNC(1, uint8_t)
1059818cae0fSMitchell Horne ASAN_BUS_PEEK_FUNC(2, uint16_t)
1060818cae0fSMitchell Horne ASAN_BUS_PEEK_FUNC(4, uint32_t)
1061818cae0fSMitchell Horne ASAN_BUS_PEEK_FUNC(8, uint64_t)
1062818cae0fSMitchell Horne
1063818cae0fSMitchell Horne #define ASAN_BUS_POKE_FUNC(width, type) \
1064818cae0fSMitchell Horne int kasan_bus_space_poke_##width(bus_space_tag_t tag, \
1065818cae0fSMitchell Horne bus_space_handle_t hnd, bus_size_t offset, type value) \
1066818cae0fSMitchell Horne { \
1067818cae0fSMitchell Horne return (bus_space_poke_##width(tag, hnd, offset, \
1068818cae0fSMitchell Horne value)); \
1069818cae0fSMitchell Horne }
1070818cae0fSMitchell Horne
1071818cae0fSMitchell Horne ASAN_BUS_POKE_FUNC(1, uint8_t)
1072818cae0fSMitchell Horne ASAN_BUS_POKE_FUNC(2, uint16_t)
1073818cae0fSMitchell Horne ASAN_BUS_POKE_FUNC(4, uint32_t)
1074818cae0fSMitchell Horne ASAN_BUS_POKE_FUNC(8, uint64_t)
1075818cae0fSMitchell Horne
107638da497aSMark Johnston /* -------------------------------------------------------------------------- */
107738da497aSMark Johnston
107838da497aSMark Johnston void __asan_register_globals(struct __asan_global *, size_t);
107938da497aSMark Johnston void __asan_unregister_globals(struct __asan_global *, size_t);
108038da497aSMark Johnston
108138da497aSMark Johnston void
__asan_register_globals(struct __asan_global * globals,size_t n)108238da497aSMark Johnston __asan_register_globals(struct __asan_global *globals, size_t n)
108338da497aSMark Johnston {
108438da497aSMark Johnston size_t i;
108538da497aSMark Johnston
108638da497aSMark Johnston for (i = 0; i < n; i++) {
108738da497aSMark Johnston kasan_mark(globals[i].beg, globals[i].size,
108838da497aSMark Johnston globals[i].size_with_redzone, KASAN_GENERIC_REDZONE);
108938da497aSMark Johnston }
109038da497aSMark Johnston }
109138da497aSMark Johnston
109238da497aSMark Johnston void
__asan_unregister_globals(struct __asan_global * globals,size_t n)109338da497aSMark Johnston __asan_unregister_globals(struct __asan_global *globals, size_t n)
109438da497aSMark Johnston {
1095588c7a06SMark Johnston size_t i;
1096588c7a06SMark Johnston
1097588c7a06SMark Johnston for (i = 0; i < n; i++) {
1098588c7a06SMark Johnston kasan_mark(globals[i].beg, globals[i].size_with_redzone,
1099588c7a06SMark Johnston globals[i].size_with_redzone, 0);
1100588c7a06SMark Johnston }
110138da497aSMark Johnston }
110238da497aSMark Johnston
110338da497aSMark Johnston #define ASAN_LOAD_STORE(size) \
110438da497aSMark Johnston void __asan_load##size(unsigned long); \
110538da497aSMark Johnston void __asan_load##size(unsigned long addr) \
110638da497aSMark Johnston { \
110738da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR);\
110838da497aSMark Johnston } \
110938da497aSMark Johnston void __asan_load##size##_noabort(unsigned long); \
111038da497aSMark Johnston void __asan_load##size##_noabort(unsigned long addr) \
111138da497aSMark Johnston { \
111238da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR);\
111338da497aSMark Johnston } \
111438da497aSMark Johnston void __asan_store##size(unsigned long); \
111538da497aSMark Johnston void __asan_store##size(unsigned long addr) \
111638da497aSMark Johnston { \
111738da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR);\
111838da497aSMark Johnston } \
111938da497aSMark Johnston void __asan_store##size##_noabort(unsigned long); \
112038da497aSMark Johnston void __asan_store##size##_noabort(unsigned long addr) \
112138da497aSMark Johnston { \
112238da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR);\
112338da497aSMark Johnston }
112438da497aSMark Johnston
112538da497aSMark Johnston ASAN_LOAD_STORE(1);
112638da497aSMark Johnston ASAN_LOAD_STORE(2);
112738da497aSMark Johnston ASAN_LOAD_STORE(4);
112838da497aSMark Johnston ASAN_LOAD_STORE(8);
112938da497aSMark Johnston ASAN_LOAD_STORE(16);
113038da497aSMark Johnston
113138da497aSMark Johnston void __asan_loadN(unsigned long, size_t);
113238da497aSMark Johnston void __asan_loadN_noabort(unsigned long, size_t);
113338da497aSMark Johnston void __asan_storeN(unsigned long, size_t);
113438da497aSMark Johnston void __asan_storeN_noabort(unsigned long, size_t);
113538da497aSMark Johnston void __asan_handle_no_return(void);
113638da497aSMark Johnston
113738da497aSMark Johnston void
__asan_loadN(unsigned long addr,size_t size)113838da497aSMark Johnston __asan_loadN(unsigned long addr, size_t size)
113938da497aSMark Johnston {
114038da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR);
114138da497aSMark Johnston }
114238da497aSMark Johnston
114338da497aSMark Johnston void
__asan_loadN_noabort(unsigned long addr,size_t size)114438da497aSMark Johnston __asan_loadN_noabort(unsigned long addr, size_t size)
114538da497aSMark Johnston {
114638da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR);
114738da497aSMark Johnston }
114838da497aSMark Johnston
114938da497aSMark Johnston void
__asan_storeN(unsigned long addr,size_t size)115038da497aSMark Johnston __asan_storeN(unsigned long addr, size_t size)
115138da497aSMark Johnston {
115238da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR);
115338da497aSMark Johnston }
115438da497aSMark Johnston
115538da497aSMark Johnston void
__asan_storeN_noabort(unsigned long addr,size_t size)115638da497aSMark Johnston __asan_storeN_noabort(unsigned long addr, size_t size)
115738da497aSMark Johnston {
115838da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR);
115938da497aSMark Johnston }
116038da497aSMark Johnston
116138da497aSMark Johnston void
__asan_handle_no_return(void)116238da497aSMark Johnston __asan_handle_no_return(void)
116338da497aSMark Johnston {
116438da497aSMark Johnston /* nothing */
116538da497aSMark Johnston }
116638da497aSMark Johnston
116738da497aSMark Johnston #define ASAN_SET_SHADOW(byte) \
116838da497aSMark Johnston void __asan_set_shadow_##byte(void *, size_t); \
116938da497aSMark Johnston void __asan_set_shadow_##byte(void *addr, size_t size) \
117038da497aSMark Johnston { \
117138da497aSMark Johnston __builtin_memset((void *)addr, 0x##byte, size); \
117238da497aSMark Johnston }
117338da497aSMark Johnston
117438da497aSMark Johnston ASAN_SET_SHADOW(00);
117538da497aSMark Johnston ASAN_SET_SHADOW(f1);
117638da497aSMark Johnston ASAN_SET_SHADOW(f2);
117738da497aSMark Johnston ASAN_SET_SHADOW(f3);
117838da497aSMark Johnston ASAN_SET_SHADOW(f5);
117938da497aSMark Johnston ASAN_SET_SHADOW(f8);
118038da497aSMark Johnston
118138da497aSMark Johnston void __asan_poison_stack_memory(const void *, size_t);
118238da497aSMark Johnston void __asan_unpoison_stack_memory(const void *, size_t);
118338da497aSMark Johnston
118438da497aSMark Johnston void
__asan_poison_stack_memory(const void * addr,size_t size)118538da497aSMark Johnston __asan_poison_stack_memory(const void *addr, size_t size)
118638da497aSMark Johnston {
118738da497aSMark Johnston size = roundup(size, KASAN_SHADOW_SCALE);
118838da497aSMark Johnston kasan_shadow_Nbyte_fill(addr, size, KASAN_USE_AFTER_SCOPE);
118938da497aSMark Johnston }
119038da497aSMark Johnston
119138da497aSMark Johnston void
__asan_unpoison_stack_memory(const void * addr,size_t size)119238da497aSMark Johnston __asan_unpoison_stack_memory(const void *addr, size_t size)
119338da497aSMark Johnston {
119438da497aSMark Johnston kasan_shadow_Nbyte_markvalid(addr, size);
119538da497aSMark Johnston }
119638da497aSMark Johnston
119738da497aSMark Johnston void __asan_alloca_poison(const void *, size_t);
119838da497aSMark Johnston void __asan_allocas_unpoison(const void *, const void *);
119938da497aSMark Johnston
120038da497aSMark Johnston void
__asan_alloca_poison(const void * addr,size_t size)120138da497aSMark Johnston __asan_alloca_poison(const void *addr, size_t size)
120238da497aSMark Johnston {
120338da497aSMark Johnston const void *l, *r;
120438da497aSMark Johnston
120538da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_ALLOCA_SCALE_SIZE == 0,
120638da497aSMark Johnston ("%s: invalid address %p", __func__, addr));
120738da497aSMark Johnston
120838da497aSMark Johnston l = (const uint8_t *)addr - KASAN_ALLOCA_SCALE_SIZE;
120938da497aSMark Johnston r = (const uint8_t *)addr + roundup(size, KASAN_ALLOCA_SCALE_SIZE);
121038da497aSMark Johnston
121138da497aSMark Johnston kasan_shadow_Nbyte_fill(l, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_LEFT);
121238da497aSMark Johnston kasan_mark(addr, size, roundup(size, KASAN_ALLOCA_SCALE_SIZE),
121338da497aSMark Johnston KASAN_STACK_MID);
121438da497aSMark Johnston kasan_shadow_Nbyte_fill(r, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_RIGHT);
121538da497aSMark Johnston }
121638da497aSMark Johnston
121738da497aSMark Johnston void
__asan_allocas_unpoison(const void * stkbegin,const void * stkend)121838da497aSMark Johnston __asan_allocas_unpoison(const void *stkbegin, const void *stkend)
121938da497aSMark Johnston {
122038da497aSMark Johnston size_t size;
122138da497aSMark Johnston
122238da497aSMark Johnston if (__predict_false(!stkbegin))
122338da497aSMark Johnston return;
122438da497aSMark Johnston if (__predict_false((uintptr_t)stkbegin > (uintptr_t)stkend))
122538da497aSMark Johnston return;
122638da497aSMark Johnston size = (uintptr_t)stkend - (uintptr_t)stkbegin;
122738da497aSMark Johnston
122838da497aSMark Johnston kasan_shadow_Nbyte_fill(stkbegin, size, 0);
122938da497aSMark Johnston }
123038da497aSMark Johnston
123138da497aSMark Johnston void __asan_poison_memory_region(const void *addr, size_t size);
123238da497aSMark Johnston void __asan_unpoison_memory_region(const void *addr, size_t size);
123338da497aSMark Johnston
123438da497aSMark Johnston void
__asan_poison_memory_region(const void * addr,size_t size)123538da497aSMark Johnston __asan_poison_memory_region(const void *addr, size_t size)
123638da497aSMark Johnston {
123738da497aSMark Johnston }
123838da497aSMark Johnston
123938da497aSMark Johnston void
__asan_unpoison_memory_region(const void * addr,size_t size)124038da497aSMark Johnston __asan_unpoison_memory_region(const void *addr, size_t size)
124138da497aSMark Johnston {
124238da497aSMark Johnston }
1243