1*38da497aSMark Johnston /* $NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $ */ 2*38da497aSMark Johnston 3*38da497aSMark Johnston /* 4*38da497aSMark Johnston * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net 5*38da497aSMark Johnston * All rights reserved. 6*38da497aSMark Johnston * 7*38da497aSMark Johnston * This code is part of the KASAN subsystem of the NetBSD kernel. 8*38da497aSMark Johnston * 9*38da497aSMark Johnston * Redistribution and use in source and binary forms, with or without 10*38da497aSMark Johnston * modification, are permitted provided that the following conditions 11*38da497aSMark Johnston * are met: 12*38da497aSMark Johnston * 1. Redistributions of source code must retain the above copyright 13*38da497aSMark Johnston * notice, this list of conditions and the following disclaimer. 14*38da497aSMark Johnston * 2. Redistributions in binary form must reproduce the above copyright 15*38da497aSMark Johnston * notice, this list of conditions and the following disclaimer in the 16*38da497aSMark Johnston * documentation and/or other materials provided with the distribution. 17*38da497aSMark Johnston * 18*38da497aSMark Johnston * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19*38da497aSMark Johnston * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20*38da497aSMark Johnston * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21*38da497aSMark Johnston * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22*38da497aSMark Johnston * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23*38da497aSMark Johnston * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24*38da497aSMark Johnston * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25*38da497aSMark Johnston * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26*38da497aSMark Johnston * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27*38da497aSMark Johnston * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*38da497aSMark Johnston * SUCH DAMAGE. 29*38da497aSMark Johnston */ 30*38da497aSMark Johnston 31*38da497aSMark Johnston #define SAN_RUNTIME 32*38da497aSMark Johnston 33*38da497aSMark Johnston #include <sys/cdefs.h> 34*38da497aSMark Johnston __FBSDID("$FreeBSD$"); 35*38da497aSMark Johnston #if 0 36*38da497aSMark Johnston __KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $"); 37*38da497aSMark Johnston #endif 38*38da497aSMark Johnston 39*38da497aSMark Johnston #include <sys/param.h> 40*38da497aSMark Johnston #include <sys/systm.h> 41*38da497aSMark Johnston #include <sys/asan.h> 42*38da497aSMark Johnston #include <sys/kernel.h> 43*38da497aSMark Johnston #include <sys/stack.h> 44*38da497aSMark Johnston #include <sys/sysctl.h> 45*38da497aSMark Johnston 46*38da497aSMark Johnston #include <machine/asan.h> 47*38da497aSMark Johnston 48*38da497aSMark Johnston /* ASAN constants. Part of the compiler ABI. */ 49*38da497aSMark Johnston #define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE - 1) 50*38da497aSMark Johnston #define KASAN_ALLOCA_SCALE_SIZE 32 51*38da497aSMark Johnston 52*38da497aSMark Johnston /* ASAN ABI version. */ 53*38da497aSMark Johnston #if defined(__clang__) && (__clang_major__ - 0 >= 6) 54*38da497aSMark Johnston #define ASAN_ABI_VERSION 8 55*38da497aSMark Johnston #elif __GNUC_PREREQ__(7, 1) && !defined(__clang__) 56*38da497aSMark Johnston #define ASAN_ABI_VERSION 8 57*38da497aSMark Johnston #elif __GNUC_PREREQ__(6, 1) && !defined(__clang__) 58*38da497aSMark Johnston #define ASAN_ABI_VERSION 6 59*38da497aSMark Johnston #else 60*38da497aSMark Johnston #error "Unsupported compiler version" 61*38da497aSMark Johnston #endif 62*38da497aSMark Johnston 63*38da497aSMark Johnston #define __RET_ADDR (unsigned long)__builtin_return_address(0) 64*38da497aSMark Johnston 65*38da497aSMark Johnston /* Global variable descriptor. Part of the compiler ABI. */ 66*38da497aSMark Johnston struct __asan_global_source_location { 67*38da497aSMark Johnston const char *filename; 68*38da497aSMark Johnston int line_no; 69*38da497aSMark Johnston int column_no; 70*38da497aSMark Johnston }; 71*38da497aSMark Johnston 72*38da497aSMark Johnston struct __asan_global { 73*38da497aSMark Johnston const void *beg; /* address of the global variable */ 74*38da497aSMark Johnston size_t size; /* size of the global variable */ 75*38da497aSMark Johnston size_t size_with_redzone; /* size with the redzone */ 76*38da497aSMark Johnston const void *name; /* name of the variable */ 77*38da497aSMark Johnston const void *module_name; /* name of the module where the var is declared */ 78*38da497aSMark Johnston unsigned long has_dynamic_init; /* the var has dyn initializer (c++) */ 79*38da497aSMark Johnston struct __asan_global_source_location *location; 80*38da497aSMark Johnston #if ASAN_ABI_VERSION >= 7 81*38da497aSMark Johnston uintptr_t odr_indicator; /* the address of the ODR indicator symbol */ 82*38da497aSMark Johnston #endif 83*38da497aSMark Johnston }; 84*38da497aSMark Johnston 85*38da497aSMark Johnston FEATURE(kasan, "Kernel address sanitizer"); 86*38da497aSMark Johnston 87*38da497aSMark Johnston static SYSCTL_NODE(_debug, OID_AUTO, kasan, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 88*38da497aSMark Johnston "KASAN options"); 89*38da497aSMark Johnston 90*38da497aSMark Johnston static int panic_on_violation = 1; 91*38da497aSMark Johnston SYSCTL_INT(_debug_kasan, OID_AUTO, panic_on_violation, CTLFLAG_RDTUN, 92*38da497aSMark Johnston &panic_on_violation, 0, 93*38da497aSMark Johnston "Panic if an invalid access is detected"); 94*38da497aSMark Johnston 95*38da497aSMark Johnston static bool kasan_enabled __read_mostly = false; 96*38da497aSMark Johnston 97*38da497aSMark Johnston /* -------------------------------------------------------------------------- */ 98*38da497aSMark Johnston 99*38da497aSMark Johnston void 100*38da497aSMark Johnston kasan_shadow_map(void *addr, size_t size) 101*38da497aSMark Johnston { 102*38da497aSMark Johnston size_t sz, npages, i; 103*38da497aSMark Johnston vm_offset_t sva, eva; 104*38da497aSMark Johnston 105*38da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0, 106*38da497aSMark Johnston ("%s: invalid address %p", __func__, addr)); 107*38da497aSMark Johnston 108*38da497aSMark Johnston sz = roundup(size, KASAN_SHADOW_SCALE) / KASAN_SHADOW_SCALE; 109*38da497aSMark Johnston 110*38da497aSMark Johnston sva = kasan_md_addr_to_shad((vm_offset_t)addr); 111*38da497aSMark Johnston eva = kasan_md_addr_to_shad((vm_offset_t)addr) + sz; 112*38da497aSMark Johnston 113*38da497aSMark Johnston sva = rounddown(sva, PAGE_SIZE); 114*38da497aSMark Johnston eva = roundup(eva, PAGE_SIZE); 115*38da497aSMark Johnston 116*38da497aSMark Johnston npages = (eva - sva) / PAGE_SIZE; 117*38da497aSMark Johnston 118*38da497aSMark Johnston KASSERT(sva >= KASAN_MIN_ADDRESS && eva < KASAN_MAX_ADDRESS, 119*38da497aSMark Johnston ("%s: invalid address range %#lx-%#lx", __func__, sva, eva)); 120*38da497aSMark Johnston 121*38da497aSMark Johnston for (i = 0; i < npages; i++) 122*38da497aSMark Johnston pmap_kasan_enter(sva + ptoa(i)); 123*38da497aSMark Johnston } 124*38da497aSMark Johnston 125*38da497aSMark Johnston void 126*38da497aSMark Johnston kasan_init(void) 127*38da497aSMark Johnston { 128*38da497aSMark Johnston int disabled; 129*38da497aSMark Johnston 130*38da497aSMark Johnston disabled = 0; 131*38da497aSMark Johnston TUNABLE_INT_FETCH("debug.kasan.disabled", &disabled); 132*38da497aSMark Johnston if (disabled) 133*38da497aSMark Johnston return; 134*38da497aSMark Johnston 135*38da497aSMark Johnston /* MD initialization. */ 136*38da497aSMark Johnston kasan_md_init(); 137*38da497aSMark Johnston 138*38da497aSMark Johnston /* Now officially enabled. */ 139*38da497aSMark Johnston kasan_enabled = true; 140*38da497aSMark Johnston } 141*38da497aSMark Johnston 142*38da497aSMark Johnston static inline const char * 143*38da497aSMark Johnston kasan_code_name(uint8_t code) 144*38da497aSMark Johnston { 145*38da497aSMark Johnston switch (code) { 146*38da497aSMark Johnston case KASAN_GENERIC_REDZONE: 147*38da497aSMark Johnston return "GenericRedZone"; 148*38da497aSMark Johnston case KASAN_MALLOC_REDZONE: 149*38da497aSMark Johnston return "MallocRedZone"; 150*38da497aSMark Johnston case KASAN_KMEM_REDZONE: 151*38da497aSMark Johnston return "KmemRedZone"; 152*38da497aSMark Johnston case KASAN_UMA_FREED: 153*38da497aSMark Johnston return "UMAUseAfterFree"; 154*38da497aSMark Johnston case KASAN_KSTACK_FREED: 155*38da497aSMark Johnston return "KernelStack"; 156*38da497aSMark Johnston case 1 ... 7: 157*38da497aSMark Johnston return "RedZonePartial"; 158*38da497aSMark Johnston case KASAN_STACK_LEFT: 159*38da497aSMark Johnston return "StackLeft"; 160*38da497aSMark Johnston case KASAN_STACK_MID: 161*38da497aSMark Johnston return "StackMiddle"; 162*38da497aSMark Johnston case KASAN_STACK_RIGHT: 163*38da497aSMark Johnston return "StackRight"; 164*38da497aSMark Johnston case KASAN_USE_AFTER_RET: 165*38da497aSMark Johnston return "UseAfterRet"; 166*38da497aSMark Johnston case KASAN_USE_AFTER_SCOPE: 167*38da497aSMark Johnston return "UseAfterScope"; 168*38da497aSMark Johnston default: 169*38da497aSMark Johnston return "Unknown"; 170*38da497aSMark Johnston } 171*38da497aSMark Johnston } 172*38da497aSMark Johnston 173*38da497aSMark Johnston #define REPORT(f, ...) do { \ 174*38da497aSMark Johnston if (panic_on_violation) { \ 175*38da497aSMark Johnston panic(f, __VA_ARGS__); \ 176*38da497aSMark Johnston } else { \ 177*38da497aSMark Johnston struct stack st; \ 178*38da497aSMark Johnston \ 179*38da497aSMark Johnston stack_save(&st); \ 180*38da497aSMark Johnston printf(f "\n", __VA_ARGS__); \ 181*38da497aSMark Johnston stack_print_ddb(&st); \ 182*38da497aSMark Johnston } \ 183*38da497aSMark Johnston } while (0) 184*38da497aSMark Johnston 185*38da497aSMark Johnston static void 186*38da497aSMark Johnston kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc, 187*38da497aSMark Johnston uint8_t code) 188*38da497aSMark Johnston { 189*38da497aSMark Johnston REPORT("ASan: Invalid access, %zu-byte %s at %#lx, %s(%x)", 190*38da497aSMark Johnston size, (write ? "write" : "read"), addr, kasan_code_name(code), 191*38da497aSMark Johnston code); 192*38da497aSMark Johnston } 193*38da497aSMark Johnston 194*38da497aSMark Johnston static __always_inline void 195*38da497aSMark Johnston kasan_shadow_1byte_markvalid(unsigned long addr) 196*38da497aSMark Johnston { 197*38da497aSMark Johnston int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr); 198*38da497aSMark Johnston int8_t last = (addr & KASAN_SHADOW_MASK) + 1; 199*38da497aSMark Johnston 200*38da497aSMark Johnston *byte = last; 201*38da497aSMark Johnston } 202*38da497aSMark Johnston 203*38da497aSMark Johnston static __always_inline void 204*38da497aSMark Johnston kasan_shadow_Nbyte_markvalid(const void *addr, size_t size) 205*38da497aSMark Johnston { 206*38da497aSMark Johnston size_t i; 207*38da497aSMark Johnston 208*38da497aSMark Johnston for (i = 0; i < size; i++) { 209*38da497aSMark Johnston kasan_shadow_1byte_markvalid((unsigned long)addr + i); 210*38da497aSMark Johnston } 211*38da497aSMark Johnston } 212*38da497aSMark Johnston 213*38da497aSMark Johnston static __always_inline void 214*38da497aSMark Johnston kasan_shadow_Nbyte_fill(const void *addr, size_t size, uint8_t code) 215*38da497aSMark Johnston { 216*38da497aSMark Johnston void *shad; 217*38da497aSMark Johnston 218*38da497aSMark Johnston if (__predict_false(size == 0)) 219*38da497aSMark Johnston return; 220*38da497aSMark Johnston if (__predict_false(kasan_md_unsupported((vm_offset_t)addr))) 221*38da497aSMark Johnston return; 222*38da497aSMark Johnston 223*38da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0, 224*38da497aSMark Johnston ("%s: invalid address %p", __func__, addr)); 225*38da497aSMark Johnston KASSERT(size % KASAN_SHADOW_SCALE == 0, 226*38da497aSMark Johnston ("%s: invalid size %zu", __func__, size)); 227*38da497aSMark Johnston 228*38da497aSMark Johnston shad = (void *)kasan_md_addr_to_shad((uintptr_t)addr); 229*38da497aSMark Johnston size = size >> KASAN_SHADOW_SCALE_SHIFT; 230*38da497aSMark Johnston 231*38da497aSMark Johnston __builtin_memset(shad, code, size); 232*38da497aSMark Johnston } 233*38da497aSMark Johnston 234*38da497aSMark Johnston /* 235*38da497aSMark Johnston * In an area of size 'sz_with_redz', mark the 'size' first bytes as valid, 236*38da497aSMark Johnston * and the rest as invalid. There are generally two use cases: 237*38da497aSMark Johnston * 238*38da497aSMark Johnston * o kasan_mark(addr, origsize, size, code), with origsize < size. This marks 239*38da497aSMark Johnston * the redzone at the end of the buffer as invalid. If the entire is to be 240*38da497aSMark Johnston * marked invalid, origsize will be 0. 241*38da497aSMark Johnston * 242*38da497aSMark Johnston * o kasan_mark(addr, size, size, 0). This marks the entire buffer as valid. 243*38da497aSMark Johnston */ 244*38da497aSMark Johnston void 245*38da497aSMark Johnston kasan_mark(const void *addr, size_t size, size_t redzsize, uint8_t code) 246*38da497aSMark Johnston { 247*38da497aSMark Johnston size_t i, n, redz; 248*38da497aSMark Johnston int8_t *shad; 249*38da497aSMark Johnston 250*38da497aSMark Johnston if ((vm_offset_t)addr >= DMAP_MIN_ADDRESS && 251*38da497aSMark Johnston (vm_offset_t)addr < DMAP_MAX_ADDRESS) 252*38da497aSMark Johnston return; 253*38da497aSMark Johnston 254*38da497aSMark Johnston KASSERT((vm_offset_t)addr >= VM_MIN_KERNEL_ADDRESS && 255*38da497aSMark Johnston (vm_offset_t)addr < VM_MAX_KERNEL_ADDRESS, 256*38da497aSMark Johnston ("%s: invalid address %p", __func__, addr)); 257*38da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0, 258*38da497aSMark Johnston ("%s: invalid address %p", __func__, addr)); 259*38da497aSMark Johnston redz = redzsize - roundup(size, KASAN_SHADOW_SCALE); 260*38da497aSMark Johnston KASSERT(redz % KASAN_SHADOW_SCALE == 0, 261*38da497aSMark Johnston ("%s: invalid size %zu", __func__, redz)); 262*38da497aSMark Johnston shad = (int8_t *)kasan_md_addr_to_shad((uintptr_t)addr); 263*38da497aSMark Johnston 264*38da497aSMark Johnston /* Chunks of 8 bytes, valid. */ 265*38da497aSMark Johnston n = size / KASAN_SHADOW_SCALE; 266*38da497aSMark Johnston for (i = 0; i < n; i++) { 267*38da497aSMark Johnston *shad++ = 0; 268*38da497aSMark Johnston } 269*38da497aSMark Johnston 270*38da497aSMark Johnston /* Possibly one chunk, mid. */ 271*38da497aSMark Johnston if ((size & KASAN_SHADOW_MASK) != 0) { 272*38da497aSMark Johnston *shad++ = (size & KASAN_SHADOW_MASK); 273*38da497aSMark Johnston } 274*38da497aSMark Johnston 275*38da497aSMark Johnston /* Chunks of 8 bytes, invalid. */ 276*38da497aSMark Johnston n = redz / KASAN_SHADOW_SCALE; 277*38da497aSMark Johnston for (i = 0; i < n; i++) { 278*38da497aSMark Johnston *shad++ = code; 279*38da497aSMark Johnston } 280*38da497aSMark Johnston } 281*38da497aSMark Johnston 282*38da497aSMark Johnston /* -------------------------------------------------------------------------- */ 283*38da497aSMark Johnston 284*38da497aSMark Johnston #define ADDR_CROSSES_SCALE_BOUNDARY(addr, size) \ 285*38da497aSMark Johnston (addr >> KASAN_SHADOW_SCALE_SHIFT) != \ 286*38da497aSMark Johnston ((addr + size - 1) >> KASAN_SHADOW_SCALE_SHIFT) 287*38da497aSMark Johnston 288*38da497aSMark Johnston static __always_inline bool 289*38da497aSMark Johnston kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code) 290*38da497aSMark Johnston { 291*38da497aSMark Johnston int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr); 292*38da497aSMark Johnston int8_t last = (addr & KASAN_SHADOW_MASK) + 1; 293*38da497aSMark Johnston 294*38da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) { 295*38da497aSMark Johnston return (true); 296*38da497aSMark Johnston } 297*38da497aSMark Johnston *code = *byte; 298*38da497aSMark Johnston return (false); 299*38da497aSMark Johnston } 300*38da497aSMark Johnston 301*38da497aSMark Johnston static __always_inline bool 302*38da497aSMark Johnston kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code) 303*38da497aSMark Johnston { 304*38da497aSMark Johnston int8_t *byte, last; 305*38da497aSMark Johnston 306*38da497aSMark Johnston if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 2)) { 307*38da497aSMark Johnston return (kasan_shadow_1byte_isvalid(addr, code) && 308*38da497aSMark Johnston kasan_shadow_1byte_isvalid(addr+1, code)); 309*38da497aSMark Johnston } 310*38da497aSMark Johnston 311*38da497aSMark Johnston byte = (int8_t *)kasan_md_addr_to_shad(addr); 312*38da497aSMark Johnston last = ((addr + 1) & KASAN_SHADOW_MASK) + 1; 313*38da497aSMark Johnston 314*38da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) { 315*38da497aSMark Johnston return (true); 316*38da497aSMark Johnston } 317*38da497aSMark Johnston *code = *byte; 318*38da497aSMark Johnston return (false); 319*38da497aSMark Johnston } 320*38da497aSMark Johnston 321*38da497aSMark Johnston static __always_inline bool 322*38da497aSMark Johnston kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code) 323*38da497aSMark Johnston { 324*38da497aSMark Johnston int8_t *byte, last; 325*38da497aSMark Johnston 326*38da497aSMark Johnston if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 4)) { 327*38da497aSMark Johnston return (kasan_shadow_2byte_isvalid(addr, code) && 328*38da497aSMark Johnston kasan_shadow_2byte_isvalid(addr+2, code)); 329*38da497aSMark Johnston } 330*38da497aSMark Johnston 331*38da497aSMark Johnston byte = (int8_t *)kasan_md_addr_to_shad(addr); 332*38da497aSMark Johnston last = ((addr + 3) & KASAN_SHADOW_MASK) + 1; 333*38da497aSMark Johnston 334*38da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) { 335*38da497aSMark Johnston return (true); 336*38da497aSMark Johnston } 337*38da497aSMark Johnston *code = *byte; 338*38da497aSMark Johnston return (false); 339*38da497aSMark Johnston } 340*38da497aSMark Johnston 341*38da497aSMark Johnston static __always_inline bool 342*38da497aSMark Johnston kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code) 343*38da497aSMark Johnston { 344*38da497aSMark Johnston int8_t *byte, last; 345*38da497aSMark Johnston 346*38da497aSMark Johnston if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 8)) { 347*38da497aSMark Johnston return (kasan_shadow_4byte_isvalid(addr, code) && 348*38da497aSMark Johnston kasan_shadow_4byte_isvalid(addr+4, code)); 349*38da497aSMark Johnston } 350*38da497aSMark Johnston 351*38da497aSMark Johnston byte = (int8_t *)kasan_md_addr_to_shad(addr); 352*38da497aSMark Johnston last = ((addr + 7) & KASAN_SHADOW_MASK) + 1; 353*38da497aSMark Johnston 354*38da497aSMark Johnston if (__predict_true(*byte == 0 || last <= *byte)) { 355*38da497aSMark Johnston return (true); 356*38da497aSMark Johnston } 357*38da497aSMark Johnston *code = *byte; 358*38da497aSMark Johnston return (false); 359*38da497aSMark Johnston } 360*38da497aSMark Johnston 361*38da497aSMark Johnston static __always_inline bool 362*38da497aSMark Johnston kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code) 363*38da497aSMark Johnston { 364*38da497aSMark Johnston size_t i; 365*38da497aSMark Johnston 366*38da497aSMark Johnston for (i = 0; i < size; i++) { 367*38da497aSMark Johnston if (!kasan_shadow_1byte_isvalid(addr+i, code)) 368*38da497aSMark Johnston return (false); 369*38da497aSMark Johnston } 370*38da497aSMark Johnston 371*38da497aSMark Johnston return (true); 372*38da497aSMark Johnston } 373*38da497aSMark Johnston 374*38da497aSMark Johnston static __always_inline void 375*38da497aSMark Johnston kasan_shadow_check(unsigned long addr, size_t size, bool write, 376*38da497aSMark Johnston unsigned long retaddr) 377*38da497aSMark Johnston { 378*38da497aSMark Johnston uint8_t code; 379*38da497aSMark Johnston bool valid; 380*38da497aSMark Johnston 381*38da497aSMark Johnston if (__predict_false(!kasan_enabled)) 382*38da497aSMark Johnston return; 383*38da497aSMark Johnston if (__predict_false(size == 0)) 384*38da497aSMark Johnston return; 385*38da497aSMark Johnston if (__predict_false(kasan_md_unsupported(addr))) 386*38da497aSMark Johnston return; 387*38da497aSMark Johnston if (__predict_false(panicstr != NULL)) 388*38da497aSMark Johnston return; 389*38da497aSMark Johnston 390*38da497aSMark Johnston if (__builtin_constant_p(size)) { 391*38da497aSMark Johnston switch (size) { 392*38da497aSMark Johnston case 1: 393*38da497aSMark Johnston valid = kasan_shadow_1byte_isvalid(addr, &code); 394*38da497aSMark Johnston break; 395*38da497aSMark Johnston case 2: 396*38da497aSMark Johnston valid = kasan_shadow_2byte_isvalid(addr, &code); 397*38da497aSMark Johnston break; 398*38da497aSMark Johnston case 4: 399*38da497aSMark Johnston valid = kasan_shadow_4byte_isvalid(addr, &code); 400*38da497aSMark Johnston break; 401*38da497aSMark Johnston case 8: 402*38da497aSMark Johnston valid = kasan_shadow_8byte_isvalid(addr, &code); 403*38da497aSMark Johnston break; 404*38da497aSMark Johnston default: 405*38da497aSMark Johnston valid = kasan_shadow_Nbyte_isvalid(addr, size, &code); 406*38da497aSMark Johnston break; 407*38da497aSMark Johnston } 408*38da497aSMark Johnston } else { 409*38da497aSMark Johnston valid = kasan_shadow_Nbyte_isvalid(addr, size, &code); 410*38da497aSMark Johnston } 411*38da497aSMark Johnston 412*38da497aSMark Johnston if (__predict_false(!valid)) { 413*38da497aSMark Johnston kasan_report(addr, size, write, retaddr, code); 414*38da497aSMark Johnston } 415*38da497aSMark Johnston } 416*38da497aSMark Johnston 417*38da497aSMark Johnston /* -------------------------------------------------------------------------- */ 418*38da497aSMark Johnston 419*38da497aSMark Johnston void * 420*38da497aSMark Johnston kasan_memcpy(void *dst, const void *src, size_t len) 421*38da497aSMark Johnston { 422*38da497aSMark Johnston kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); 423*38da497aSMark Johnston kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); 424*38da497aSMark Johnston return (__builtin_memcpy(dst, src, len)); 425*38da497aSMark Johnston } 426*38da497aSMark Johnston 427*38da497aSMark Johnston int 428*38da497aSMark Johnston kasan_memcmp(const void *b1, const void *b2, size_t len) 429*38da497aSMark Johnston { 430*38da497aSMark Johnston kasan_shadow_check((unsigned long)b1, len, false, __RET_ADDR); 431*38da497aSMark Johnston kasan_shadow_check((unsigned long)b2, len, false, __RET_ADDR); 432*38da497aSMark Johnston return (__builtin_memcmp(b1, b2, len)); 433*38da497aSMark Johnston } 434*38da497aSMark Johnston 435*38da497aSMark Johnston void * 436*38da497aSMark Johnston kasan_memset(void *b, int c, size_t len) 437*38da497aSMark Johnston { 438*38da497aSMark Johnston kasan_shadow_check((unsigned long)b, len, true, __RET_ADDR); 439*38da497aSMark Johnston return (__builtin_memset(b, c, len)); 440*38da497aSMark Johnston } 441*38da497aSMark Johnston 442*38da497aSMark Johnston void * 443*38da497aSMark Johnston kasan_memmove(void *dst, const void *src, size_t len) 444*38da497aSMark Johnston { 445*38da497aSMark Johnston kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR); 446*38da497aSMark Johnston kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR); 447*38da497aSMark Johnston return (__builtin_memmove(dst, src, len)); 448*38da497aSMark Johnston } 449*38da497aSMark Johnston 450*38da497aSMark Johnston size_t 451*38da497aSMark Johnston kasan_strlen(const char *str) 452*38da497aSMark Johnston { 453*38da497aSMark Johnston const char *s; 454*38da497aSMark Johnston 455*38da497aSMark Johnston s = str; 456*38da497aSMark Johnston while (1) { 457*38da497aSMark Johnston kasan_shadow_check((unsigned long)s, 1, false, __RET_ADDR); 458*38da497aSMark Johnston if (*s == '\0') 459*38da497aSMark Johnston break; 460*38da497aSMark Johnston s++; 461*38da497aSMark Johnston } 462*38da497aSMark Johnston 463*38da497aSMark Johnston return (s - str); 464*38da497aSMark Johnston } 465*38da497aSMark Johnston 466*38da497aSMark Johnston char * 467*38da497aSMark Johnston kasan_strcpy(char *dst, const char *src) 468*38da497aSMark Johnston { 469*38da497aSMark Johnston char *save = dst; 470*38da497aSMark Johnston 471*38da497aSMark Johnston while (1) { 472*38da497aSMark Johnston kasan_shadow_check((unsigned long)src, 1, false, __RET_ADDR); 473*38da497aSMark Johnston kasan_shadow_check((unsigned long)dst, 1, true, __RET_ADDR); 474*38da497aSMark Johnston *dst = *src; 475*38da497aSMark Johnston if (*src == '\0') 476*38da497aSMark Johnston break; 477*38da497aSMark Johnston src++, dst++; 478*38da497aSMark Johnston } 479*38da497aSMark Johnston 480*38da497aSMark Johnston return save; 481*38da497aSMark Johnston } 482*38da497aSMark Johnston 483*38da497aSMark Johnston int 484*38da497aSMark Johnston kasan_strcmp(const char *s1, const char *s2) 485*38da497aSMark Johnston { 486*38da497aSMark Johnston while (1) { 487*38da497aSMark Johnston kasan_shadow_check((unsigned long)s1, 1, false, __RET_ADDR); 488*38da497aSMark Johnston kasan_shadow_check((unsigned long)s2, 1, false, __RET_ADDR); 489*38da497aSMark Johnston if (*s1 != *s2) 490*38da497aSMark Johnston break; 491*38da497aSMark Johnston if (*s1 == '\0') 492*38da497aSMark Johnston return 0; 493*38da497aSMark Johnston s1++, s2++; 494*38da497aSMark Johnston } 495*38da497aSMark Johnston 496*38da497aSMark Johnston return (*(const unsigned char *)s1 - *(const unsigned char *)s2); 497*38da497aSMark Johnston } 498*38da497aSMark Johnston 499*38da497aSMark Johnston int 500*38da497aSMark Johnston kasan_copyin(const void *uaddr, void *kaddr, size_t len) 501*38da497aSMark Johnston { 502*38da497aSMark Johnston kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR); 503*38da497aSMark Johnston return (copyin(uaddr, kaddr, len)); 504*38da497aSMark Johnston } 505*38da497aSMark Johnston 506*38da497aSMark Johnston int 507*38da497aSMark Johnston kasan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) 508*38da497aSMark Johnston { 509*38da497aSMark Johnston kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR); 510*38da497aSMark Johnston return (copyinstr(uaddr, kaddr, len, done)); 511*38da497aSMark Johnston } 512*38da497aSMark Johnston 513*38da497aSMark Johnston int 514*38da497aSMark Johnston kasan_copyout(const void *kaddr, void *uaddr, size_t len) 515*38da497aSMark Johnston { 516*38da497aSMark Johnston kasan_shadow_check((unsigned long)kaddr, len, false, __RET_ADDR); 517*38da497aSMark Johnston return (copyout(kaddr, uaddr, len)); 518*38da497aSMark Johnston } 519*38da497aSMark Johnston 520*38da497aSMark Johnston /* -------------------------------------------------------------------------- */ 521*38da497aSMark Johnston 522*38da497aSMark Johnston #include <machine/atomic.h> 523*38da497aSMark Johnston #define ATOMIC_SAN_PREFIX kasan 524*38da497aSMark Johnston #include <sys/atomic_san.h> 525*38da497aSMark Johnston 526*38da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_ADD(name, type) \ 527*38da497aSMark Johnston void kasan_atomic_add_##name(volatile type *ptr, type val) \ 528*38da497aSMark Johnston { \ 529*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 530*38da497aSMark Johnston __RET_ADDR); \ 531*38da497aSMark Johnston atomic_add_##name(ptr, val); \ 532*38da497aSMark Johnston } 533*38da497aSMark Johnston 534*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_ADD(name, type) \ 535*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_ADD(name, type) \ 536*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_ADD(acq_##name, type) \ 537*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_ADD(rel_##name, type) 538*38da497aSMark Johnston 539*38da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \ 540*38da497aSMark Johnston void kasan_atomic_subtract_##name(volatile type *ptr, type val) \ 541*38da497aSMark Johnston { \ 542*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 543*38da497aSMark Johnston __RET_ADDR); \ 544*38da497aSMark Johnston atomic_subtract_##name(ptr, val); \ 545*38da497aSMark Johnston } 546*38da497aSMark Johnston 547*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \ 548*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_SUBTRACT(name, type) \ 549*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type) \ 550*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type) 551*38da497aSMark Johnston 552*38da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_SET(name, type) \ 553*38da497aSMark Johnston void kasan_atomic_set_##name(volatile type *ptr, type val) \ 554*38da497aSMark Johnston { \ 555*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 556*38da497aSMark Johnston __RET_ADDR); \ 557*38da497aSMark Johnston atomic_set_##name(ptr, val); \ 558*38da497aSMark Johnston } 559*38da497aSMark Johnston 560*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_SET(name, type) \ 561*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_SET(name, type) \ 562*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_SET(acq_##name, type) \ 563*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_SET(rel_##name, type) 564*38da497aSMark Johnston 565*38da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_CLEAR(name, type) \ 566*38da497aSMark Johnston void kasan_atomic_clear_##name(volatile type *ptr, type val) \ 567*38da497aSMark Johnston { \ 568*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 569*38da497aSMark Johnston __RET_ADDR); \ 570*38da497aSMark Johnston atomic_clear_##name(ptr, val); \ 571*38da497aSMark Johnston } 572*38da497aSMark Johnston 573*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_CLEAR(name, type) \ 574*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_CLEAR(name, type) \ 575*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_CLEAR(acq_##name, type) \ 576*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_CLEAR(rel_##name, type) 577*38da497aSMark Johnston 578*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_FETCHADD(name, type) \ 579*38da497aSMark Johnston type kasan_atomic_fetchadd_##name(volatile type *ptr, type val) \ 580*38da497aSMark Johnston { \ 581*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 582*38da497aSMark Johnston __RET_ADDR); \ 583*38da497aSMark Johnston return (atomic_fetchadd_##name(ptr, val)); \ 584*38da497aSMark Johnston } 585*38da497aSMark Johnston 586*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_READANDCLEAR(name, type) \ 587*38da497aSMark Johnston type kasan_atomic_readandclear_##name(volatile type *ptr) \ 588*38da497aSMark Johnston { \ 589*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 590*38da497aSMark Johnston __RET_ADDR); \ 591*38da497aSMark Johnston return (atomic_readandclear_##name(ptr)); \ 592*38da497aSMark Johnston } 593*38da497aSMark Johnston 594*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_TESTANDCLEAR(name, type) \ 595*38da497aSMark Johnston int kasan_atomic_testandclear_##name(volatile type *ptr, u_int v) \ 596*38da497aSMark Johnston { \ 597*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 598*38da497aSMark Johnston __RET_ADDR); \ 599*38da497aSMark Johnston return (atomic_testandclear_##name(ptr, v)); \ 600*38da497aSMark Johnston } 601*38da497aSMark Johnston 602*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_TESTANDSET(name, type) \ 603*38da497aSMark Johnston int kasan_atomic_testandset_##name(volatile type *ptr, u_int v) \ 604*38da497aSMark Johnston { \ 605*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 606*38da497aSMark Johnston __RET_ADDR); \ 607*38da497aSMark Johnston return (atomic_testandset_##name(ptr, v)); \ 608*38da497aSMark Johnston } 609*38da497aSMark Johnston 610*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_SWAP(name, type) \ 611*38da497aSMark Johnston type kasan_atomic_swap_##name(volatile type *ptr, type val) \ 612*38da497aSMark Johnston { \ 613*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 614*38da497aSMark Johnston __RET_ADDR); \ 615*38da497aSMark Johnston return (atomic_swap_##name(ptr, val)); \ 616*38da497aSMark Johnston } 617*38da497aSMark Johnston 618*38da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_CMPSET(name, type) \ 619*38da497aSMark Johnston int kasan_atomic_cmpset_##name(volatile type *ptr, type oval, \ 620*38da497aSMark Johnston type nval) \ 621*38da497aSMark Johnston { \ 622*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 623*38da497aSMark Johnston __RET_ADDR); \ 624*38da497aSMark Johnston return (atomic_cmpset_##name(ptr, oval, nval)); \ 625*38da497aSMark Johnston } 626*38da497aSMark Johnston 627*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_CMPSET(name, type) \ 628*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_CMPSET(name, type) \ 629*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_CMPSET(acq_##name, type) \ 630*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_CMPSET(rel_##name, type) 631*38da497aSMark Johnston 632*38da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \ 633*38da497aSMark Johnston int kasan_atomic_fcmpset_##name(volatile type *ptr, type *oval, \ 634*38da497aSMark Johnston type nval) \ 635*38da497aSMark Johnston { \ 636*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 637*38da497aSMark Johnston __RET_ADDR); \ 638*38da497aSMark Johnston return (atomic_fcmpset_##name(ptr, oval, nval)); \ 639*38da497aSMark Johnston } 640*38da497aSMark Johnston 641*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_FCMPSET(name, type) \ 642*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_FCMPSET(name, type) \ 643*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_FCMPSET(acq_##name, type) \ 644*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_FCMPSET(rel_##name, type) 645*38da497aSMark Johnston 646*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_THREAD_FENCE(name) \ 647*38da497aSMark Johnston void kasan_atomic_thread_fence_##name(void) \ 648*38da497aSMark Johnston { \ 649*38da497aSMark Johnston atomic_thread_fence_##name(); \ 650*38da497aSMark Johnston } 651*38da497aSMark Johnston 652*38da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_LOAD(name, type) \ 653*38da497aSMark Johnston type kasan_atomic_load_##name(volatile type *ptr) \ 654*38da497aSMark Johnston { \ 655*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 656*38da497aSMark Johnston __RET_ADDR); \ 657*38da497aSMark Johnston return (atomic_load_##name(ptr)); \ 658*38da497aSMark Johnston } 659*38da497aSMark Johnston 660*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_LOAD(name, type) \ 661*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_LOAD(name, type) \ 662*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_LOAD(acq_##name, type) 663*38da497aSMark Johnston 664*38da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_STORE(name, type) \ 665*38da497aSMark Johnston void kasan_atomic_store_##name(volatile type *ptr, type val) \ 666*38da497aSMark Johnston { \ 667*38da497aSMark Johnston kasan_shadow_check((uintptr_t)ptr, sizeof(type), true, \ 668*38da497aSMark Johnston __RET_ADDR); \ 669*38da497aSMark Johnston atomic_store_##name(ptr, val); \ 670*38da497aSMark Johnston } 671*38da497aSMark Johnston 672*38da497aSMark Johnston #define ASAN_ATOMIC_FUNC_STORE(name, type) \ 673*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_STORE(name, type) \ 674*38da497aSMark Johnston _ASAN_ATOMIC_FUNC_STORE(rel_##name, type) 675*38da497aSMark Johnston 676*38da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(8, uint8_t); 677*38da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(16, uint16_t); 678*38da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(32, uint32_t); 679*38da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(64, uint64_t); 680*38da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(int, u_int); 681*38da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(long, u_long); 682*38da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(ptr, uintptr_t); 683*38da497aSMark Johnston 684*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t); 685*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t); 686*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t); 687*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t); 688*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(int, u_int); 689*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(long, u_long); 690*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t); 691*38da497aSMark Johnston 692*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(8, uint8_t); 693*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(16, uint16_t); 694*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(32, uint32_t); 695*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(64, uint64_t); 696*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(int, u_int); 697*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(long, u_long); 698*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(ptr, uintptr_t); 699*38da497aSMark Johnston 700*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(8, uint8_t); 701*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(16, uint16_t); 702*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(32, uint32_t); 703*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(64, uint64_t); 704*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(int, u_int); 705*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(long, u_long); 706*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t); 707*38da497aSMark Johnston 708*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(32, uint32_t); 709*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(64, uint64_t); 710*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(int, u_int); 711*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(long, u_long); 712*38da497aSMark Johnston 713*38da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t); 714*38da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t); 715*38da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(int, u_int); 716*38da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(long, u_long); 717*38da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t); 718*38da497aSMark Johnston 719*38da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t); 720*38da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t); 721*38da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int); 722*38da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long); 723*38da497aSMark Johnston 724*38da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t); 725*38da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t); 726*38da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(int, u_int); 727*38da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(long, u_long); 728*38da497aSMark Johnston 729*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(32, uint32_t); 730*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(64, uint64_t); 731*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(int, u_int); 732*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(long, u_long); 733*38da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t); 734*38da497aSMark Johnston 735*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(8, uint8_t); 736*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(16, uint16_t); 737*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(32, uint32_t); 738*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(64, uint64_t); 739*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(int, u_int); 740*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(long, u_long); 741*38da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t); 742*38da497aSMark Johnston 743*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(8, uint8_t); 744*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(16, uint16_t); 745*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(32, uint32_t); 746*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(64, uint64_t); 747*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(int, u_int); 748*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(long, u_long); 749*38da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t); 750*38da497aSMark Johnston 751*38da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(8, uint8_t); 752*38da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(16, uint16_t); 753*38da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(32, uint32_t); 754*38da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(64, uint64_t); 755*38da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(char, u_char); 756*38da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(short, u_short); 757*38da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(int, u_int); 758*38da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(long, u_long); 759*38da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t); 760*38da497aSMark Johnston 761*38da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(8, uint8_t); 762*38da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(16, uint16_t); 763*38da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(32, uint32_t); 764*38da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(64, uint64_t); 765*38da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(char, u_char); 766*38da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(short, u_short); 767*38da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(int, u_int); 768*38da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(long, u_long); 769*38da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(ptr, uintptr_t); 770*38da497aSMark Johnston 771*38da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(acq); 772*38da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(rel); 773*38da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel); 774*38da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst); 775*38da497aSMark Johnston 776*38da497aSMark Johnston void 777*38da497aSMark Johnston kasan_atomic_interrupt_fence(void) 778*38da497aSMark Johnston { 779*38da497aSMark Johnston } 780*38da497aSMark Johnston 781*38da497aSMark Johnston /* -------------------------------------------------------------------------- */ 782*38da497aSMark Johnston 783*38da497aSMark Johnston #include <sys/bus.h> 784*38da497aSMark Johnston #include <machine/bus.h> 785*38da497aSMark Johnston #define BUS_SAN_PREFIX kasan 786*38da497aSMark Johnston #include <sys/bus_san.h> 787*38da497aSMark Johnston 788*38da497aSMark Johnston int 789*38da497aSMark Johnston kasan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size, 790*38da497aSMark Johnston int flags, bus_space_handle_t *handlep) 791*38da497aSMark Johnston { 792*38da497aSMark Johnston return (bus_space_map(tag, hnd, size, flags, handlep)); 793*38da497aSMark Johnston } 794*38da497aSMark Johnston 795*38da497aSMark Johnston void 796*38da497aSMark Johnston kasan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd, 797*38da497aSMark Johnston bus_size_t size) 798*38da497aSMark Johnston { 799*38da497aSMark Johnston bus_space_unmap(tag, hnd, size); 800*38da497aSMark Johnston } 801*38da497aSMark Johnston 802*38da497aSMark Johnston int 803*38da497aSMark Johnston kasan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd, 804*38da497aSMark Johnston bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep) 805*38da497aSMark Johnston { 806*38da497aSMark Johnston return (bus_space_subregion(tag, hnd, offset, size, handlep)); 807*38da497aSMark Johnston } 808*38da497aSMark Johnston 809*38da497aSMark Johnston void 810*38da497aSMark Johnston kasan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd, 811*38da497aSMark Johnston bus_size_t size) 812*38da497aSMark Johnston { 813*38da497aSMark Johnston bus_space_free(tag, hnd, size); 814*38da497aSMark Johnston } 815*38da497aSMark Johnston 816*38da497aSMark Johnston void 817*38da497aSMark Johnston kasan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd, 818*38da497aSMark Johnston bus_size_t offset, bus_size_t size, int flags) 819*38da497aSMark Johnston { 820*38da497aSMark Johnston bus_space_barrier(tag, hnd, offset, size, flags); 821*38da497aSMark Johnston } 822*38da497aSMark Johnston 823*38da497aSMark Johnston #define ASAN_BUS_READ_FUNC(func, width, type) \ 824*38da497aSMark Johnston type kasan_bus_space_read##func##_##width(bus_space_tag_t tag, \ 825*38da497aSMark Johnston bus_space_handle_t hnd, bus_size_t offset) \ 826*38da497aSMark Johnston { \ 827*38da497aSMark Johnston return (bus_space_read##func##_##width(tag, hnd, \ 828*38da497aSMark Johnston offset)); \ 829*38da497aSMark Johnston } \ 830*38da497aSMark Johnston 831*38da497aSMark Johnston #define ASAN_BUS_READ_PTR_FUNC(func, width, type) \ 832*38da497aSMark Johnston void kasan_bus_space_read_##func##_##width(bus_space_tag_t tag, \ 833*38da497aSMark Johnston bus_space_handle_t hnd, bus_size_t size, type *buf, \ 834*38da497aSMark Johnston bus_size_t count) \ 835*38da497aSMark Johnston { \ 836*38da497aSMark Johnston kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\ 837*38da497aSMark Johnston false, __RET_ADDR); \ 838*38da497aSMark Johnston bus_space_read_##func##_##width(tag, hnd, size, buf, \ 839*38da497aSMark Johnston count); \ 840*38da497aSMark Johnston } 841*38da497aSMark Johnston 842*38da497aSMark Johnston ASAN_BUS_READ_FUNC(, 1, uint8_t) 843*38da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 1, uint8_t) 844*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t) 845*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t) 846*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 1, uint8_t) 847*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t) 848*38da497aSMark Johnston 849*38da497aSMark Johnston ASAN_BUS_READ_FUNC(, 2, uint16_t) 850*38da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 2, uint16_t) 851*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t) 852*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t) 853*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 2, uint16_t) 854*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t) 855*38da497aSMark Johnston 856*38da497aSMark Johnston ASAN_BUS_READ_FUNC(, 4, uint32_t) 857*38da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 4, uint32_t) 858*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t) 859*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t) 860*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 4, uint32_t) 861*38da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t) 862*38da497aSMark Johnston 863*38da497aSMark Johnston ASAN_BUS_READ_FUNC(, 8, uint64_t) 864*38da497aSMark Johnston 865*38da497aSMark Johnston #define ASAN_BUS_WRITE_FUNC(func, width, type) \ 866*38da497aSMark Johnston void kasan_bus_space_write##func##_##width(bus_space_tag_t tag, \ 867*38da497aSMark Johnston bus_space_handle_t hnd, bus_size_t offset, type value) \ 868*38da497aSMark Johnston { \ 869*38da497aSMark Johnston bus_space_write##func##_##width(tag, hnd, offset, value);\ 870*38da497aSMark Johnston } \ 871*38da497aSMark Johnston 872*38da497aSMark Johnston #define ASAN_BUS_WRITE_PTR_FUNC(func, width, type) \ 873*38da497aSMark Johnston void kasan_bus_space_write_##func##_##width(bus_space_tag_t tag,\ 874*38da497aSMark Johnston bus_space_handle_t hnd, bus_size_t size, const type *buf, \ 875*38da497aSMark Johnston bus_size_t count) \ 876*38da497aSMark Johnston { \ 877*38da497aSMark Johnston kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\ 878*38da497aSMark Johnston true, __RET_ADDR); \ 879*38da497aSMark Johnston bus_space_write_##func##_##width(tag, hnd, size, buf, \ 880*38da497aSMark Johnston count); \ 881*38da497aSMark Johnston } 882*38da497aSMark Johnston 883*38da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 1, uint8_t) 884*38da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 1, uint8_t) 885*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t) 886*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t) 887*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t) 888*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t) 889*38da497aSMark Johnston 890*38da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 2, uint16_t) 891*38da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 2, uint16_t) 892*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t) 893*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t) 894*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t) 895*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t) 896*38da497aSMark Johnston 897*38da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 4, uint32_t) 898*38da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 4, uint32_t) 899*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t) 900*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t) 901*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t) 902*38da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t) 903*38da497aSMark Johnston 904*38da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 8, uint64_t) 905*38da497aSMark Johnston 906*38da497aSMark Johnston #define ASAN_BUS_SET_FUNC(func, width, type) \ 907*38da497aSMark Johnston void kasan_bus_space_set_##func##_##width(bus_space_tag_t tag, \ 908*38da497aSMark Johnston bus_space_handle_t hnd, bus_size_t offset, type value, \ 909*38da497aSMark Johnston bus_size_t count) \ 910*38da497aSMark Johnston { \ 911*38da497aSMark Johnston bus_space_set_##func##_##width(tag, hnd, offset, value, \ 912*38da497aSMark Johnston count); \ 913*38da497aSMark Johnston } 914*38da497aSMark Johnston 915*38da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 1, uint8_t) 916*38da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 1, uint8_t) 917*38da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 1, uint8_t) 918*38da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 1, uint8_t) 919*38da497aSMark Johnston 920*38da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 2, uint16_t) 921*38da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 2, uint16_t) 922*38da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 2, uint16_t) 923*38da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 2, uint16_t) 924*38da497aSMark Johnston 925*38da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 4, uint32_t) 926*38da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 4, uint32_t) 927*38da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 4, uint32_t) 928*38da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 4, uint32_t) 929*38da497aSMark Johnston 930*38da497aSMark Johnston /* -------------------------------------------------------------------------- */ 931*38da497aSMark Johnston 932*38da497aSMark Johnston void __asan_register_globals(struct __asan_global *, size_t); 933*38da497aSMark Johnston void __asan_unregister_globals(struct __asan_global *, size_t); 934*38da497aSMark Johnston 935*38da497aSMark Johnston void 936*38da497aSMark Johnston __asan_register_globals(struct __asan_global *globals, size_t n) 937*38da497aSMark Johnston { 938*38da497aSMark Johnston size_t i; 939*38da497aSMark Johnston 940*38da497aSMark Johnston for (i = 0; i < n; i++) { 941*38da497aSMark Johnston kasan_mark(globals[i].beg, globals[i].size, 942*38da497aSMark Johnston globals[i].size_with_redzone, KASAN_GENERIC_REDZONE); 943*38da497aSMark Johnston } 944*38da497aSMark Johnston } 945*38da497aSMark Johnston 946*38da497aSMark Johnston void 947*38da497aSMark Johnston __asan_unregister_globals(struct __asan_global *globals, size_t n) 948*38da497aSMark Johnston { 949*38da497aSMark Johnston /* never called */ 950*38da497aSMark Johnston } 951*38da497aSMark Johnston 952*38da497aSMark Johnston #define ASAN_LOAD_STORE(size) \ 953*38da497aSMark Johnston void __asan_load##size(unsigned long); \ 954*38da497aSMark Johnston void __asan_load##size(unsigned long addr) \ 955*38da497aSMark Johnston { \ 956*38da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR);\ 957*38da497aSMark Johnston } \ 958*38da497aSMark Johnston void __asan_load##size##_noabort(unsigned long); \ 959*38da497aSMark Johnston void __asan_load##size##_noabort(unsigned long addr) \ 960*38da497aSMark Johnston { \ 961*38da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR);\ 962*38da497aSMark Johnston } \ 963*38da497aSMark Johnston void __asan_store##size(unsigned long); \ 964*38da497aSMark Johnston void __asan_store##size(unsigned long addr) \ 965*38da497aSMark Johnston { \ 966*38da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR);\ 967*38da497aSMark Johnston } \ 968*38da497aSMark Johnston void __asan_store##size##_noabort(unsigned long); \ 969*38da497aSMark Johnston void __asan_store##size##_noabort(unsigned long addr) \ 970*38da497aSMark Johnston { \ 971*38da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR);\ 972*38da497aSMark Johnston } 973*38da497aSMark Johnston 974*38da497aSMark Johnston ASAN_LOAD_STORE(1); 975*38da497aSMark Johnston ASAN_LOAD_STORE(2); 976*38da497aSMark Johnston ASAN_LOAD_STORE(4); 977*38da497aSMark Johnston ASAN_LOAD_STORE(8); 978*38da497aSMark Johnston ASAN_LOAD_STORE(16); 979*38da497aSMark Johnston 980*38da497aSMark Johnston void __asan_loadN(unsigned long, size_t); 981*38da497aSMark Johnston void __asan_loadN_noabort(unsigned long, size_t); 982*38da497aSMark Johnston void __asan_storeN(unsigned long, size_t); 983*38da497aSMark Johnston void __asan_storeN_noabort(unsigned long, size_t); 984*38da497aSMark Johnston void __asan_handle_no_return(void); 985*38da497aSMark Johnston 986*38da497aSMark Johnston void 987*38da497aSMark Johnston __asan_loadN(unsigned long addr, size_t size) 988*38da497aSMark Johnston { 989*38da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR); 990*38da497aSMark Johnston } 991*38da497aSMark Johnston 992*38da497aSMark Johnston void 993*38da497aSMark Johnston __asan_loadN_noabort(unsigned long addr, size_t size) 994*38da497aSMark Johnston { 995*38da497aSMark Johnston kasan_shadow_check(addr, size, false, __RET_ADDR); 996*38da497aSMark Johnston } 997*38da497aSMark Johnston 998*38da497aSMark Johnston void 999*38da497aSMark Johnston __asan_storeN(unsigned long addr, size_t size) 1000*38da497aSMark Johnston { 1001*38da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR); 1002*38da497aSMark Johnston } 1003*38da497aSMark Johnston 1004*38da497aSMark Johnston void 1005*38da497aSMark Johnston __asan_storeN_noabort(unsigned long addr, size_t size) 1006*38da497aSMark Johnston { 1007*38da497aSMark Johnston kasan_shadow_check(addr, size, true, __RET_ADDR); 1008*38da497aSMark Johnston } 1009*38da497aSMark Johnston 1010*38da497aSMark Johnston void 1011*38da497aSMark Johnston __asan_handle_no_return(void) 1012*38da497aSMark Johnston { 1013*38da497aSMark Johnston /* nothing */ 1014*38da497aSMark Johnston } 1015*38da497aSMark Johnston 1016*38da497aSMark Johnston #define ASAN_SET_SHADOW(byte) \ 1017*38da497aSMark Johnston void __asan_set_shadow_##byte(void *, size_t); \ 1018*38da497aSMark Johnston void __asan_set_shadow_##byte(void *addr, size_t size) \ 1019*38da497aSMark Johnston { \ 1020*38da497aSMark Johnston __builtin_memset((void *)addr, 0x##byte, size); \ 1021*38da497aSMark Johnston } 1022*38da497aSMark Johnston 1023*38da497aSMark Johnston ASAN_SET_SHADOW(00); 1024*38da497aSMark Johnston ASAN_SET_SHADOW(f1); 1025*38da497aSMark Johnston ASAN_SET_SHADOW(f2); 1026*38da497aSMark Johnston ASAN_SET_SHADOW(f3); 1027*38da497aSMark Johnston ASAN_SET_SHADOW(f5); 1028*38da497aSMark Johnston ASAN_SET_SHADOW(f8); 1029*38da497aSMark Johnston 1030*38da497aSMark Johnston void __asan_poison_stack_memory(const void *, size_t); 1031*38da497aSMark Johnston void __asan_unpoison_stack_memory(const void *, size_t); 1032*38da497aSMark Johnston 1033*38da497aSMark Johnston void 1034*38da497aSMark Johnston __asan_poison_stack_memory(const void *addr, size_t size) 1035*38da497aSMark Johnston { 1036*38da497aSMark Johnston size = roundup(size, KASAN_SHADOW_SCALE); 1037*38da497aSMark Johnston kasan_shadow_Nbyte_fill(addr, size, KASAN_USE_AFTER_SCOPE); 1038*38da497aSMark Johnston } 1039*38da497aSMark Johnston 1040*38da497aSMark Johnston void 1041*38da497aSMark Johnston __asan_unpoison_stack_memory(const void *addr, size_t size) 1042*38da497aSMark Johnston { 1043*38da497aSMark Johnston kasan_shadow_Nbyte_markvalid(addr, size); 1044*38da497aSMark Johnston } 1045*38da497aSMark Johnston 1046*38da497aSMark Johnston void __asan_alloca_poison(const void *, size_t); 1047*38da497aSMark Johnston void __asan_allocas_unpoison(const void *, const void *); 1048*38da497aSMark Johnston 1049*38da497aSMark Johnston void 1050*38da497aSMark Johnston __asan_alloca_poison(const void *addr, size_t size) 1051*38da497aSMark Johnston { 1052*38da497aSMark Johnston const void *l, *r; 1053*38da497aSMark Johnston 1054*38da497aSMark Johnston KASSERT((vm_offset_t)addr % KASAN_ALLOCA_SCALE_SIZE == 0, 1055*38da497aSMark Johnston ("%s: invalid address %p", __func__, addr)); 1056*38da497aSMark Johnston 1057*38da497aSMark Johnston l = (const uint8_t *)addr - KASAN_ALLOCA_SCALE_SIZE; 1058*38da497aSMark Johnston r = (const uint8_t *)addr + roundup(size, KASAN_ALLOCA_SCALE_SIZE); 1059*38da497aSMark Johnston 1060*38da497aSMark Johnston kasan_shadow_Nbyte_fill(l, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_LEFT); 1061*38da497aSMark Johnston kasan_mark(addr, size, roundup(size, KASAN_ALLOCA_SCALE_SIZE), 1062*38da497aSMark Johnston KASAN_STACK_MID); 1063*38da497aSMark Johnston kasan_shadow_Nbyte_fill(r, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_RIGHT); 1064*38da497aSMark Johnston } 1065*38da497aSMark Johnston 1066*38da497aSMark Johnston void 1067*38da497aSMark Johnston __asan_allocas_unpoison(const void *stkbegin, const void *stkend) 1068*38da497aSMark Johnston { 1069*38da497aSMark Johnston size_t size; 1070*38da497aSMark Johnston 1071*38da497aSMark Johnston if (__predict_false(!stkbegin)) 1072*38da497aSMark Johnston return; 1073*38da497aSMark Johnston if (__predict_false((uintptr_t)stkbegin > (uintptr_t)stkend)) 1074*38da497aSMark Johnston return; 1075*38da497aSMark Johnston size = (uintptr_t)stkend - (uintptr_t)stkbegin; 1076*38da497aSMark Johnston 1077*38da497aSMark Johnston kasan_shadow_Nbyte_fill(stkbegin, size, 0); 1078*38da497aSMark Johnston } 1079*38da497aSMark Johnston 1080*38da497aSMark Johnston void __asan_poison_memory_region(const void *addr, size_t size); 1081*38da497aSMark Johnston void __asan_unpoison_memory_region(const void *addr, size_t size); 1082*38da497aSMark Johnston 1083*38da497aSMark Johnston void 1084*38da497aSMark Johnston __asan_poison_memory_region(const void *addr, size_t size) 1085*38da497aSMark Johnston { 1086*38da497aSMark Johnston } 1087*38da497aSMark Johnston 1088*38da497aSMark Johnston void 1089*38da497aSMark Johnston __asan_unpoison_memory_region(const void *addr, size_t size) 1090*38da497aSMark Johnston { 1091*38da497aSMark Johnston } 1092