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