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 __FBSDID("$FreeBSD$"); 3538da497aSMark Johnston #if 0 3638da497aSMark Johnston __KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $"); 3738da497aSMark Johnston #endif 3838da497aSMark Johnston 3938da497aSMark Johnston #include <sys/param.h> 4038da497aSMark Johnston #include <sys/systm.h> 4138da497aSMark Johnston #include <sys/asan.h> 4238da497aSMark Johnston #include <sys/kernel.h> 4338da497aSMark Johnston #include <sys/stack.h> 4438da497aSMark Johnston #include <sys/sysctl.h> 4538da497aSMark Johnston 4638da497aSMark Johnston #include <machine/asan.h> 47*818cae0fSMitchell 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 9638da497aSMark Johnston static bool kasan_enabled __read_mostly = false; 9738da497aSMark Johnston 9838da497aSMark Johnston /* -------------------------------------------------------------------------- */ 9938da497aSMark Johnston 10038da497aSMark Johnston void 10120e3b9d8SMark Johnston kasan_shadow_map(vm_offset_t addr, size_t size) 10238da497aSMark Johnston { 10338da497aSMark Johnston size_t sz, npages, i; 10438da497aSMark Johnston vm_offset_t sva, eva; 10538da497aSMark Johnston 10620e3b9d8SMark Johnston KASSERT(addr % KASAN_SHADOW_SCALE == 0, 10720e3b9d8SMark Johnston ("%s: invalid address %#lx", __func__, addr)); 10838da497aSMark Johnston 10938da497aSMark Johnston sz = roundup(size, KASAN_SHADOW_SCALE) / KASAN_SHADOW_SCALE; 11038da497aSMark Johnston 11120e3b9d8SMark Johnston sva = kasan_md_addr_to_shad(addr); 11220e3b9d8SMark Johnston eva = kasan_md_addr_to_shad(addr) + sz; 11338da497aSMark Johnston 11438da497aSMark Johnston sva = rounddown(sva, PAGE_SIZE); 11538da497aSMark Johnston eva = roundup(eva, PAGE_SIZE); 11638da497aSMark Johnston 11738da497aSMark Johnston npages = (eva - sva) / PAGE_SIZE; 11838da497aSMark Johnston 11938da497aSMark Johnston KASSERT(sva >= KASAN_MIN_ADDRESS && eva < KASAN_MAX_ADDRESS, 12038da497aSMark Johnston ("%s: invalid address range %#lx-%#lx", __func__, sva, eva)); 12138da497aSMark Johnston 12238da497aSMark Johnston for (i = 0; i < npages; i++) 123175d3380SMark Johnston pmap_san_enter(sva + ptoa(i)); 12438da497aSMark Johnston } 12538da497aSMark Johnston 12638da497aSMark Johnston void 12738da497aSMark Johnston kasan_init(void) 12838da497aSMark Johnston { 12938da497aSMark Johnston int disabled; 13038da497aSMark Johnston 13138da497aSMark Johnston disabled = 0; 13238da497aSMark Johnston TUNABLE_INT_FETCH("debug.kasan.disabled", &disabled); 13338da497aSMark Johnston if (disabled) 13438da497aSMark Johnston return; 13538da497aSMark Johnston 13638da497aSMark Johnston /* MD initialization. */ 13738da497aSMark Johnston kasan_md_init(); 13838da497aSMark Johnston 13938da497aSMark Johnston /* Now officially enabled. */ 14038da497aSMark Johnston kasan_enabled = true; 14138da497aSMark Johnston } 14238da497aSMark Johnston 143756bc3adSMark Johnston void 144756bc3adSMark Johnston kasan_init_early(vm_offset_t stack, size_t size) 145756bc3adSMark Johnston { 146756bc3adSMark Johnston kasan_md_init_early(stack, size); 147756bc3adSMark Johnston } 148756bc3adSMark Johnston 14938da497aSMark Johnston static inline const char * 15038da497aSMark Johnston kasan_code_name(uint8_t code) 15138da497aSMark Johnston { 15238da497aSMark Johnston switch (code) { 15338da497aSMark Johnston case KASAN_GENERIC_REDZONE: 15438da497aSMark Johnston return "GenericRedZone"; 15538da497aSMark Johnston case KASAN_MALLOC_REDZONE: 15638da497aSMark Johnston return "MallocRedZone"; 15738da497aSMark Johnston case KASAN_KMEM_REDZONE: 15838da497aSMark Johnston return "KmemRedZone"; 15938da497aSMark Johnston case KASAN_UMA_FREED: 16038da497aSMark Johnston return "UMAUseAfterFree"; 16138da497aSMark Johnston case KASAN_KSTACK_FREED: 16238da497aSMark Johnston return "KernelStack"; 163f1c3adefSMark Johnston case KASAN_EXEC_ARGS_FREED: 164f1c3adefSMark Johnston return "ExecKVA"; 16538da497aSMark Johnston case 1 ... 7: 16638da497aSMark Johnston return "RedZonePartial"; 16738da497aSMark Johnston case KASAN_STACK_LEFT: 16838da497aSMark Johnston return "StackLeft"; 16938da497aSMark Johnston case KASAN_STACK_MID: 17038da497aSMark Johnston return "StackMiddle"; 17138da497aSMark Johnston case KASAN_STACK_RIGHT: 17238da497aSMark Johnston return "StackRight"; 17338da497aSMark Johnston case KASAN_USE_AFTER_RET: 17438da497aSMark Johnston return "UseAfterRet"; 17538da497aSMark Johnston case KASAN_USE_AFTER_SCOPE: 17638da497aSMark Johnston return "UseAfterScope"; 17738da497aSMark Johnston default: 17838da497aSMark Johnston return "Unknown"; 17938da497aSMark Johnston } 18038da497aSMark Johnston } 18138da497aSMark Johnston 18238da497aSMark Johnston #define REPORT(f, ...) do { \ 18338da497aSMark Johnston if (panic_on_violation) { \ 184ea3fbe07SMark Johnston kasan_enabled = false; \ 18538da497aSMark Johnston panic(f, __VA_ARGS__); \ 18638da497aSMark Johnston } else { \ 18738da497aSMark Johnston struct stack st; \ 18838da497aSMark Johnston \ 18938da497aSMark Johnston stack_save(&st); \ 19038da497aSMark Johnston printf(f "\n", __VA_ARGS__); \ 19138da497aSMark Johnston stack_print_ddb(&st); \ 19238da497aSMark Johnston } \ 19338da497aSMark Johnston } while (0) 19438da497aSMark Johnston 19538da497aSMark Johnston static void 19638da497aSMark Johnston kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc, 19738da497aSMark Johnston uint8_t code) 19838da497aSMark Johnston { 19938da497aSMark Johnston REPORT("ASan: Invalid access, %zu-byte %s at %#lx, %s(%x)", 20038da497aSMark Johnston size, (write ? "write" : "read"), addr, kasan_code_name(code), 20138da497aSMark Johnston code); 20238da497aSMark Johnston } 20338da497aSMark Johnston 20438da497aSMark Johnston static __always_inline void 20538da497aSMark Johnston kasan_shadow_1byte_markvalid(unsigned long addr) 20638da497aSMark Johnston { 20738da497aSMark Johnston int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr); 20838da497aSMark Johnston int8_t last = (addr & KASAN_SHADOW_MASK) + 1; 20938da497aSMark Johnston 21038da497aSMark Johnston *byte = last; 21138da497aSMark Johnston } 21238da497aSMark Johnston 21338da497aSMark Johnston static __always_inline void 21438da497aSMark Johnston kasan_shadow_Nbyte_markvalid(const void *addr, size_t size) 21538da497aSMark Johnston { 21638da497aSMark Johnston size_t i; 21738da497aSMark Johnston 21838da497aSMark Johnston for (i = 0; i < size; i++) { 21938da497aSMark Johnston kasan_shadow_1byte_markvalid((unsigned long)addr + i); 22038da497aSMark Johnston } 22138da497aSMark Johnston } 22238da497aSMark Johnston 22338da497aSMark Johnston static __always_inline void 22438da497aSMark Johnston kasan_shadow_Nbyte_fill(const void *addr, size_t size, uint8_t code) 22538da497aSMark Johnston { 22638da497aSMark Johnston void *shad; 22738da497aSMark Johnston 22838da497aSMark Johnston if (__predict_false(size == 0)) 22938da497aSMark Johnston return; 23038da497aSMark Johnston if (__predict_false(kasan_md_unsupported((vm_offset_t)addr))) 23138da497aSMark Johnston return; 23238da497aSMark Johnston 23338da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0, 23438da497aSMark Johnston ("%s: invalid address %p", __func__, addr)); 23538da497aSMark Johnston KASSERT(size % KASAN_SHADOW_SCALE == 0, 23638da497aSMark Johnston ("%s: invalid size %zu", __func__, size)); 23738da497aSMark Johnston 23838da497aSMark Johnston shad = (void *)kasan_md_addr_to_shad((uintptr_t)addr); 23938da497aSMark Johnston size = size >> KASAN_SHADOW_SCALE_SHIFT; 24038da497aSMark Johnston 24138da497aSMark Johnston __builtin_memset(shad, code, size); 24238da497aSMark Johnston } 24338da497aSMark Johnston 24438da497aSMark Johnston /* 24538da497aSMark Johnston * In an area of size 'sz_with_redz', mark the 'size' first bytes as valid, 24638da497aSMark Johnston * and the rest as invalid. There are generally two use cases: 24738da497aSMark Johnston * 24838da497aSMark Johnston * o kasan_mark(addr, origsize, size, code), with origsize < size. This marks 24938da497aSMark Johnston * the redzone at the end of the buffer as invalid. If the entire is to be 25038da497aSMark Johnston * marked invalid, origsize will be 0. 25138da497aSMark Johnston * 25238da497aSMark Johnston * o kasan_mark(addr, size, size, 0). This marks the entire buffer as valid. 25338da497aSMark Johnston */ 25438da497aSMark Johnston void 25538da497aSMark Johnston kasan_mark(const void *addr, size_t size, size_t redzsize, uint8_t code) 25638da497aSMark Johnston { 25738da497aSMark Johnston size_t i, n, redz; 25838da497aSMark Johnston int8_t *shad; 25938da497aSMark Johnston 26038da497aSMark Johnston if ((vm_offset_t)addr >= DMAP_MIN_ADDRESS && 26138da497aSMark Johnston (vm_offset_t)addr < DMAP_MAX_ADDRESS) 26238da497aSMark Johnston return; 26338da497aSMark Johnston 26438da497aSMark Johnston KASSERT((vm_offset_t)addr >= VM_MIN_KERNEL_ADDRESS && 26538da497aSMark Johnston (vm_offset_t)addr < VM_MAX_KERNEL_ADDRESS, 26638da497aSMark Johnston ("%s: invalid address %p", __func__, addr)); 26738da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0, 26838da497aSMark Johnston ("%s: invalid address %p", __func__, addr)); 26938da497aSMark Johnston redz = redzsize - roundup(size, KASAN_SHADOW_SCALE); 27038da497aSMark Johnston KASSERT(redz % KASAN_SHADOW_SCALE == 0, 27138da497aSMark Johnston ("%s: invalid size %zu", __func__, redz)); 27238da497aSMark Johnston shad = (int8_t *)kasan_md_addr_to_shad((uintptr_t)addr); 27338da497aSMark Johnston 27438da497aSMark Johnston /* Chunks of 8 bytes, valid. */ 27538da497aSMark Johnston n = size / KASAN_SHADOW_SCALE; 27638da497aSMark Johnston for (i = 0; i < n; i++) { 27738da497aSMark Johnston *shad++ = 0; 27838da497aSMark Johnston } 27938da497aSMark Johnston 28038da497aSMark Johnston /* Possibly one chunk, mid. */ 28138da497aSMark Johnston if ((size & KASAN_SHADOW_MASK) != 0) { 28238da497aSMark Johnston *shad++ = (size & KASAN_SHADOW_MASK); 28338da497aSMark Johnston } 28438da497aSMark Johnston 28538da497aSMark Johnston /* Chunks of 8 bytes, invalid. */ 28638da497aSMark Johnston n = redz / KASAN_SHADOW_SCALE; 28738da497aSMark Johnston for (i = 0; i < n; i++) { 28838da497aSMark Johnston *shad++ = code; 28938da497aSMark Johnston } 29038da497aSMark Johnston } 29138da497aSMark Johnston 29238da497aSMark Johnston /* -------------------------------------------------------------------------- */ 29338da497aSMark Johnston 29438da497aSMark Johnston #define ADDR_CROSSES_SCALE_BOUNDARY(addr, size) \ 29538da497aSMark Johnston (addr >> KASAN_SHADOW_SCALE_SHIFT) != \ 29638da497aSMark Johnston ((addr + size - 1) >> KASAN_SHADOW_SCALE_SHIFT) 29738da497aSMark Johnston 29838da497aSMark Johnston static __always_inline bool 29938da497aSMark Johnston kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code) 30038da497aSMark Johnston { 30138da497aSMark Johnston int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr); 30238da497aSMark Johnston int8_t last = (addr & KASAN_SHADOW_MASK) + 1; 30338da497aSMark Johnston 30438da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) { 30538da497aSMark Johnston return (true); 30638da497aSMark Johnston } 30738da497aSMark Johnston *code = *byte; 30838da497aSMark Johnston return (false); 30938da497aSMark Johnston } 31038da497aSMark Johnston 31138da497aSMark Johnston static __always_inline bool 31238da497aSMark Johnston kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code) 31338da497aSMark Johnston { 31438da497aSMark Johnston int8_t *byte, last; 31538da497aSMark Johnston 31638da497aSMark Johnston if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 2)) { 31738da497aSMark Johnston return (kasan_shadow_1byte_isvalid(addr, code) && 31838da497aSMark Johnston kasan_shadow_1byte_isvalid(addr+1, code)); 31938da497aSMark Johnston } 32038da497aSMark Johnston 32138da497aSMark Johnston byte = (int8_t *)kasan_md_addr_to_shad(addr); 32238da497aSMark Johnston last = ((addr + 1) & KASAN_SHADOW_MASK) + 1; 32338da497aSMark Johnston 32438da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) { 32538da497aSMark Johnston return (true); 32638da497aSMark Johnston } 32738da497aSMark Johnston *code = *byte; 32838da497aSMark Johnston return (false); 32938da497aSMark Johnston } 33038da497aSMark Johnston 33138da497aSMark Johnston static __always_inline bool 33238da497aSMark Johnston kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code) 33338da497aSMark Johnston { 33438da497aSMark Johnston int8_t *byte, last; 33538da497aSMark Johnston 33638da497aSMark Johnston if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 4)) { 33738da497aSMark Johnston return (kasan_shadow_2byte_isvalid(addr, code) && 33838da497aSMark Johnston kasan_shadow_2byte_isvalid(addr+2, code)); 33938da497aSMark Johnston } 34038da497aSMark Johnston 34138da497aSMark Johnston byte = (int8_t *)kasan_md_addr_to_shad(addr); 34238da497aSMark Johnston last = ((addr + 3) & KASAN_SHADOW_MASK) + 1; 34338da497aSMark Johnston 34438da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) { 34538da497aSMark Johnston return (true); 34638da497aSMark Johnston } 34738da497aSMark Johnston *code = *byte; 34838da497aSMark Johnston return (false); 34938da497aSMark Johnston } 35038da497aSMark Johnston 35138da497aSMark Johnston static __always_inline bool 35238da497aSMark Johnston kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code) 35338da497aSMark Johnston { 35438da497aSMark Johnston int8_t *byte, last; 35538da497aSMark Johnston 35638da497aSMark Johnston if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 8)) { 35738da497aSMark Johnston return (kasan_shadow_4byte_isvalid(addr, code) && 35838da497aSMark Johnston kasan_shadow_4byte_isvalid(addr+4, code)); 35938da497aSMark Johnston } 36038da497aSMark Johnston 36138da497aSMark Johnston byte = (int8_t *)kasan_md_addr_to_shad(addr); 36238da497aSMark Johnston last = ((addr + 7) & KASAN_SHADOW_MASK) + 1; 36338da497aSMark Johnston 36438da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) { 36538da497aSMark Johnston return (true); 36638da497aSMark Johnston } 36738da497aSMark Johnston *code = *byte; 36838da497aSMark Johnston return (false); 36938da497aSMark Johnston } 37038da497aSMark Johnston 37138da497aSMark Johnston static __always_inline bool 37238da497aSMark Johnston kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code) 37338da497aSMark Johnston { 37438da497aSMark Johnston size_t i; 37538da497aSMark Johnston 37638da497aSMark Johnston for (i = 0; i < size; i++) { 37738da497aSMark Johnston if (!kasan_shadow_1byte_isvalid(addr+i, code)) 37838da497aSMark Johnston return (false); 37938da497aSMark Johnston } 38038da497aSMark Johnston 38138da497aSMark Johnston return (true); 38238da497aSMark Johnston } 38338da497aSMark Johnston 38438da497aSMark Johnston static __always_inline void 38538da497aSMark Johnston kasan_shadow_check(unsigned long addr, size_t size, bool write, 38638da497aSMark Johnston unsigned long retaddr) 38738da497aSMark Johnston { 38838da497aSMark Johnston uint8_t code; 38938da497aSMark Johnston bool valid; 39038da497aSMark Johnston 39138da497aSMark Johnston if (__predict_false(!kasan_enabled)) 39238da497aSMark Johnston return; 39338da497aSMark Johnston if (__predict_false(size == 0)) 39438da497aSMark Johnston return; 39538da497aSMark Johnston if (__predict_false(kasan_md_unsupported(addr))) 39638da497aSMark Johnston return; 39735eb9b10SMitchell Horne if (KERNEL_PANICKED()) 39838da497aSMark Johnston return; 39938da497aSMark Johnston 40038da497aSMark Johnston if (__builtin_constant_p(size)) { 40138da497aSMark Johnston switch (size) { 40238da497aSMark Johnston case 1: 40338da497aSMark Johnston valid = kasan_shadow_1byte_isvalid(addr, &code); 40438da497aSMark Johnston break; 40538da497aSMark Johnston case 2: 40638da497aSMark Johnston valid = kasan_shadow_2byte_isvalid(addr, &code); 40738da497aSMark Johnston break; 40838da497aSMark Johnston case 4: 40938da497aSMark Johnston valid = kasan_shadow_4byte_isvalid(addr, &code); 41038da497aSMark Johnston break; 41138da497aSMark Johnston case 8: 41238da497aSMark Johnston valid = kasan_shadow_8byte_isvalid(addr, &code); 41338da497aSMark Johnston break; 41438da497aSMark Johnston default: 41538da497aSMark Johnston valid = kasan_shadow_Nbyte_isvalid(addr, size, &code); 41638da497aSMark Johnston break; 41738da497aSMark Johnston } 41838da497aSMark Johnston } else { 41938da497aSMark Johnston valid = kasan_shadow_Nbyte_isvalid(addr, size, &code); 42038da497aSMark Johnston } 42138da497aSMark Johnston 42238da497aSMark Johnston if (__predict_false(!valid)) { 42338da497aSMark Johnston kasan_report(addr, size, write, retaddr, code); 42438da497aSMark Johnston } 42538da497aSMark Johnston } 42638da497aSMark Johnston 42738da497aSMark Johnston /* -------------------------------------------------------------------------- */ 42838da497aSMark Johnston 42938da497aSMark Johnston void * 43038da497aSMark Johnston kasan_memcpy(void *dst, const void *src, size_t len) 43138da497aSMark Johnston { 43238da497aSMark Johnston kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); 43338da497aSMark Johnston kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); 43438da497aSMark Johnston return (__builtin_memcpy(dst, src, len)); 43538da497aSMark Johnston } 43638da497aSMark Johnston 43738da497aSMark Johnston int 43838da497aSMark Johnston kasan_memcmp(const void *b1, const void *b2, size_t len) 43938da497aSMark Johnston { 44038da497aSMark Johnston kasan_shadow_check((unsigned long)b1, len, false, __RET_ADDR); 44138da497aSMark Johnston kasan_shadow_check((unsigned long)b2, len, false, __RET_ADDR); 44238da497aSMark Johnston return (__builtin_memcmp(b1, b2, len)); 44338da497aSMark Johnston } 44438da497aSMark Johnston 44538da497aSMark Johnston void * 44638da497aSMark Johnston kasan_memset(void *b, int c, size_t len) 44738da497aSMark Johnston { 44838da497aSMark Johnston kasan_shadow_check((unsigned long)b, len, true, __RET_ADDR); 44938da497aSMark Johnston return (__builtin_memset(b, c, len)); 45038da497aSMark Johnston } 45138da497aSMark Johnston 45238da497aSMark Johnston void * 45338da497aSMark Johnston kasan_memmove(void *dst, const void *src, size_t len) 45438da497aSMark Johnston { 45538da497aSMark Johnston kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); 45638da497aSMark Johnston kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); 45738da497aSMark Johnston return (__builtin_memmove(dst, src, len)); 45838da497aSMark Johnston } 45938da497aSMark Johnston 46038da497aSMark Johnston size_t 46138da497aSMark Johnston kasan_strlen(const char *str) 46238da497aSMark Johnston { 46338da497aSMark Johnston const char *s; 46438da497aSMark Johnston 46538da497aSMark Johnston s = str; 46638da497aSMark Johnston while (1) { 46738da497aSMark Johnston kasan_shadow_check((unsigned long)s, 1, false, __RET_ADDR); 46838da497aSMark Johnston if (*s == '\0') 46938da497aSMark Johnston break; 47038da497aSMark Johnston s++; 47138da497aSMark Johnston } 47238da497aSMark Johnston 47338da497aSMark Johnston return (s - str); 47438da497aSMark Johnston } 47538da497aSMark Johnston 47638da497aSMark Johnston char * 47738da497aSMark Johnston kasan_strcpy(char *dst, const char *src) 47838da497aSMark Johnston { 47938da497aSMark Johnston char *save = dst; 48038da497aSMark Johnston 48138da497aSMark Johnston while (1) { 48238da497aSMark Johnston kasan_shadow_check((unsigned long)src, 1, false, __RET_ADDR); 48338da497aSMark Johnston kasan_shadow_check((unsigned long)dst, 1, true, __RET_ADDR); 48438da497aSMark Johnston *dst = *src; 48538da497aSMark Johnston if (*src == '\0') 48638da497aSMark Johnston break; 48738da497aSMark Johnston src++, dst++; 48838da497aSMark Johnston } 48938da497aSMark Johnston 49038da497aSMark Johnston return save; 49138da497aSMark Johnston } 49238da497aSMark Johnston 49338da497aSMark Johnston int 49438da497aSMark Johnston kasan_strcmp(const char *s1, const char *s2) 49538da497aSMark Johnston { 49638da497aSMark Johnston while (1) { 49738da497aSMark Johnston kasan_shadow_check((unsigned long)s1, 1, false, __RET_ADDR); 49838da497aSMark Johnston kasan_shadow_check((unsigned long)s2, 1, false, __RET_ADDR); 49938da497aSMark Johnston if (*s1 != *s2) 50038da497aSMark Johnston break; 50138da497aSMark Johnston if (*s1 == '\0') 50238da497aSMark Johnston return 0; 50338da497aSMark Johnston s1++, s2++; 50438da497aSMark Johnston } 50538da497aSMark Johnston 50638da497aSMark Johnston return (*(const unsigned char *)s1 - *(const unsigned char *)s2); 50738da497aSMark Johnston } 50838da497aSMark Johnston 50938da497aSMark Johnston int 51038da497aSMark Johnston kasan_copyin(const void *uaddr, void *kaddr, size_t len) 51138da497aSMark Johnston { 51238da497aSMark Johnston kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR); 51338da497aSMark Johnston return (copyin(uaddr, kaddr, len)); 51438da497aSMark Johnston } 51538da497aSMark Johnston 51638da497aSMark Johnston int 51738da497aSMark Johnston kasan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) 51838da497aSMark Johnston { 51938da497aSMark Johnston kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR); 52038da497aSMark Johnston return (copyinstr(uaddr, kaddr, len, done)); 52138da497aSMark Johnston } 52238da497aSMark Johnston 52338da497aSMark Johnston int 52438da497aSMark Johnston kasan_copyout(const void *kaddr, void *uaddr, size_t len) 52538da497aSMark Johnston { 52638da497aSMark Johnston kasan_shadow_check((unsigned long)kaddr, len, false, __RET_ADDR); 52738da497aSMark Johnston return (copyout(kaddr, uaddr, len)); 52838da497aSMark Johnston } 52938da497aSMark Johnston 53038da497aSMark Johnston /* -------------------------------------------------------------------------- */ 53138da497aSMark Johnston 5326f179693SMark Johnston int 5336f179693SMark Johnston kasan_fubyte(volatile const void *base) 5346f179693SMark Johnston { 5356f179693SMark Johnston return (fubyte(base)); 5366f179693SMark Johnston } 5376f179693SMark Johnston 5386f179693SMark Johnston int 5396f179693SMark Johnston kasan_fuword16(volatile const void *base) 5406f179693SMark Johnston { 5416f179693SMark Johnston return (fuword16(base)); 5426f179693SMark Johnston } 5436f179693SMark Johnston 5446f179693SMark Johnston int 5456f179693SMark Johnston kasan_fueword(volatile const void *base, long *val) 5466f179693SMark Johnston { 5476f179693SMark Johnston kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR); 5486f179693SMark Johnston return (fueword(base, val)); 5496f179693SMark Johnston } 5506f179693SMark Johnston 5516f179693SMark Johnston int 5526f179693SMark Johnston kasan_fueword32(volatile const void *base, int32_t *val) 5536f179693SMark Johnston { 5546f179693SMark Johnston kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR); 5556f179693SMark Johnston return (fueword32(base, val)); 5566f179693SMark Johnston } 5576f179693SMark Johnston 5586f179693SMark Johnston int 5596f179693SMark Johnston kasan_fueword64(volatile const void *base, int64_t *val) 5606f179693SMark Johnston { 5616f179693SMark Johnston kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR); 5626f179693SMark Johnston return (fueword64(base, val)); 5636f179693SMark Johnston } 5646f179693SMark Johnston 5656f179693SMark Johnston int 5666f179693SMark Johnston kasan_subyte(volatile void *base, int byte) 5676f179693SMark Johnston { 5686f179693SMark Johnston return (subyte(base, byte)); 5696f179693SMark Johnston } 5706f179693SMark Johnston 5716f179693SMark Johnston int 5726f179693SMark Johnston kasan_suword(volatile void *base, long word) 5736f179693SMark Johnston { 5746f179693SMark Johnston return (suword(base, word)); 5756f179693SMark Johnston } 5766f179693SMark Johnston 5776f179693SMark Johnston int 5786f179693SMark Johnston kasan_suword16(volatile void *base, int word) 5796f179693SMark Johnston { 5806f179693SMark Johnston return (suword16(base, word)); 5816f179693SMark Johnston } 5826f179693SMark Johnston 5836f179693SMark Johnston int 5846f179693SMark Johnston kasan_suword32(volatile void *base, int32_t word) 5856f179693SMark Johnston { 5866f179693SMark Johnston return (suword32(base, word)); 5876f179693SMark Johnston } 5886f179693SMark Johnston 5896f179693SMark Johnston int 5906f179693SMark Johnston kasan_suword64(volatile void *base, int64_t word) 5916f179693SMark Johnston { 5926f179693SMark Johnston return (suword64(base, word)); 5936f179693SMark Johnston } 5946f179693SMark Johnston 5956f179693SMark Johnston int 5966f179693SMark Johnston kasan_casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp, 5976f179693SMark Johnston uint32_t newval) 5986f179693SMark Johnston { 5996f179693SMark Johnston kasan_shadow_check((unsigned long)oldvalp, sizeof(*oldvalp), true, 6006f179693SMark Johnston __RET_ADDR); 6016f179693SMark Johnston return (casueword32(base, oldval, oldvalp, newval)); 6026f179693SMark Johnston } 6036f179693SMark Johnston 6046f179693SMark Johnston int 6056f179693SMark Johnston kasan_casueword(volatile u_long *base, u_long oldval, u_long *oldvalp, 6066f179693SMark Johnston u_long newval) 6076f179693SMark Johnston { 6086f179693SMark Johnston kasan_shadow_check((unsigned long)oldvalp, sizeof(*oldvalp), true, 6096f179693SMark Johnston __RET_ADDR); 6106f179693SMark Johnston return (casueword(base, oldval, oldvalp, newval)); 6116f179693SMark Johnston } 6126f179693SMark Johnston 6136f179693SMark Johnston /* -------------------------------------------------------------------------- */ 6146f179693SMark Johnston 61538da497aSMark Johnston #include <machine/atomic.h> 61638da497aSMark Johnston #include <sys/atomic_san.h> 61738da497aSMark Johnston 61838da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_ADD(name, type) \ 61938da497aSMark Johnston void kasan_atomic_add_##name(volatile type *ptr, type val) \ 62038da497aSMark Johnston { \ 62138da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 62238da497aSMark Johnston __RET_ADDR); \ 62338da497aSMark Johnston atomic_add_##name(ptr, val); \ 62438da497aSMark Johnston } 62538da497aSMark Johnston 62638da497aSMark Johnston #define ASAN_ATOMIC_FUNC_ADD(name, type) \ 62738da497aSMark Johnston _ASAN_ATOMIC_FUNC_ADD(name, type) \ 62838da497aSMark Johnston _ASAN_ATOMIC_FUNC_ADD(acq_##name, type) \ 62938da497aSMark Johnston _ASAN_ATOMIC_FUNC_ADD(rel_##name, type) 63038da497aSMark Johnston 63138da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \ 63238da497aSMark Johnston void kasan_atomic_subtract_##name(volatile type *ptr, type val) \ 63338da497aSMark Johnston { \ 63438da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 63538da497aSMark Johnston __RET_ADDR); \ 63638da497aSMark Johnston atomic_subtract_##name(ptr, val); \ 63738da497aSMark Johnston } 63838da497aSMark Johnston 63938da497aSMark Johnston #define ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \ 64038da497aSMark Johnston _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \ 64138da497aSMark Johnston _ASAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type) \ 64238da497aSMark Johnston _ASAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type) 64338da497aSMark Johnston 64438da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_SET(name, type) \ 64538da497aSMark Johnston void kasan_atomic_set_##name(volatile type *ptr, type val) \ 64638da497aSMark Johnston { \ 64738da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 64838da497aSMark Johnston __RET_ADDR); \ 64938da497aSMark Johnston atomic_set_##name(ptr, val); \ 65038da497aSMark Johnston } 65138da497aSMark Johnston 65238da497aSMark Johnston #define ASAN_ATOMIC_FUNC_SET(name, type) \ 65338da497aSMark Johnston _ASAN_ATOMIC_FUNC_SET(name, type) \ 65438da497aSMark Johnston _ASAN_ATOMIC_FUNC_SET(acq_##name, type) \ 65538da497aSMark Johnston _ASAN_ATOMIC_FUNC_SET(rel_##name, type) 65638da497aSMark Johnston 65738da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_CLEAR(name, type) \ 65838da497aSMark Johnston void kasan_atomic_clear_##name(volatile type *ptr, type val) \ 65938da497aSMark Johnston { \ 66038da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 66138da497aSMark Johnston __RET_ADDR); \ 66238da497aSMark Johnston atomic_clear_##name(ptr, val); \ 66338da497aSMark Johnston } 66438da497aSMark Johnston 66538da497aSMark Johnston #define ASAN_ATOMIC_FUNC_CLEAR(name, type) \ 66638da497aSMark Johnston _ASAN_ATOMIC_FUNC_CLEAR(name, type) \ 66738da497aSMark Johnston _ASAN_ATOMIC_FUNC_CLEAR(acq_##name, type) \ 66838da497aSMark Johnston _ASAN_ATOMIC_FUNC_CLEAR(rel_##name, type) 66938da497aSMark Johnston 67038da497aSMark Johnston #define ASAN_ATOMIC_FUNC_FETCHADD(name, type) \ 67138da497aSMark Johnston type kasan_atomic_fetchadd_##name(volatile type *ptr, type val) \ 67238da497aSMark Johnston { \ 67338da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 67438da497aSMark Johnston __RET_ADDR); \ 67538da497aSMark Johnston return (atomic_fetchadd_##name(ptr, val)); \ 67638da497aSMark Johnston } 67738da497aSMark Johnston 67838da497aSMark Johnston #define ASAN_ATOMIC_FUNC_READANDCLEAR(name, type) \ 67938da497aSMark Johnston type kasan_atomic_readandclear_##name(volatile type *ptr) \ 68038da497aSMark Johnston { \ 68138da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 68238da497aSMark Johnston __RET_ADDR); \ 68338da497aSMark Johnston return (atomic_readandclear_##name(ptr)); \ 68438da497aSMark Johnston } 68538da497aSMark Johnston 68638da497aSMark Johnston #define ASAN_ATOMIC_FUNC_TESTANDCLEAR(name, type) \ 68738da497aSMark Johnston int kasan_atomic_testandclear_##name(volatile type *ptr, u_int v) \ 68838da497aSMark Johnston { \ 68938da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 69038da497aSMark Johnston __RET_ADDR); \ 69138da497aSMark Johnston return (atomic_testandclear_##name(ptr, v)); \ 69238da497aSMark Johnston } 69338da497aSMark Johnston 69438da497aSMark Johnston #define ASAN_ATOMIC_FUNC_TESTANDSET(name, type) \ 69538da497aSMark Johnston int kasan_atomic_testandset_##name(volatile type *ptr, u_int v) \ 69638da497aSMark Johnston { \ 69738da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 69838da497aSMark Johnston __RET_ADDR); \ 69938da497aSMark Johnston return (atomic_testandset_##name(ptr, v)); \ 70038da497aSMark Johnston } 70138da497aSMark Johnston 70238da497aSMark Johnston #define ASAN_ATOMIC_FUNC_SWAP(name, type) \ 70338da497aSMark Johnston type kasan_atomic_swap_##name(volatile type *ptr, type val) \ 70438da497aSMark Johnston { \ 70538da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 70638da497aSMark Johnston __RET_ADDR); \ 70738da497aSMark Johnston return (atomic_swap_##name(ptr, val)); \ 70838da497aSMark Johnston } 70938da497aSMark Johnston 71038da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_CMPSET(name, type) \ 71138da497aSMark Johnston int kasan_atomic_cmpset_##name(volatile type *ptr, type oval, \ 71238da497aSMark Johnston type nval) \ 71338da497aSMark Johnston { \ 71438da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 71538da497aSMark Johnston __RET_ADDR); \ 71638da497aSMark Johnston return (atomic_cmpset_##name(ptr, oval, nval)); \ 71738da497aSMark Johnston } 71838da497aSMark Johnston 71938da497aSMark Johnston #define ASAN_ATOMIC_FUNC_CMPSET(name, type) \ 72038da497aSMark Johnston _ASAN_ATOMIC_FUNC_CMPSET(name, type) \ 72138da497aSMark Johnston _ASAN_ATOMIC_FUNC_CMPSET(acq_##name, type) \ 72238da497aSMark Johnston _ASAN_ATOMIC_FUNC_CMPSET(rel_##name, type) 72338da497aSMark Johnston 72438da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \ 72538da497aSMark Johnston int kasan_atomic_fcmpset_##name(volatile type *ptr, type *oval, \ 72638da497aSMark Johnston type nval) \ 72738da497aSMark Johnston { \ 72838da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 72938da497aSMark Johnston __RET_ADDR); \ 73038da497aSMark Johnston return (atomic_fcmpset_##name(ptr, oval, nval)); \ 73138da497aSMark Johnston } 73238da497aSMark Johnston 73338da497aSMark Johnston #define ASAN_ATOMIC_FUNC_FCMPSET(name, type) \ 73438da497aSMark Johnston _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \ 73538da497aSMark Johnston _ASAN_ATOMIC_FUNC_FCMPSET(acq_##name, type) \ 73638da497aSMark Johnston _ASAN_ATOMIC_FUNC_FCMPSET(rel_##name, type) 73738da497aSMark Johnston 73838da497aSMark Johnston #define ASAN_ATOMIC_FUNC_THREAD_FENCE(name) \ 73938da497aSMark Johnston void kasan_atomic_thread_fence_##name(void) \ 74038da497aSMark Johnston { \ 74138da497aSMark Johnston atomic_thread_fence_##name(); \ 74238da497aSMark Johnston } 74338da497aSMark Johnston 74438da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_LOAD(name, type) \ 74538da497aSMark Johnston type kasan_atomic_load_##name(volatile type *ptr) \ 74638da497aSMark Johnston { \ 74738da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 74838da497aSMark Johnston __RET_ADDR); \ 74938da497aSMark Johnston return (atomic_load_##name(ptr)); \ 75038da497aSMark Johnston } 75138da497aSMark Johnston 75238da497aSMark Johnston #define ASAN_ATOMIC_FUNC_LOAD(name, type) \ 75338da497aSMark Johnston _ASAN_ATOMIC_FUNC_LOAD(name, type) \ 75438da497aSMark Johnston _ASAN_ATOMIC_FUNC_LOAD(acq_##name, type) 75538da497aSMark Johnston 75638da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_STORE(name, type) \ 75738da497aSMark Johnston void kasan_atomic_store_##name(volatile type *ptr, type val) \ 75838da497aSMark Johnston { \ 75938da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 76038da497aSMark Johnston __RET_ADDR); \ 76138da497aSMark Johnston atomic_store_##name(ptr, val); \ 76238da497aSMark Johnston } 76338da497aSMark Johnston 76438da497aSMark Johnston #define ASAN_ATOMIC_FUNC_STORE(name, type) \ 76538da497aSMark Johnston _ASAN_ATOMIC_FUNC_STORE(name, type) \ 76638da497aSMark Johnston _ASAN_ATOMIC_FUNC_STORE(rel_##name, type) 76738da497aSMark Johnston 76838da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(8, uint8_t); 76938da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(16, uint16_t); 77038da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(32, uint32_t); 77138da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(64, uint64_t); 77238da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(int, u_int); 77338da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(long, u_long); 77438da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(ptr, uintptr_t); 77538da497aSMark Johnston 77638da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t); 77738da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t); 77838da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t); 77938da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t); 78038da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(int, u_int); 78138da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(long, u_long); 78238da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t); 78338da497aSMark Johnston 78438da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(8, uint8_t); 78538da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(16, uint16_t); 78638da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(32, uint32_t); 78738da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(64, uint64_t); 78838da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(int, u_int); 78938da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(long, u_long); 79038da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(ptr, uintptr_t); 79138da497aSMark Johnston 79238da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(8, uint8_t); 79338da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(16, uint16_t); 79438da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(32, uint32_t); 79538da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(64, uint64_t); 79638da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(int, u_int); 79738da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(long, u_long); 79838da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t); 79938da497aSMark Johnston 80038da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(32, uint32_t); 80138da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(64, uint64_t); 80238da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(int, u_int); 80338da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(long, u_long); 80438da497aSMark Johnston 80538da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t); 80638da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t); 80738da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(int, u_int); 80838da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(long, u_long); 80938da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t); 81038da497aSMark Johnston 81138da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t); 81238da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t); 81338da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int); 81438da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long); 81538da497aSMark Johnston 81638da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t); 81738da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t); 81838da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(int, u_int); 81938da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(long, u_long); 82038da497aSMark Johnston 82138da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(32, uint32_t); 82238da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(64, uint64_t); 82338da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(int, u_int); 82438da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(long, u_long); 82538da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t); 82638da497aSMark Johnston 82738da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(8, uint8_t); 82838da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(16, uint16_t); 82938da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(32, uint32_t); 83038da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(64, uint64_t); 83138da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(int, u_int); 83238da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(long, u_long); 83338da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t); 83438da497aSMark Johnston 83538da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(8, uint8_t); 83638da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(16, uint16_t); 83738da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(32, uint32_t); 83838da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(64, uint64_t); 83938da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(int, u_int); 84038da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(long, u_long); 84138da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t); 84238da497aSMark Johnston 84338da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(8, uint8_t); 84438da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(16, uint16_t); 84538da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(32, uint32_t); 84638da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(64, uint64_t); 84738da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(char, u_char); 84838da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(short, u_short); 84938da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(int, u_int); 85038da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(long, u_long); 85138da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t); 85238da497aSMark Johnston 85338da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(8, uint8_t); 85438da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(16, uint16_t); 85538da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(32, uint32_t); 85638da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(64, uint64_t); 85738da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(char, u_char); 85838da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(short, u_short); 85938da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(int, u_int); 86038da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(long, u_long); 86138da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(ptr, uintptr_t); 86238da497aSMark Johnston 86338da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(acq); 86438da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(rel); 86538da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel); 86638da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst); 86738da497aSMark Johnston 86838da497aSMark Johnston void 86938da497aSMark Johnston kasan_atomic_interrupt_fence(void) 87038da497aSMark Johnston { 87138da497aSMark Johnston } 87238da497aSMark Johnston 87338da497aSMark Johnston /* -------------------------------------------------------------------------- */ 87438da497aSMark Johnston 87538da497aSMark Johnston #include <sys/bus.h> 87638da497aSMark Johnston #include <machine/bus.h> 87738da497aSMark Johnston #include <sys/bus_san.h> 87838da497aSMark Johnston 87938da497aSMark Johnston int 88038da497aSMark Johnston kasan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size, 88138da497aSMark Johnston int flags, bus_space_handle_t *handlep) 88238da497aSMark Johnston { 88338da497aSMark Johnston return (bus_space_map(tag, hnd, size, flags, handlep)); 88438da497aSMark Johnston } 88538da497aSMark Johnston 88638da497aSMark Johnston void 88738da497aSMark Johnston kasan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd, 88838da497aSMark Johnston bus_size_t size) 88938da497aSMark Johnston { 89038da497aSMark Johnston bus_space_unmap(tag, hnd, size); 89138da497aSMark Johnston } 89238da497aSMark Johnston 89338da497aSMark Johnston int 89438da497aSMark Johnston kasan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd, 89538da497aSMark Johnston bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep) 89638da497aSMark Johnston { 89738da497aSMark Johnston return (bus_space_subregion(tag, hnd, offset, size, handlep)); 89838da497aSMark Johnston } 89938da497aSMark Johnston 90038da497aSMark Johnston void 90138da497aSMark Johnston kasan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd, 90238da497aSMark Johnston bus_size_t size) 90338da497aSMark Johnston { 90438da497aSMark Johnston bus_space_free(tag, hnd, size); 90538da497aSMark Johnston } 90638da497aSMark Johnston 90738da497aSMark Johnston void 90838da497aSMark Johnston kasan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd, 90938da497aSMark Johnston bus_size_t offset, bus_size_t size, int flags) 91038da497aSMark Johnston { 91138da497aSMark Johnston bus_space_barrier(tag, hnd, offset, size, flags); 91238da497aSMark Johnston } 91338da497aSMark Johnston 91438da497aSMark Johnston #define ASAN_BUS_READ_FUNC(func, width, type) \ 91538da497aSMark Johnston type kasan_bus_space_read##func##_##width(bus_space_tag_t tag, \ 91638da497aSMark Johnston bus_space_handle_t hnd, bus_size_t offset) \ 91738da497aSMark Johnston { \ 91838da497aSMark Johnston return (bus_space_read##func##_##width(tag, hnd, \ 91938da497aSMark Johnston offset)); \ 92038da497aSMark Johnston } \ 92138da497aSMark Johnston 92238da497aSMark Johnston #define ASAN_BUS_READ_PTR_FUNC(func, width, type) \ 92338da497aSMark Johnston void kasan_bus_space_read_##func##_##width(bus_space_tag_t tag, \ 92438da497aSMark Johnston bus_space_handle_t hnd, bus_size_t size, type *buf, \ 92538da497aSMark Johnston bus_size_t count) \ 92638da497aSMark Johnston { \ 92738da497aSMark Johnston kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\ 92838da497aSMark Johnston false, __RET_ADDR); \ 92938da497aSMark Johnston bus_space_read_##func##_##width(tag, hnd, size, buf, \ 93038da497aSMark Johnston count); \ 93138da497aSMark Johnston } 93238da497aSMark Johnston 93338da497aSMark Johnston ASAN_BUS_READ_FUNC(, 1, uint8_t) 93438da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 1, uint8_t) 93538da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t) 93638da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t) 93738da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 1, uint8_t) 93838da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t) 93938da497aSMark Johnston 94038da497aSMark Johnston ASAN_BUS_READ_FUNC(, 2, uint16_t) 94138da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 2, uint16_t) 94238da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t) 94338da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t) 94438da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 2, uint16_t) 94538da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t) 94638da497aSMark Johnston 94738da497aSMark Johnston ASAN_BUS_READ_FUNC(, 4, uint32_t) 94838da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 4, uint32_t) 94938da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t) 95038da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t) 95138da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 4, uint32_t) 95238da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t) 95338da497aSMark Johnston 95438da497aSMark Johnston ASAN_BUS_READ_FUNC(, 8, uint64_t) 95538da497aSMark Johnston 95638da497aSMark Johnston #define ASAN_BUS_WRITE_FUNC(func, width, type) \ 95738da497aSMark Johnston void kasan_bus_space_write##func##_##width(bus_space_tag_t tag, \ 95838da497aSMark Johnston bus_space_handle_t hnd, bus_size_t offset, type value) \ 95938da497aSMark Johnston { \ 96038da497aSMark Johnston bus_space_write##func##_##width(tag, hnd, offset, value);\ 96138da497aSMark Johnston } \ 96238da497aSMark Johnston 96338da497aSMark Johnston #define ASAN_BUS_WRITE_PTR_FUNC(func, width, type) \ 96438da497aSMark Johnston void kasan_bus_space_write_##func##_##width(bus_space_tag_t tag,\ 96538da497aSMark Johnston bus_space_handle_t hnd, bus_size_t size, const type *buf, \ 96638da497aSMark Johnston bus_size_t count) \ 96738da497aSMark Johnston { \ 96838da497aSMark Johnston kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\ 96938da497aSMark Johnston true, __RET_ADDR); \ 97038da497aSMark Johnston bus_space_write_##func##_##width(tag, hnd, size, buf, \ 97138da497aSMark Johnston count); \ 97238da497aSMark Johnston } 97338da497aSMark Johnston 97438da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 1, uint8_t) 97538da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 1, uint8_t) 97638da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t) 97738da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t) 97838da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t) 97938da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t) 98038da497aSMark Johnston 98138da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 2, uint16_t) 98238da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 2, uint16_t) 98338da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t) 98438da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t) 98538da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t) 98638da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t) 98738da497aSMark Johnston 98838da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 4, uint32_t) 98938da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 4, uint32_t) 99038da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t) 99138da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t) 99238da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t) 99338da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t) 99438da497aSMark Johnston 99538da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 8, uint64_t) 99638da497aSMark Johnston 99738da497aSMark Johnston #define ASAN_BUS_SET_FUNC(func, width, type) \ 99838da497aSMark Johnston void kasan_bus_space_set_##func##_##width(bus_space_tag_t tag, \ 99938da497aSMark Johnston bus_space_handle_t hnd, bus_size_t offset, type value, \ 100038da497aSMark Johnston bus_size_t count) \ 100138da497aSMark Johnston { \ 100238da497aSMark Johnston bus_space_set_##func##_##width(tag, hnd, offset, value, \ 100338da497aSMark Johnston count); \ 100438da497aSMark Johnston } 100538da497aSMark Johnston 100638da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 1, uint8_t) 100738da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 1, uint8_t) 100838da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 1, uint8_t) 100938da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 1, uint8_t) 101038da497aSMark Johnston 101138da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 2, uint16_t) 101238da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 2, uint16_t) 101338da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 2, uint16_t) 101438da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 2, uint16_t) 101538da497aSMark Johnston 101638da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 4, uint32_t) 101738da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 4, uint32_t) 101838da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 4, uint32_t) 101938da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 4, uint32_t) 102038da497aSMark Johnston 1021*818cae0fSMitchell Horne #define ASAN_BUS_PEEK_FUNC(width, type) \ 1022*818cae0fSMitchell Horne int kasan_bus_space_peek_##width(bus_space_tag_t tag, \ 1023*818cae0fSMitchell Horne bus_space_handle_t hnd, bus_size_t offset, type *valuep) \ 1024*818cae0fSMitchell Horne { \ 1025*818cae0fSMitchell Horne return (bus_space_peek_##width(tag, hnd, offset, \ 1026*818cae0fSMitchell Horne valuep)); \ 1027*818cae0fSMitchell Horne } 1028*818cae0fSMitchell Horne 1029*818cae0fSMitchell Horne ASAN_BUS_PEEK_FUNC(1, uint8_t) 1030*818cae0fSMitchell Horne ASAN_BUS_PEEK_FUNC(2, uint16_t) 1031*818cae0fSMitchell Horne ASAN_BUS_PEEK_FUNC(4, uint32_t) 1032*818cae0fSMitchell Horne ASAN_BUS_PEEK_FUNC(8, uint64_t) 1033*818cae0fSMitchell Horne 1034*818cae0fSMitchell Horne #define ASAN_BUS_POKE_FUNC(width, type) \ 1035*818cae0fSMitchell Horne int kasan_bus_space_poke_##width(bus_space_tag_t tag, \ 1036*818cae0fSMitchell Horne bus_space_handle_t hnd, bus_size_t offset, type value) \ 1037*818cae0fSMitchell Horne { \ 1038*818cae0fSMitchell Horne return (bus_space_poke_##width(tag, hnd, offset, \ 1039*818cae0fSMitchell Horne value)); \ 1040*818cae0fSMitchell Horne } 1041*818cae0fSMitchell Horne 1042*818cae0fSMitchell Horne ASAN_BUS_POKE_FUNC(1, uint8_t) 1043*818cae0fSMitchell Horne ASAN_BUS_POKE_FUNC(2, uint16_t) 1044*818cae0fSMitchell Horne ASAN_BUS_POKE_FUNC(4, uint32_t) 1045*818cae0fSMitchell Horne ASAN_BUS_POKE_FUNC(8, uint64_t) 1046*818cae0fSMitchell Horne 104738da497aSMark Johnston /* -------------------------------------------------------------------------- */ 104838da497aSMark Johnston 104938da497aSMark Johnston void __asan_register_globals(struct __asan_global *, size_t); 105038da497aSMark Johnston void __asan_unregister_globals(struct __asan_global *, size_t); 105138da497aSMark Johnston 105238da497aSMark Johnston void 105338da497aSMark Johnston __asan_register_globals(struct __asan_global *globals, size_t n) 105438da497aSMark Johnston { 105538da497aSMark Johnston size_t i; 105638da497aSMark Johnston 105738da497aSMark Johnston for (i = 0; i < n; i++) { 105838da497aSMark Johnston kasan_mark(globals[i].beg, globals[i].size, 105938da497aSMark Johnston globals[i].size_with_redzone, KASAN_GENERIC_REDZONE); 106038da497aSMark Johnston } 106138da497aSMark Johnston } 106238da497aSMark Johnston 106338da497aSMark Johnston void 106438da497aSMark Johnston __asan_unregister_globals(struct __asan_global *globals, size_t n) 106538da497aSMark Johnston { 1066588c7a06SMark Johnston size_t i; 1067588c7a06SMark Johnston 1068588c7a06SMark Johnston for (i = 0; i < n; i++) { 1069588c7a06SMark Johnston kasan_mark(globals[i].beg, globals[i].size_with_redzone, 1070588c7a06SMark Johnston globals[i].size_with_redzone, 0); 1071588c7a06SMark Johnston } 107238da497aSMark Johnston } 107338da497aSMark Johnston 107438da497aSMark Johnston #define ASAN_LOAD_STORE(size) \ 107538da497aSMark Johnston void __asan_load##size(unsigned long); \ 107638da497aSMark Johnston void __asan_load##size(unsigned long addr) \ 107738da497aSMark Johnston { \ 107838da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR);\ 107938da497aSMark Johnston } \ 108038da497aSMark Johnston void __asan_load##size##_noabort(unsigned long); \ 108138da497aSMark Johnston void __asan_load##size##_noabort(unsigned long addr) \ 108238da497aSMark Johnston { \ 108338da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR);\ 108438da497aSMark Johnston } \ 108538da497aSMark Johnston void __asan_store##size(unsigned long); \ 108638da497aSMark Johnston void __asan_store##size(unsigned long addr) \ 108738da497aSMark Johnston { \ 108838da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR);\ 108938da497aSMark Johnston } \ 109038da497aSMark Johnston void __asan_store##size##_noabort(unsigned long); \ 109138da497aSMark Johnston void __asan_store##size##_noabort(unsigned long addr) \ 109238da497aSMark Johnston { \ 109338da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR);\ 109438da497aSMark Johnston } 109538da497aSMark Johnston 109638da497aSMark Johnston ASAN_LOAD_STORE(1); 109738da497aSMark Johnston ASAN_LOAD_STORE(2); 109838da497aSMark Johnston ASAN_LOAD_STORE(4); 109938da497aSMark Johnston ASAN_LOAD_STORE(8); 110038da497aSMark Johnston ASAN_LOAD_STORE(16); 110138da497aSMark Johnston 110238da497aSMark Johnston void __asan_loadN(unsigned long, size_t); 110338da497aSMark Johnston void __asan_loadN_noabort(unsigned long, size_t); 110438da497aSMark Johnston void __asan_storeN(unsigned long, size_t); 110538da497aSMark Johnston void __asan_storeN_noabort(unsigned long, size_t); 110638da497aSMark Johnston void __asan_handle_no_return(void); 110738da497aSMark Johnston 110838da497aSMark Johnston void 110938da497aSMark Johnston __asan_loadN(unsigned long addr, size_t size) 111038da497aSMark Johnston { 111138da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR); 111238da497aSMark Johnston } 111338da497aSMark Johnston 111438da497aSMark Johnston void 111538da497aSMark Johnston __asan_loadN_noabort(unsigned long addr, size_t size) 111638da497aSMark Johnston { 111738da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR); 111838da497aSMark Johnston } 111938da497aSMark Johnston 112038da497aSMark Johnston void 112138da497aSMark Johnston __asan_storeN(unsigned long addr, size_t size) 112238da497aSMark Johnston { 112338da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR); 112438da497aSMark Johnston } 112538da497aSMark Johnston 112638da497aSMark Johnston void 112738da497aSMark Johnston __asan_storeN_noabort(unsigned long addr, size_t size) 112838da497aSMark Johnston { 112938da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR); 113038da497aSMark Johnston } 113138da497aSMark Johnston 113238da497aSMark Johnston void 113338da497aSMark Johnston __asan_handle_no_return(void) 113438da497aSMark Johnston { 113538da497aSMark Johnston /* nothing */ 113638da497aSMark Johnston } 113738da497aSMark Johnston 113838da497aSMark Johnston #define ASAN_SET_SHADOW(byte) \ 113938da497aSMark Johnston void __asan_set_shadow_##byte(void *, size_t); \ 114038da497aSMark Johnston void __asan_set_shadow_##byte(void *addr, size_t size) \ 114138da497aSMark Johnston { \ 114238da497aSMark Johnston __builtin_memset((void *)addr, 0x##byte, size); \ 114338da497aSMark Johnston } 114438da497aSMark Johnston 114538da497aSMark Johnston ASAN_SET_SHADOW(00); 114638da497aSMark Johnston ASAN_SET_SHADOW(f1); 114738da497aSMark Johnston ASAN_SET_SHADOW(f2); 114838da497aSMark Johnston ASAN_SET_SHADOW(f3); 114938da497aSMark Johnston ASAN_SET_SHADOW(f5); 115038da497aSMark Johnston ASAN_SET_SHADOW(f8); 115138da497aSMark Johnston 115238da497aSMark Johnston void __asan_poison_stack_memory(const void *, size_t); 115338da497aSMark Johnston void __asan_unpoison_stack_memory(const void *, size_t); 115438da497aSMark Johnston 115538da497aSMark Johnston void 115638da497aSMark Johnston __asan_poison_stack_memory(const void *addr, size_t size) 115738da497aSMark Johnston { 115838da497aSMark Johnston size = roundup(size, KASAN_SHADOW_SCALE); 115938da497aSMark Johnston kasan_shadow_Nbyte_fill(addr, size, KASAN_USE_AFTER_SCOPE); 116038da497aSMark Johnston } 116138da497aSMark Johnston 116238da497aSMark Johnston void 116338da497aSMark Johnston __asan_unpoison_stack_memory(const void *addr, size_t size) 116438da497aSMark Johnston { 116538da497aSMark Johnston kasan_shadow_Nbyte_markvalid(addr, size); 116638da497aSMark Johnston } 116738da497aSMark Johnston 116838da497aSMark Johnston void __asan_alloca_poison(const void *, size_t); 116938da497aSMark Johnston void __asan_allocas_unpoison(const void *, const void *); 117038da497aSMark Johnston 117138da497aSMark Johnston void 117238da497aSMark Johnston __asan_alloca_poison(const void *addr, size_t size) 117338da497aSMark Johnston { 117438da497aSMark Johnston const void *l, *r; 117538da497aSMark Johnston 117638da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_ALLOCA_SCALE_SIZE == 0, 117738da497aSMark Johnston ("%s: invalid address %p", __func__, addr)); 117838da497aSMark Johnston 117938da497aSMark Johnston l = (const uint8_t *)addr - KASAN_ALLOCA_SCALE_SIZE; 118038da497aSMark Johnston r = (const uint8_t *)addr + roundup(size, KASAN_ALLOCA_SCALE_SIZE); 118138da497aSMark Johnston 118238da497aSMark Johnston kasan_shadow_Nbyte_fill(l, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_LEFT); 118338da497aSMark Johnston kasan_mark(addr, size, roundup(size, KASAN_ALLOCA_SCALE_SIZE), 118438da497aSMark Johnston KASAN_STACK_MID); 118538da497aSMark Johnston kasan_shadow_Nbyte_fill(r, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_RIGHT); 118638da497aSMark Johnston } 118738da497aSMark Johnston 118838da497aSMark Johnston void 118938da497aSMark Johnston __asan_allocas_unpoison(const void *stkbegin, const void *stkend) 119038da497aSMark Johnston { 119138da497aSMark Johnston size_t size; 119238da497aSMark Johnston 119338da497aSMark Johnston if (__predict_false(!stkbegin)) 119438da497aSMark Johnston return; 119538da497aSMark Johnston if (__predict_false((uintptr_t)stkbegin > (uintptr_t)stkend)) 119638da497aSMark Johnston return; 119738da497aSMark Johnston size = (uintptr_t)stkend - (uintptr_t)stkbegin; 119838da497aSMark Johnston 119938da497aSMark Johnston kasan_shadow_Nbyte_fill(stkbegin, size, 0); 120038da497aSMark Johnston } 120138da497aSMark Johnston 120238da497aSMark Johnston void __asan_poison_memory_region(const void *addr, size_t size); 120338da497aSMark Johnston void __asan_unpoison_memory_region(const void *addr, size_t size); 120438da497aSMark Johnston 120538da497aSMark Johnston void 120638da497aSMark Johnston __asan_poison_memory_region(const void *addr, size_t size) 120738da497aSMark Johnston { 120838da497aSMark Johnston } 120938da497aSMark Johnston 121038da497aSMark Johnston void 121138da497aSMark Johnston __asan_unpoison_memory_region(const void *addr, size_t size) 121238da497aSMark Johnston { 121338da497aSMark Johnston } 1214