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