11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 21d171f95SJens Wiklander /* 31d171f95SJens Wiklander * Copyright (c) 2016, Linaro Limited 4*ebc34e0cSAleksandr Iashchenko * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net 51d171f95SJens Wiklander */ 61d171f95SJens Wiklander 71d171f95SJens Wiklander #include <assert.h> 81d171f95SJens Wiklander #include <compiler.h> 90b1d6bacSJens Wiklander #include <keep.h> 101d171f95SJens Wiklander #include <kernel/asan.h> 110b1d6bacSJens Wiklander #include <kernel/panic.h> 12c9c847d5SAleksandr Iashchenko #include <printk.h> 137749dda2SAleksandr Iashchenko #include <setjmp.h> 141d171f95SJens Wiklander #include <string.h> 150b1d6bacSJens Wiklander #include <trace.h> 161d171f95SJens Wiklander #include <types_ext.h> 171d171f95SJens Wiklander #include <util.h> 181d171f95SJens Wiklander 1957cf66e1SJens Wiklander #if __GCC_VERSION >= 70000 2057cf66e1SJens Wiklander #define ASAN_ABI_VERSION 7 2157cf66e1SJens Wiklander #else 2257cf66e1SJens Wiklander #define ASAN_ABI_VERSION 6 2357cf66e1SJens Wiklander #endif 2457cf66e1SJens Wiklander 251d171f95SJens Wiklander struct asan_source_location { 261d171f95SJens Wiklander const char *file_name; 271d171f95SJens Wiklander int line_no; 281d171f95SJens Wiklander int column_no; 291d171f95SJens Wiklander }; 301d171f95SJens Wiklander 311d171f95SJens Wiklander struct asan_global { 321d171f95SJens Wiklander uintptr_t beg; 331d171f95SJens Wiklander uintptr_t size; 341d171f95SJens Wiklander uintptr_t size_with_redzone; 351d171f95SJens Wiklander const char *name; 361d171f95SJens Wiklander const char *module_name; 371d171f95SJens Wiklander uintptr_t has_dynamic_init; 381d171f95SJens Wiklander struct asan_source_location *location; 3957cf66e1SJens Wiklander #if ASAN_ABI_VERSION >= 7 4057cf66e1SJens Wiklander uintptr_t odr_indicator; 4157cf66e1SJens Wiklander #endif 421d171f95SJens Wiklander }; 431d171f95SJens Wiklander 441d171f95SJens Wiklander static vaddr_t asan_va_base; 451d171f95SJens Wiklander static size_t asan_va_size; 461d171f95SJens Wiklander static bool asan_active; 47c9c847d5SAleksandr Iashchenko static asan_panic_cb_t asan_panic_cb = asan_panic; 481d171f95SJens Wiklander 49*ebc34e0cSAleksandr Iashchenko static bool addr_crosses_scale_boundary(vaddr_t addr, size_t size) 50*ebc34e0cSAleksandr Iashchenko { 51*ebc34e0cSAleksandr Iashchenko return (addr >> ASAN_BLOCK_SHIFT) != 52*ebc34e0cSAleksandr Iashchenko ((addr + size - 1) >> ASAN_BLOCK_SHIFT); 53*ebc34e0cSAleksandr Iashchenko } 54*ebc34e0cSAleksandr Iashchenko 55bce4951cSJens Wiklander static int8_t *va_to_shadow(const void *va) 561d171f95SJens Wiklander { 571d171f95SJens Wiklander vaddr_t sa = ((vaddr_t)va / ASAN_BLOCK_SIZE) + CFG_ASAN_SHADOW_OFFSET; 581d171f95SJens Wiklander 591d171f95SJens Wiklander return (int8_t *)sa; 601d171f95SJens Wiklander } 611d171f95SJens Wiklander 62bce4951cSJens Wiklander static size_t va_range_to_shadow_size(const void *begin, const void *end) 631d171f95SJens Wiklander { 641d171f95SJens Wiklander return ((vaddr_t)end - (vaddr_t)begin) / ASAN_BLOCK_SIZE; 651d171f95SJens Wiklander } 661d171f95SJens Wiklander 67bce4951cSJens Wiklander static bool va_range_inside_shadow(const void *begin, const void *end) 681d171f95SJens Wiklander { 691d171f95SJens Wiklander vaddr_t b = (vaddr_t)begin; 701d171f95SJens Wiklander vaddr_t e = (vaddr_t)end; 711d171f95SJens Wiklander 721d171f95SJens Wiklander if (b >= e) 731d171f95SJens Wiklander return false; 741d171f95SJens Wiklander return (b >= asan_va_base) && (e <= (asan_va_base + asan_va_size)); 751d171f95SJens Wiklander } 761d171f95SJens Wiklander 77bce4951cSJens Wiklander static bool va_range_outside_shadow(const void *begin, const void *end) 781d171f95SJens Wiklander { 791d171f95SJens Wiklander vaddr_t b = (vaddr_t)begin; 801d171f95SJens Wiklander vaddr_t e = (vaddr_t)end; 811d171f95SJens Wiklander 821d171f95SJens Wiklander if (b >= e) 831d171f95SJens Wiklander return false; 841d171f95SJens Wiklander return (e <= asan_va_base) || (b >= (asan_va_base + asan_va_size)); 851d171f95SJens Wiklander } 861d171f95SJens Wiklander 87bce4951cSJens Wiklander static size_t va_misalignment(const void *va) 881d171f95SJens Wiklander { 891d171f95SJens Wiklander return (vaddr_t)va & ASAN_BLOCK_MASK; 901d171f95SJens Wiklander } 911d171f95SJens Wiklander 92bce4951cSJens Wiklander static bool va_is_well_aligned(const void *va) 931d171f95SJens Wiklander { 941d171f95SJens Wiklander return !va_misalignment(va); 951d171f95SJens Wiklander } 961d171f95SJens Wiklander 97bce4951cSJens Wiklander void asan_set_shadowed(const void *begin, const void *end) 981d171f95SJens Wiklander { 991d171f95SJens Wiklander vaddr_t b = (vaddr_t)begin; 1001d171f95SJens Wiklander vaddr_t e = (vaddr_t)end; 1011d171f95SJens Wiklander 1021d171f95SJens Wiklander assert(!asan_va_base); 1031d171f95SJens Wiklander assert(va_is_well_aligned(begin)); 1041d171f95SJens Wiklander assert(va_is_well_aligned(end)); 1051d171f95SJens Wiklander assert(b < e); 1061d171f95SJens Wiklander 1071d171f95SJens Wiklander asan_va_base = b; 1081d171f95SJens Wiklander asan_va_size = e - b; 1091d171f95SJens Wiklander } 1101d171f95SJens Wiklander 111bce4951cSJens Wiklander void asan_tag_no_access(const void *begin, const void *end) 1121d171f95SJens Wiklander { 1131d171f95SJens Wiklander assert(va_is_well_aligned(begin)); 1141d171f95SJens Wiklander assert(va_is_well_aligned(end)); 1151d171f95SJens Wiklander assert(va_range_inside_shadow(begin, end)); 1161d171f95SJens Wiklander 117abccd909SJens Wiklander asan_memset_unchecked(va_to_shadow(begin), ASAN_DATA_RED_ZONE, 1181d171f95SJens Wiklander va_range_to_shadow_size(begin, end)); 1191d171f95SJens Wiklander } 1201d171f95SJens Wiklander 121bce4951cSJens Wiklander void asan_tag_access(const void *begin, const void *end) 1221d171f95SJens Wiklander { 12324fe8015SJens Wiklander if (!asan_va_base || (begin == end)) 1241d171f95SJens Wiklander return; 1251d171f95SJens Wiklander 1261d171f95SJens Wiklander assert(va_range_inside_shadow(begin, end)); 1271d171f95SJens Wiklander assert(va_is_well_aligned(begin)); 1281d171f95SJens Wiklander 129abccd909SJens Wiklander asan_memset_unchecked(va_to_shadow(begin), 0, 130abccd909SJens Wiklander va_range_to_shadow_size(begin, end)); 1311d171f95SJens Wiklander if (!va_is_well_aligned(end)) 132*ebc34e0cSAleksandr Iashchenko *va_to_shadow(end) = va_misalignment(end); 1331d171f95SJens Wiklander } 1341d171f95SJens Wiklander 135bce4951cSJens Wiklander void asan_tag_heap_free(const void *begin, const void *end) 1361d171f95SJens Wiklander { 1371d171f95SJens Wiklander if (!asan_va_base) 1381d171f95SJens Wiklander return; 1391d171f95SJens Wiklander 1401d171f95SJens Wiklander assert(va_range_inside_shadow(begin, end)); 1411d171f95SJens Wiklander assert(va_is_well_aligned(begin)); 1421d171f95SJens Wiklander assert(va_is_well_aligned(end)); 1431d171f95SJens Wiklander 144abccd909SJens Wiklander asan_memset_unchecked(va_to_shadow(begin), ASAN_HEAP_RED_ZONE, 1451d171f95SJens Wiklander va_range_to_shadow_size(begin, end)); 1461d171f95SJens Wiklander } 1471d171f95SJens Wiklander 1485bea6aedSJerome Forissier __inhibit_loop_to_libcall void *asan_memset_unchecked(void *s, int c, size_t n) 149abccd909SJens Wiklander { 150abccd909SJens Wiklander uint8_t *b = s; 151abccd909SJens Wiklander size_t m; 152abccd909SJens Wiklander 153abccd909SJens Wiklander for (m = 0; m < n; m++) 154abccd909SJens Wiklander b[m] = c; 155abccd909SJens Wiklander 156abccd909SJens Wiklander return s; 157abccd909SJens Wiklander } 158abccd909SJens Wiklander 1595bea6aedSJerome Forissier __inhibit_loop_to_libcall 16006fe4216SJens Wiklander void *asan_memcpy_unchecked(void *__restrict dst, const void *__restrict src, 16106fe4216SJens Wiklander size_t len) 16206fe4216SJens Wiklander { 16306fe4216SJens Wiklander uint8_t *__restrict d = dst; 16406fe4216SJens Wiklander const uint8_t *__restrict s = src; 16506fe4216SJens Wiklander size_t n; 16606fe4216SJens Wiklander 16706fe4216SJens Wiklander for (n = 0; n < len; n++) 16806fe4216SJens Wiklander d[n] = s[n]; 16906fe4216SJens Wiklander 17006fe4216SJens Wiklander return dst; 17106fe4216SJens Wiklander } 17206fe4216SJens Wiklander 1731d171f95SJens Wiklander void asan_start(void) 1741d171f95SJens Wiklander { 1751d171f95SJens Wiklander assert(asan_va_base && !asan_active); 1761d171f95SJens Wiklander asan_active = true; 1771d171f95SJens Wiklander } 1781d171f95SJens Wiklander 179c9c847d5SAleksandr Iashchenko void __noreturn asan_panic(void) 180c9c847d5SAleksandr Iashchenko { 181c9c847d5SAleksandr Iashchenko panic(); 182c9c847d5SAleksandr Iashchenko } 183c9c847d5SAleksandr Iashchenko 184c9c847d5SAleksandr Iashchenko void asan_set_panic_cb(asan_panic_cb_t panic_cb) 185c9c847d5SAleksandr Iashchenko { 186c9c847d5SAleksandr Iashchenko asan_panic_cb = panic_cb; 187c9c847d5SAleksandr Iashchenko } 188c9c847d5SAleksandr Iashchenko 189c9c847d5SAleksandr Iashchenko static void asan_report(vaddr_t addr, size_t size) 190c9c847d5SAleksandr Iashchenko { 191c9c847d5SAleksandr Iashchenko #ifdef KASAN_DUMP_SHADOW 192c9c847d5SAleksandr Iashchenko char buf[128] = {0}; 193c9c847d5SAleksandr Iashchenko int r = 0, rc = 0; 194c9c847d5SAleksandr Iashchenko vaddr_t b = 0, e = 0, saddr = 0; 195c9c847d5SAleksandr Iashchenko 196c9c847d5SAleksandr Iashchenko b = ROUNDDOWN(addr, ASAN_BLOCK_SIZE) - ASAN_BLOCK_SIZE; 197c9c847d5SAleksandr Iashchenko e = ROUNDDOWN(addr, ASAN_BLOCK_SIZE) + ASAN_BLOCK_SIZE; 198c9c847d5SAleksandr Iashchenko 199c9c847d5SAleksandr Iashchenko /* Print shadow map nearby */ 200c9c847d5SAleksandr Iashchenko if (va_range_inside_shadow((void *)b, (void *)e)) { 201c9c847d5SAleksandr Iashchenko rc = snprintk(buf + r, sizeof(buf) - r, "%lx: ", b); 202c9c847d5SAleksandr Iashchenko assert(rc > 0); 203c9c847d5SAleksandr Iashchenko r += rc; 204c9c847d5SAleksandr Iashchenko for (saddr = b; saddr <= e; saddr += ASAN_BLOCK_SIZE) { 205c9c847d5SAleksandr Iashchenko int8_t *sbyte = va_to_shadow((void *)saddr); 206c9c847d5SAleksandr Iashchenko 207c9c847d5SAleksandr Iashchenko rc = snprintk(buf + r, sizeof(buf) - r, 208c9c847d5SAleksandr Iashchenko "0x%02x ", (uint8_t)*sbyte); 209c9c847d5SAleksandr Iashchenko assert(rc > 0); 210c9c847d5SAleksandr Iashchenko r += rc; 211c9c847d5SAleksandr Iashchenko } 212c9c847d5SAleksandr Iashchenko EMSG("%s", buf); 213c9c847d5SAleksandr Iashchenko } 214c9c847d5SAleksandr Iashchenko #endif 215c9c847d5SAleksandr Iashchenko EMSG("[ASAN]: access violation, addr: %lx size: %zu\n", 216c9c847d5SAleksandr Iashchenko addr, size); 217c9c847d5SAleksandr Iashchenko 218c9c847d5SAleksandr Iashchenko asan_panic_cb(); 219c9c847d5SAleksandr Iashchenko } 220c9c847d5SAleksandr Iashchenko 221*ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_1byte_isvalid(vaddr_t addr) 2221d171f95SJens Wiklander { 223*ebc34e0cSAleksandr Iashchenko int8_t last = (addr & ASAN_BLOCK_MASK) + 1; 224*ebc34e0cSAleksandr Iashchenko int8_t *byte = va_to_shadow((void *)addr); 225*ebc34e0cSAleksandr Iashchenko 226*ebc34e0cSAleksandr Iashchenko if (*byte == 0 || last <= *byte) 227*ebc34e0cSAleksandr Iashchenko return true; 228*ebc34e0cSAleksandr Iashchenko 229*ebc34e0cSAleksandr Iashchenko return false; 230*ebc34e0cSAleksandr Iashchenko } 231*ebc34e0cSAleksandr Iashchenko 232*ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_2byte_isvalid(vaddr_t addr) 233*ebc34e0cSAleksandr Iashchenko { 234*ebc34e0cSAleksandr Iashchenko if (addr_crosses_scale_boundary(addr, 2)) { 235*ebc34e0cSAleksandr Iashchenko return (asan_shadow_1byte_isvalid(addr) && 236*ebc34e0cSAleksandr Iashchenko asan_shadow_1byte_isvalid(addr + 1)); 237*ebc34e0cSAleksandr Iashchenko } else { 238*ebc34e0cSAleksandr Iashchenko int8_t last = ((addr + 1) & ASAN_BLOCK_MASK) + 1; 239*ebc34e0cSAleksandr Iashchenko int8_t *byte = va_to_shadow((void *)addr); 240*ebc34e0cSAleksandr Iashchenko 241*ebc34e0cSAleksandr Iashchenko if (*byte == 0 || last <= *byte) 242*ebc34e0cSAleksandr Iashchenko return true; 243*ebc34e0cSAleksandr Iashchenko 244*ebc34e0cSAleksandr Iashchenko return false; 245*ebc34e0cSAleksandr Iashchenko } 246*ebc34e0cSAleksandr Iashchenko } 247*ebc34e0cSAleksandr Iashchenko 248*ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_4byte_isvalid(vaddr_t addr) 249*ebc34e0cSAleksandr Iashchenko { 250*ebc34e0cSAleksandr Iashchenko if (addr_crosses_scale_boundary(addr, 4)) { 251*ebc34e0cSAleksandr Iashchenko return (asan_shadow_2byte_isvalid(addr) && 252*ebc34e0cSAleksandr Iashchenko asan_shadow_2byte_isvalid(addr + 2)); 253*ebc34e0cSAleksandr Iashchenko } else { 254*ebc34e0cSAleksandr Iashchenko int8_t last = ((addr + 3) & ASAN_BLOCK_MASK) + 1; 255*ebc34e0cSAleksandr Iashchenko int8_t *byte = va_to_shadow((void *)addr); 256*ebc34e0cSAleksandr Iashchenko 257*ebc34e0cSAleksandr Iashchenko if (*byte == 0 || last <= *byte) 258*ebc34e0cSAleksandr Iashchenko return true; 259*ebc34e0cSAleksandr Iashchenko 260*ebc34e0cSAleksandr Iashchenko return false; 261*ebc34e0cSAleksandr Iashchenko } 262*ebc34e0cSAleksandr Iashchenko } 263*ebc34e0cSAleksandr Iashchenko 264*ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_8byte_isvalid(vaddr_t addr) 265*ebc34e0cSAleksandr Iashchenko { 266*ebc34e0cSAleksandr Iashchenko if (addr_crosses_scale_boundary(addr, 8)) { 267*ebc34e0cSAleksandr Iashchenko return (asan_shadow_4byte_isvalid(addr) && 268*ebc34e0cSAleksandr Iashchenko asan_shadow_4byte_isvalid(addr + 4)); 269*ebc34e0cSAleksandr Iashchenko } else { 270*ebc34e0cSAleksandr Iashchenko int8_t last = ((addr + 7) & ASAN_BLOCK_MASK) + 1; 271*ebc34e0cSAleksandr Iashchenko int8_t *byte = va_to_shadow((void *)addr); 272*ebc34e0cSAleksandr Iashchenko 273*ebc34e0cSAleksandr Iashchenko if (*byte == 0 || last <= *byte) 274*ebc34e0cSAleksandr Iashchenko return true; 275*ebc34e0cSAleksandr Iashchenko 276*ebc34e0cSAleksandr Iashchenko return false; 277*ebc34e0cSAleksandr Iashchenko } 278*ebc34e0cSAleksandr Iashchenko } 279*ebc34e0cSAleksandr Iashchenko 280*ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_Nbyte_isvalid(vaddr_t addr, 281*ebc34e0cSAleksandr Iashchenko size_t size) 282*ebc34e0cSAleksandr Iashchenko { 283*ebc34e0cSAleksandr Iashchenko size_t i = 0; 284*ebc34e0cSAleksandr Iashchenko 285*ebc34e0cSAleksandr Iashchenko for (; i < size; i++) { 286*ebc34e0cSAleksandr Iashchenko if (!asan_shadow_1byte_isvalid(addr + i)) 287*ebc34e0cSAleksandr Iashchenko return false; 288*ebc34e0cSAleksandr Iashchenko } 289*ebc34e0cSAleksandr Iashchenko 290*ebc34e0cSAleksandr Iashchenko return true; 291*ebc34e0cSAleksandr Iashchenko } 292*ebc34e0cSAleksandr Iashchenko 293*ebc34e0cSAleksandr Iashchenko static __always_inline void check_access(vaddr_t addr, size_t size) 294*ebc34e0cSAleksandr Iashchenko { 295*ebc34e0cSAleksandr Iashchenko bool valid = false; 2961d171f95SJens Wiklander void *begin = (void *)addr; 2971d171f95SJens Wiklander void *end = (void *)(addr + size); 2981d171f95SJens Wiklander 299*ebc34e0cSAleksandr Iashchenko if (!asan_active) 300*ebc34e0cSAleksandr Iashchenko return; 301*ebc34e0cSAleksandr Iashchenko if (size == 0) 3021d171f95SJens Wiklander return; 3031d171f95SJens Wiklander if (va_range_outside_shadow(begin, end)) 3041d171f95SJens Wiklander return; 3051d171f95SJens Wiklander /* 3061d171f95SJens Wiklander * If it isn't outside it has to be completely inside or there's a 3071d171f95SJens Wiklander * problem. 3081d171f95SJens Wiklander */ 3091d171f95SJens Wiklander if (!va_range_inside_shadow(begin, end)) 3101d171f95SJens Wiklander panic(); 3111d171f95SJens Wiklander 312*ebc34e0cSAleksandr Iashchenko if (__builtin_constant_p(size)) { 313*ebc34e0cSAleksandr Iashchenko switch (size) { 314*ebc34e0cSAleksandr Iashchenko case 1: 315*ebc34e0cSAleksandr Iashchenko valid = asan_shadow_1byte_isvalid(addr); 316*ebc34e0cSAleksandr Iashchenko break; 317*ebc34e0cSAleksandr Iashchenko case 2: 318*ebc34e0cSAleksandr Iashchenko valid = asan_shadow_2byte_isvalid(addr); 319*ebc34e0cSAleksandr Iashchenko break; 320*ebc34e0cSAleksandr Iashchenko case 4: 321*ebc34e0cSAleksandr Iashchenko valid = asan_shadow_4byte_isvalid(addr); 322*ebc34e0cSAleksandr Iashchenko break; 323*ebc34e0cSAleksandr Iashchenko case 8: 324*ebc34e0cSAleksandr Iashchenko valid = asan_shadow_8byte_isvalid(addr); 325*ebc34e0cSAleksandr Iashchenko break; 326*ebc34e0cSAleksandr Iashchenko default: 327*ebc34e0cSAleksandr Iashchenko valid = asan_shadow_Nbyte_isvalid(addr, size); 328*ebc34e0cSAleksandr Iashchenko break; 329*ebc34e0cSAleksandr Iashchenko } 330*ebc34e0cSAleksandr Iashchenko } else { 331*ebc34e0cSAleksandr Iashchenko valid = asan_shadow_Nbyte_isvalid(addr, size); 332*ebc34e0cSAleksandr Iashchenko } 3331d171f95SJens Wiklander 334*ebc34e0cSAleksandr Iashchenko if (!valid) 335c9c847d5SAleksandr Iashchenko asan_report(addr, size); 3361d171f95SJens Wiklander } 3371d171f95SJens Wiklander 338*ebc34e0cSAleksandr Iashchenko static __always_inline void check_load(vaddr_t addr, size_t size) 3391d171f95SJens Wiklander { 3401d171f95SJens Wiklander check_access(addr, size); 3411d171f95SJens Wiklander } 3421d171f95SJens Wiklander 343*ebc34e0cSAleksandr Iashchenko static __always_inline void check_store(vaddr_t addr, size_t size) 3441d171f95SJens Wiklander { 3451d171f95SJens Wiklander check_access(addr, size); 3461d171f95SJens Wiklander } 3471d171f95SJens Wiklander 3481d171f95SJens Wiklander static void __noreturn report_load(vaddr_t addr __unused, size_t size __unused) 3491d171f95SJens Wiklander { 3501d171f95SJens Wiklander panic(); 3511d171f95SJens Wiklander } 3521d171f95SJens Wiklander 3531d171f95SJens Wiklander static void __noreturn report_store(vaddr_t addr __unused, size_t size __unused) 3541d171f95SJens Wiklander { 3551d171f95SJens Wiklander panic(); 3561d171f95SJens Wiklander } 3571d171f95SJens Wiklander 3581d171f95SJens Wiklander 3591d171f95SJens Wiklander 3601d171f95SJens Wiklander #define DEFINE_ASAN_FUNC(type, size) \ 3611d171f95SJens Wiklander void __asan_##type##size(vaddr_t addr); \ 3621d171f95SJens Wiklander void __asan_##type##size(vaddr_t addr) \ 3631d171f95SJens Wiklander { check_##type(addr, size); } \ 3641d171f95SJens Wiklander void __asan_##type##size##_noabort(vaddr_t addr); \ 3651d171f95SJens Wiklander void __asan_##type##size##_noabort(vaddr_t addr) \ 3661d171f95SJens Wiklander { check_##type(addr, size); } \ 3671d171f95SJens Wiklander void __asan_report_##type##size##_noabort(vaddr_t addr);\ 3681d171f95SJens Wiklander void __noreturn __asan_report_##type##size##_noabort(vaddr_t addr) \ 3691d171f95SJens Wiklander { report_##type(addr, size); } 3701d171f95SJens Wiklander 3711d171f95SJens Wiklander DEFINE_ASAN_FUNC(load, 1) 3721d171f95SJens Wiklander DEFINE_ASAN_FUNC(load, 2) 3731d171f95SJens Wiklander DEFINE_ASAN_FUNC(load, 4) 3741d171f95SJens Wiklander DEFINE_ASAN_FUNC(load, 8) 3751d171f95SJens Wiklander DEFINE_ASAN_FUNC(load, 16) 3761d171f95SJens Wiklander DEFINE_ASAN_FUNC(store, 1) 3771d171f95SJens Wiklander DEFINE_ASAN_FUNC(store, 2) 3781d171f95SJens Wiklander DEFINE_ASAN_FUNC(store, 4) 3791d171f95SJens Wiklander DEFINE_ASAN_FUNC(store, 8) 3801d171f95SJens Wiklander DEFINE_ASAN_FUNC(store, 16) 3811d171f95SJens Wiklander 3821d171f95SJens Wiklander void __asan_loadN_noabort(vaddr_t addr, size_t size); 3831d171f95SJens Wiklander void __asan_loadN_noabort(vaddr_t addr, size_t size) 3841d171f95SJens Wiklander { 3851d171f95SJens Wiklander check_load(addr, size); 3861d171f95SJens Wiklander } 3871d171f95SJens Wiklander 3881d171f95SJens Wiklander void __asan_storeN_noabort(vaddr_t addr, size_t size); 3891d171f95SJens Wiklander void __asan_storeN_noabort(vaddr_t addr, size_t size) 3901d171f95SJens Wiklander { 3911d171f95SJens Wiklander check_store(addr, size); 3921d171f95SJens Wiklander } 3931d171f95SJens Wiklander 3941d171f95SJens Wiklander void __asan_report_load_n_noabort(vaddr_t addr, size_t size); 3951d171f95SJens Wiklander void __noreturn __asan_report_load_n_noabort(vaddr_t addr, size_t size) 3961d171f95SJens Wiklander { 3971d171f95SJens Wiklander report_load(addr, size); 3981d171f95SJens Wiklander } 3991d171f95SJens Wiklander 4001d171f95SJens Wiklander void __asan_report_store_n_noabort(vaddr_t addr, size_t size); 4011d171f95SJens Wiklander void __noreturn __asan_report_store_n_noabort(vaddr_t addr, size_t size) 4021d171f95SJens Wiklander { 4031d171f95SJens Wiklander report_store(addr, size); 4041d171f95SJens Wiklander } 4051d171f95SJens Wiklander 4061d171f95SJens Wiklander void __asan_handle_no_return(void); 407ce553c81SJens Wiklander void __asan_handle_no_return(void) 4081d171f95SJens Wiklander { 4091d171f95SJens Wiklander } 4101d171f95SJens Wiklander 4111d171f95SJens Wiklander void __asan_register_globals(struct asan_global *globals, size_t size); 4121d171f95SJens Wiklander void __asan_register_globals(struct asan_global *globals, size_t size) 4131d171f95SJens Wiklander { 4141d171f95SJens Wiklander size_t n; 4151d171f95SJens Wiklander 4161d171f95SJens Wiklander for (n = 0; n < size; n++) 4171d171f95SJens Wiklander asan_tag_access((void *)globals[n].beg, 4181d171f95SJens Wiklander (void *)(globals[n].beg + globals[n].size)); 4191d171f95SJens Wiklander } 4203639b55fSJerome Forissier DECLARE_KEEP_INIT(__asan_register_globals); 4211d171f95SJens Wiklander 4221d171f95SJens Wiklander void __asan_unregister_globals(struct asan_global *globals, size_t size); 4231d171f95SJens Wiklander void __asan_unregister_globals(struct asan_global *globals __unused, 4241d171f95SJens Wiklander size_t size __unused) 4251d171f95SJens Wiklander { 4261d171f95SJens Wiklander } 4277749dda2SAleksandr Iashchenko 4287749dda2SAleksandr Iashchenko void asan_handle_longjmp(void *old_sp) 4297749dda2SAleksandr Iashchenko { 4307749dda2SAleksandr Iashchenko void *top = old_sp; 4317749dda2SAleksandr Iashchenko void *bottom = (void *)ROUNDDOWN((vaddr_t)&top, 4327749dda2SAleksandr Iashchenko ASAN_BLOCK_SIZE); 4337749dda2SAleksandr Iashchenko 4347749dda2SAleksandr Iashchenko asan_tag_access(bottom, top); 4357749dda2SAleksandr Iashchenko } 436