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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 * 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 * 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 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 * 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 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 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 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 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 5516f179693SMark Johnston kasan_fubyte(volatile const void *base) 5526f179693SMark Johnston { 5536f179693SMark Johnston return (fubyte(base)); 5546f179693SMark Johnston } 5556f179693SMark Johnston 5566f179693SMark Johnston int 5576f179693SMark Johnston kasan_fuword16(volatile const void *base) 5586f179693SMark Johnston { 5596f179693SMark Johnston return (fuword16(base)); 5606f179693SMark Johnston } 5616f179693SMark Johnston 5626f179693SMark Johnston int 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 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 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 5846f179693SMark Johnston kasan_subyte(volatile void *base, int byte) 5856f179693SMark Johnston { 5866f179693SMark Johnston return (subyte(base, byte)); 5876f179693SMark Johnston } 5886f179693SMark Johnston 5896f179693SMark Johnston int 5906f179693SMark Johnston kasan_suword(volatile void *base, long word) 5916f179693SMark Johnston { 5926f179693SMark Johnston return (suword(base, word)); 5936f179693SMark Johnston } 5946f179693SMark Johnston 5956f179693SMark Johnston int 5966f179693SMark Johnston kasan_suword16(volatile void *base, int word) 5976f179693SMark Johnston { 5986f179693SMark Johnston return (suword16(base, word)); 5996f179693SMark Johnston } 6006f179693SMark Johnston 6016f179693SMark Johnston int 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 123538da497aSMark Johnston __asan_poison_memory_region(const void *addr, size_t size) 123638da497aSMark Johnston { 123738da497aSMark Johnston } 123838da497aSMark Johnston 123938da497aSMark Johnston void 124038da497aSMark Johnston __asan_unpoison_memory_region(const void *addr, size_t size) 124138da497aSMark Johnston { 124238da497aSMark Johnston } 1243