11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
21d171f95SJens Wiklander /*
31d171f95SJens Wiklander * Copyright (c) 2016, Linaro Limited
4ebc34e0cSAleksandr 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
addr_crosses_scale_boundary(vaddr_t addr,size_t size)49ebc34e0cSAleksandr Iashchenko static bool addr_crosses_scale_boundary(vaddr_t addr, size_t size)
50ebc34e0cSAleksandr Iashchenko {
51ebc34e0cSAleksandr Iashchenko return (addr >> ASAN_BLOCK_SHIFT) !=
52ebc34e0cSAleksandr Iashchenko ((addr + size - 1) >> ASAN_BLOCK_SHIFT);
53ebc34e0cSAleksandr Iashchenko }
54ebc34e0cSAleksandr Iashchenko
va_to_shadow(const void * va)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
va_range_to_shadow_size(const void * begin,const void * end)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
va_range_inside_shadow(const void * begin,const void * end)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
va_range_outside_shadow(const void * begin,const void * end)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
va_misalignment(const void * va)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
va_is_well_aligned(const void * va)92bce4951cSJens Wiklander static bool va_is_well_aligned(const void *va)
931d171f95SJens Wiklander {
941d171f95SJens Wiklander return !va_misalignment(va);
951d171f95SJens Wiklander }
961d171f95SJens Wiklander
asan_set_shadowed(const void * begin,const void * end)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
asan_tag_no_access(const void * begin,const void * end)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
asan_tag_access(const void * begin,const void * end)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))
132ebc34e0cSAleksandr Iashchenko *va_to_shadow(end) = va_misalignment(end);
1331d171f95SJens Wiklander }
1341d171f95SJens Wiklander
asan_tag_heap_free(const void * begin,const void * end)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
asan_memset_unchecked(void * s,int c,size_t n)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
asan_memcpy_unchecked(void * __restrict dst,const void * __restrict src,size_t len)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
asan_start(void)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
asan_panic(void)179c9c847d5SAleksandr Iashchenko void __noreturn asan_panic(void)
180c9c847d5SAleksandr Iashchenko {
181c9c847d5SAleksandr Iashchenko panic();
182c9c847d5SAleksandr Iashchenko }
183c9c847d5SAleksandr Iashchenko
asan_set_panic_cb(asan_panic_cb_t panic_cb)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
asan_report(vaddr_t addr,size_t size)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
asan_shadow_1byte_isvalid(vaddr_t addr)221ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_1byte_isvalid(vaddr_t addr)
2221d171f95SJens Wiklander {
223ebc34e0cSAleksandr Iashchenko int8_t last = (addr & ASAN_BLOCK_MASK) + 1;
224ebc34e0cSAleksandr Iashchenko int8_t *byte = va_to_shadow((void *)addr);
225ebc34e0cSAleksandr Iashchenko
226ebc34e0cSAleksandr Iashchenko if (*byte == 0 || last <= *byte)
227ebc34e0cSAleksandr Iashchenko return true;
228ebc34e0cSAleksandr Iashchenko
229ebc34e0cSAleksandr Iashchenko return false;
230ebc34e0cSAleksandr Iashchenko }
231ebc34e0cSAleksandr Iashchenko
asan_shadow_2byte_isvalid(vaddr_t addr)232ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_2byte_isvalid(vaddr_t addr)
233ebc34e0cSAleksandr Iashchenko {
234ebc34e0cSAleksandr Iashchenko if (addr_crosses_scale_boundary(addr, 2)) {
235ebc34e0cSAleksandr Iashchenko return (asan_shadow_1byte_isvalid(addr) &&
236ebc34e0cSAleksandr Iashchenko asan_shadow_1byte_isvalid(addr + 1));
237ebc34e0cSAleksandr Iashchenko } else {
238ebc34e0cSAleksandr Iashchenko int8_t last = ((addr + 1) & ASAN_BLOCK_MASK) + 1;
239ebc34e0cSAleksandr Iashchenko int8_t *byte = va_to_shadow((void *)addr);
240ebc34e0cSAleksandr Iashchenko
241ebc34e0cSAleksandr Iashchenko if (*byte == 0 || last <= *byte)
242ebc34e0cSAleksandr Iashchenko return true;
243ebc34e0cSAleksandr Iashchenko
244ebc34e0cSAleksandr Iashchenko return false;
245ebc34e0cSAleksandr Iashchenko }
246ebc34e0cSAleksandr Iashchenko }
247ebc34e0cSAleksandr Iashchenko
asan_shadow_4byte_isvalid(vaddr_t addr)248ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_4byte_isvalid(vaddr_t addr)
249ebc34e0cSAleksandr Iashchenko {
250ebc34e0cSAleksandr Iashchenko if (addr_crosses_scale_boundary(addr, 4)) {
251ebc34e0cSAleksandr Iashchenko return (asan_shadow_2byte_isvalid(addr) &&
252ebc34e0cSAleksandr Iashchenko asan_shadow_2byte_isvalid(addr + 2));
253ebc34e0cSAleksandr Iashchenko } else {
254ebc34e0cSAleksandr Iashchenko int8_t last = ((addr + 3) & ASAN_BLOCK_MASK) + 1;
255ebc34e0cSAleksandr Iashchenko int8_t *byte = va_to_shadow((void *)addr);
256ebc34e0cSAleksandr Iashchenko
257ebc34e0cSAleksandr Iashchenko if (*byte == 0 || last <= *byte)
258ebc34e0cSAleksandr Iashchenko return true;
259ebc34e0cSAleksandr Iashchenko
260ebc34e0cSAleksandr Iashchenko return false;
261ebc34e0cSAleksandr Iashchenko }
262ebc34e0cSAleksandr Iashchenko }
263ebc34e0cSAleksandr Iashchenko
asan_shadow_8byte_isvalid(vaddr_t addr)264ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_8byte_isvalid(vaddr_t addr)
265ebc34e0cSAleksandr Iashchenko {
266ebc34e0cSAleksandr Iashchenko if (addr_crosses_scale_boundary(addr, 8)) {
267ebc34e0cSAleksandr Iashchenko return (asan_shadow_4byte_isvalid(addr) &&
268ebc34e0cSAleksandr Iashchenko asan_shadow_4byte_isvalid(addr + 4));
269ebc34e0cSAleksandr Iashchenko } else {
270ebc34e0cSAleksandr Iashchenko int8_t last = ((addr + 7) & ASAN_BLOCK_MASK) + 1;
271ebc34e0cSAleksandr Iashchenko int8_t *byte = va_to_shadow((void *)addr);
272ebc34e0cSAleksandr Iashchenko
273ebc34e0cSAleksandr Iashchenko if (*byte == 0 || last <= *byte)
274ebc34e0cSAleksandr Iashchenko return true;
275ebc34e0cSAleksandr Iashchenko
276ebc34e0cSAleksandr Iashchenko return false;
277ebc34e0cSAleksandr Iashchenko }
278ebc34e0cSAleksandr Iashchenko }
279ebc34e0cSAleksandr Iashchenko
asan_shadow_Nbyte_isvalid(vaddr_t addr,size_t size)280ebc34e0cSAleksandr Iashchenko static __always_inline bool asan_shadow_Nbyte_isvalid(vaddr_t addr,
281ebc34e0cSAleksandr Iashchenko size_t size)
282ebc34e0cSAleksandr Iashchenko {
283ebc34e0cSAleksandr Iashchenko size_t i = 0;
284ebc34e0cSAleksandr Iashchenko
285ebc34e0cSAleksandr Iashchenko for (; i < size; i++) {
286ebc34e0cSAleksandr Iashchenko if (!asan_shadow_1byte_isvalid(addr + i))
287ebc34e0cSAleksandr Iashchenko return false;
288ebc34e0cSAleksandr Iashchenko }
289ebc34e0cSAleksandr Iashchenko
290ebc34e0cSAleksandr Iashchenko return true;
291ebc34e0cSAleksandr Iashchenko }
292ebc34e0cSAleksandr Iashchenko
check_access(vaddr_t addr,size_t size)293ebc34e0cSAleksandr Iashchenko static __always_inline void check_access(vaddr_t addr, size_t size)
294ebc34e0cSAleksandr Iashchenko {
295ebc34e0cSAleksandr Iashchenko bool valid = false;
2961d171f95SJens Wiklander void *begin = (void *)addr;
2971d171f95SJens Wiklander void *end = (void *)(addr + size);
2981d171f95SJens Wiklander
299ebc34e0cSAleksandr Iashchenko if (!asan_active)
300ebc34e0cSAleksandr Iashchenko return;
301ebc34e0cSAleksandr 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
312ebc34e0cSAleksandr Iashchenko if (__builtin_constant_p(size)) {
313ebc34e0cSAleksandr Iashchenko switch (size) {
314ebc34e0cSAleksandr Iashchenko case 1:
315ebc34e0cSAleksandr Iashchenko valid = asan_shadow_1byte_isvalid(addr);
316ebc34e0cSAleksandr Iashchenko break;
317ebc34e0cSAleksandr Iashchenko case 2:
318ebc34e0cSAleksandr Iashchenko valid = asan_shadow_2byte_isvalid(addr);
319ebc34e0cSAleksandr Iashchenko break;
320ebc34e0cSAleksandr Iashchenko case 4:
321ebc34e0cSAleksandr Iashchenko valid = asan_shadow_4byte_isvalid(addr);
322ebc34e0cSAleksandr Iashchenko break;
323ebc34e0cSAleksandr Iashchenko case 8:
324ebc34e0cSAleksandr Iashchenko valid = asan_shadow_8byte_isvalid(addr);
325ebc34e0cSAleksandr Iashchenko break;
326ebc34e0cSAleksandr Iashchenko default:
327ebc34e0cSAleksandr Iashchenko valid = asan_shadow_Nbyte_isvalid(addr, size);
328ebc34e0cSAleksandr Iashchenko break;
329ebc34e0cSAleksandr Iashchenko }
330ebc34e0cSAleksandr Iashchenko } else {
331ebc34e0cSAleksandr Iashchenko valid = asan_shadow_Nbyte_isvalid(addr, size);
332ebc34e0cSAleksandr Iashchenko }
3331d171f95SJens Wiklander
334ebc34e0cSAleksandr Iashchenko if (!valid)
335c9c847d5SAleksandr Iashchenko asan_report(addr, size);
3361d171f95SJens Wiklander }
3371d171f95SJens Wiklander
check_load(vaddr_t addr,size_t size)338ebc34e0cSAleksandr 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
check_store(vaddr_t addr,size_t size)343ebc34e0cSAleksandr 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
report_load(vaddr_t addr __unused,size_t size __unused)3481d171f95SJens Wiklander static void __noreturn report_load(vaddr_t addr __unused, size_t size __unused)
3491d171f95SJens Wiklander {
3501d171f95SJens Wiklander panic();
3511d171f95SJens Wiklander }
3521d171f95SJens Wiklander
report_store(vaddr_t addr __unused,size_t size __unused)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);
__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);
__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);
__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);
__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);
__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);
__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 {
414*fb3aa7b0SAleksandr Iashchenko size_t n = 0;
4151d171f95SJens Wiklander
416*fb3aa7b0SAleksandr Iashchenko for (n = 0; n < size; n++) {
417*fb3aa7b0SAleksandr Iashchenko vaddr_t begin = globals[n].beg;
418*fb3aa7b0SAleksandr Iashchenko vaddr_t end = begin + globals[n].size;
419*fb3aa7b0SAleksandr Iashchenko vaddr_t end_align = ROUNDUP(end, ASAN_BLOCK_SIZE);
420*fb3aa7b0SAleksandr Iashchenko vaddr_t end_rz = begin + globals[n].size_with_redzone;
421*fb3aa7b0SAleksandr Iashchenko
422*fb3aa7b0SAleksandr Iashchenko asan_tag_access((void *)begin, (void *)end);
423*fb3aa7b0SAleksandr Iashchenko asan_tag_no_access((void *)end_align, (void *)end_rz);
424*fb3aa7b0SAleksandr Iashchenko }
4251d171f95SJens Wiklander }
4263639b55fSJerome Forissier DECLARE_KEEP_INIT(__asan_register_globals);
4271d171f95SJens Wiklander
4281d171f95SJens Wiklander void __asan_unregister_globals(struct asan_global *globals, size_t size);
__asan_unregister_globals(struct asan_global * globals __unused,size_t size __unused)4291d171f95SJens Wiklander void __asan_unregister_globals(struct asan_global *globals __unused,
4301d171f95SJens Wiklander size_t size __unused)
4311d171f95SJens Wiklander {
4321d171f95SJens Wiklander }
4337749dda2SAleksandr Iashchenko
asan_handle_longjmp(void * old_sp)4347749dda2SAleksandr Iashchenko void asan_handle_longjmp(void *old_sp)
4357749dda2SAleksandr Iashchenko {
4367749dda2SAleksandr Iashchenko void *top = old_sp;
4377749dda2SAleksandr Iashchenko void *bottom = (void *)ROUNDDOWN((vaddr_t)&top,
4387749dda2SAleksandr Iashchenko ASAN_BLOCK_SIZE);
4397749dda2SAleksandr Iashchenko
4407749dda2SAleksandr Iashchenko asan_tag_access(bottom, top);
4417749dda2SAleksandr Iashchenko }
442