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