xref: /freebsd/sys/kern/subr_asan.c (revision 35eb9b10c265a27ce1f80a6eb74887240c7f4305)
138da497aSMark Johnston /*	$NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $	*/
238da497aSMark Johnston 
338da497aSMark Johnston /*
438da497aSMark Johnston  * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net
538da497aSMark Johnston  * All rights reserved.
638da497aSMark Johnston  *
738da497aSMark Johnston  * This code is part of the KASAN subsystem of the NetBSD kernel.
838da497aSMark Johnston  *
938da497aSMark Johnston  * Redistribution and use in source and binary forms, with or without
1038da497aSMark Johnston  * modification, are permitted provided that the following conditions
1138da497aSMark Johnston  * are met:
1238da497aSMark Johnston  * 1. Redistributions of source code must retain the above copyright
1338da497aSMark Johnston  *    notice, this list of conditions and the following disclaimer.
1438da497aSMark Johnston  * 2. Redistributions in binary form must reproduce the above copyright
1538da497aSMark Johnston  *    notice, this list of conditions and the following disclaimer in the
1638da497aSMark Johnston  *    documentation and/or other materials provided with the distribution.
1738da497aSMark Johnston  *
1838da497aSMark Johnston  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1938da497aSMark Johnston  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2038da497aSMark Johnston  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2138da497aSMark Johnston  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2238da497aSMark Johnston  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2338da497aSMark Johnston  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2438da497aSMark Johnston  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2538da497aSMark Johnston  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2638da497aSMark Johnston  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2738da497aSMark Johnston  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2838da497aSMark Johnston  * SUCH DAMAGE.
2938da497aSMark Johnston  */
3038da497aSMark Johnston 
3138da497aSMark Johnston #define	SAN_RUNTIME
3238da497aSMark Johnston 
3338da497aSMark Johnston #include <sys/cdefs.h>
3438da497aSMark Johnston __FBSDID("$FreeBSD$");
3538da497aSMark Johnston #if 0
3638da497aSMark Johnston __KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $");
3738da497aSMark Johnston #endif
3838da497aSMark Johnston 
3938da497aSMark Johnston #include <sys/param.h>
4038da497aSMark Johnston #include <sys/systm.h>
4138da497aSMark Johnston #include <sys/asan.h>
4238da497aSMark Johnston #include <sys/kernel.h>
4338da497aSMark Johnston #include <sys/stack.h>
4438da497aSMark Johnston #include <sys/sysctl.h>
4538da497aSMark Johnston 
4638da497aSMark Johnston #include <machine/asan.h>
4738da497aSMark Johnston 
4838da497aSMark Johnston /* ASAN constants. Part of the compiler ABI. */
4938da497aSMark Johnston #define KASAN_SHADOW_MASK		(KASAN_SHADOW_SCALE - 1)
5038da497aSMark Johnston #define KASAN_ALLOCA_SCALE_SIZE		32
5138da497aSMark Johnston 
5238da497aSMark Johnston /* ASAN ABI version. */
5338da497aSMark Johnston #if defined(__clang__) && (__clang_major__ - 0 >= 6)
5438da497aSMark Johnston #define ASAN_ABI_VERSION	8
5538da497aSMark Johnston #elif __GNUC_PREREQ__(7, 1) && !defined(__clang__)
5638da497aSMark Johnston #define ASAN_ABI_VERSION	8
5738da497aSMark Johnston #elif __GNUC_PREREQ__(6, 1) && !defined(__clang__)
5838da497aSMark Johnston #define ASAN_ABI_VERSION	6
5938da497aSMark Johnston #else
6038da497aSMark Johnston #error "Unsupported compiler version"
6138da497aSMark Johnston #endif
6238da497aSMark Johnston 
6338da497aSMark Johnston #define __RET_ADDR	(unsigned long)__builtin_return_address(0)
6438da497aSMark Johnston 
6538da497aSMark Johnston /* Global variable descriptor. Part of the compiler ABI.  */
6638da497aSMark Johnston struct __asan_global_source_location {
6738da497aSMark Johnston 	const char *filename;
6838da497aSMark Johnston 	int line_no;
6938da497aSMark Johnston 	int column_no;
7038da497aSMark Johnston };
7138da497aSMark Johnston 
7238da497aSMark Johnston struct __asan_global {
7338da497aSMark Johnston 	const void *beg;		/* address of the global variable */
7438da497aSMark Johnston 	size_t size;			/* size of the global variable */
7538da497aSMark Johnston 	size_t size_with_redzone;	/* size with the redzone */
7638da497aSMark Johnston 	const void *name;		/* name of the variable */
7738da497aSMark Johnston 	const void *module_name;	/* name of the module where the var is declared */
7838da497aSMark Johnston 	unsigned long has_dynamic_init;	/* the var has dyn initializer (c++) */
7938da497aSMark Johnston 	struct __asan_global_source_location *location;
8038da497aSMark Johnston #if ASAN_ABI_VERSION >= 7
8138da497aSMark Johnston 	uintptr_t odr_indicator;	/* the address of the ODR indicator symbol */
8238da497aSMark Johnston #endif
8338da497aSMark Johnston };
8438da497aSMark Johnston 
8538da497aSMark Johnston FEATURE(kasan, "Kernel address sanitizer");
8638da497aSMark Johnston 
8738da497aSMark Johnston static SYSCTL_NODE(_debug, OID_AUTO, kasan, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
8838da497aSMark Johnston     "KASAN options");
8938da497aSMark Johnston 
9038da497aSMark Johnston static int panic_on_violation = 1;
9138da497aSMark Johnston SYSCTL_INT(_debug_kasan, OID_AUTO, panic_on_violation, CTLFLAG_RDTUN,
9238da497aSMark Johnston     &panic_on_violation, 0,
9338da497aSMark Johnston     "Panic if an invalid access is detected");
9438da497aSMark Johnston 
9538da497aSMark Johnston static bool kasan_enabled __read_mostly = false;
9638da497aSMark Johnston 
9738da497aSMark Johnston /* -------------------------------------------------------------------------- */
9838da497aSMark Johnston 
9938da497aSMark Johnston void
10020e3b9d8SMark Johnston kasan_shadow_map(vm_offset_t addr, size_t size)
10138da497aSMark Johnston {
10238da497aSMark Johnston 	size_t sz, npages, i;
10338da497aSMark Johnston 	vm_offset_t sva, eva;
10438da497aSMark Johnston 
10520e3b9d8SMark Johnston 	KASSERT(addr % KASAN_SHADOW_SCALE == 0,
10620e3b9d8SMark Johnston 	    ("%s: invalid address %#lx", __func__, addr));
10738da497aSMark Johnston 
10838da497aSMark Johnston 	sz = roundup(size, KASAN_SHADOW_SCALE) / KASAN_SHADOW_SCALE;
10938da497aSMark Johnston 
11020e3b9d8SMark Johnston 	sva = kasan_md_addr_to_shad(addr);
11120e3b9d8SMark Johnston 	eva = kasan_md_addr_to_shad(addr) + sz;
11238da497aSMark Johnston 
11338da497aSMark Johnston 	sva = rounddown(sva, PAGE_SIZE);
11438da497aSMark Johnston 	eva = roundup(eva, PAGE_SIZE);
11538da497aSMark Johnston 
11638da497aSMark Johnston 	npages = (eva - sva) / PAGE_SIZE;
11738da497aSMark Johnston 
11838da497aSMark Johnston 	KASSERT(sva >= KASAN_MIN_ADDRESS && eva < KASAN_MAX_ADDRESS,
11938da497aSMark Johnston 	    ("%s: invalid address range %#lx-%#lx", __func__, sva, eva));
12038da497aSMark Johnston 
12138da497aSMark Johnston 	for (i = 0; i < npages; i++)
122175d3380SMark Johnston 		pmap_san_enter(sva + ptoa(i));
12338da497aSMark Johnston }
12438da497aSMark Johnston 
12538da497aSMark Johnston void
12638da497aSMark Johnston kasan_init(void)
12738da497aSMark Johnston {
12838da497aSMark Johnston 	int disabled;
12938da497aSMark Johnston 
13038da497aSMark Johnston 	disabled = 0;
13138da497aSMark Johnston 	TUNABLE_INT_FETCH("debug.kasan.disabled", &disabled);
13238da497aSMark Johnston 	if (disabled)
13338da497aSMark Johnston 		return;
13438da497aSMark Johnston 
13538da497aSMark Johnston 	/* MD initialization. */
13638da497aSMark Johnston 	kasan_md_init();
13738da497aSMark Johnston 
13838da497aSMark Johnston 	/* Now officially enabled. */
13938da497aSMark Johnston 	kasan_enabled = true;
14038da497aSMark Johnston }
14138da497aSMark Johnston 
14238da497aSMark Johnston static inline const char *
14338da497aSMark Johnston kasan_code_name(uint8_t code)
14438da497aSMark Johnston {
14538da497aSMark Johnston 	switch (code) {
14638da497aSMark Johnston 	case KASAN_GENERIC_REDZONE:
14738da497aSMark Johnston 		return "GenericRedZone";
14838da497aSMark Johnston 	case KASAN_MALLOC_REDZONE:
14938da497aSMark Johnston 		return "MallocRedZone";
15038da497aSMark Johnston 	case KASAN_KMEM_REDZONE:
15138da497aSMark Johnston 		return "KmemRedZone";
15238da497aSMark Johnston 	case KASAN_UMA_FREED:
15338da497aSMark Johnston 		return "UMAUseAfterFree";
15438da497aSMark Johnston 	case KASAN_KSTACK_FREED:
15538da497aSMark Johnston 		return "KernelStack";
156f1c3adefSMark Johnston 	case KASAN_EXEC_ARGS_FREED:
157f1c3adefSMark Johnston 		return "ExecKVA";
15838da497aSMark Johnston 	case 1 ... 7:
15938da497aSMark Johnston 		return "RedZonePartial";
16038da497aSMark Johnston 	case KASAN_STACK_LEFT:
16138da497aSMark Johnston 		return "StackLeft";
16238da497aSMark Johnston 	case KASAN_STACK_MID:
16338da497aSMark Johnston 		return "StackMiddle";
16438da497aSMark Johnston 	case KASAN_STACK_RIGHT:
16538da497aSMark Johnston 		return "StackRight";
16638da497aSMark Johnston 	case KASAN_USE_AFTER_RET:
16738da497aSMark Johnston 		return "UseAfterRet";
16838da497aSMark Johnston 	case KASAN_USE_AFTER_SCOPE:
16938da497aSMark Johnston 		return "UseAfterScope";
17038da497aSMark Johnston 	default:
17138da497aSMark Johnston 		return "Unknown";
17238da497aSMark Johnston 	}
17338da497aSMark Johnston }
17438da497aSMark Johnston 
17538da497aSMark Johnston #define	REPORT(f, ...) do {				\
17638da497aSMark Johnston 	if (panic_on_violation) {			\
177ea3fbe07SMark Johnston 		kasan_enabled = false;			\
17838da497aSMark Johnston 		panic(f, __VA_ARGS__);			\
17938da497aSMark Johnston 	} else {					\
18038da497aSMark Johnston 		struct stack st;			\
18138da497aSMark Johnston 							\
18238da497aSMark Johnston 		stack_save(&st);			\
18338da497aSMark Johnston 		printf(f "\n", __VA_ARGS__);		\
18438da497aSMark Johnston 		stack_print_ddb(&st);			\
18538da497aSMark Johnston 	}						\
18638da497aSMark Johnston } while (0)
18738da497aSMark Johnston 
18838da497aSMark Johnston static void
18938da497aSMark Johnston kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc,
19038da497aSMark Johnston     uint8_t code)
19138da497aSMark Johnston {
19238da497aSMark Johnston 	REPORT("ASan: Invalid access, %zu-byte %s at %#lx, %s(%x)",
19338da497aSMark Johnston 	    size, (write ? "write" : "read"), addr, kasan_code_name(code),
19438da497aSMark Johnston 	    code);
19538da497aSMark Johnston }
19638da497aSMark Johnston 
19738da497aSMark Johnston static __always_inline void
19838da497aSMark Johnston kasan_shadow_1byte_markvalid(unsigned long addr)
19938da497aSMark Johnston {
20038da497aSMark Johnston 	int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr);
20138da497aSMark Johnston 	int8_t last = (addr & KASAN_SHADOW_MASK) + 1;
20238da497aSMark Johnston 
20338da497aSMark Johnston 	*byte = last;
20438da497aSMark Johnston }
20538da497aSMark Johnston 
20638da497aSMark Johnston static __always_inline void
20738da497aSMark Johnston kasan_shadow_Nbyte_markvalid(const void *addr, size_t size)
20838da497aSMark Johnston {
20938da497aSMark Johnston 	size_t i;
21038da497aSMark Johnston 
21138da497aSMark Johnston 	for (i = 0; i < size; i++) {
21238da497aSMark Johnston 		kasan_shadow_1byte_markvalid((unsigned long)addr + i);
21338da497aSMark Johnston 	}
21438da497aSMark Johnston }
21538da497aSMark Johnston 
21638da497aSMark Johnston static __always_inline void
21738da497aSMark Johnston kasan_shadow_Nbyte_fill(const void *addr, size_t size, uint8_t code)
21838da497aSMark Johnston {
21938da497aSMark Johnston 	void *shad;
22038da497aSMark Johnston 
22138da497aSMark Johnston 	if (__predict_false(size == 0))
22238da497aSMark Johnston 		return;
22338da497aSMark Johnston 	if (__predict_false(kasan_md_unsupported((vm_offset_t)addr)))
22438da497aSMark Johnston 		return;
22538da497aSMark Johnston 
22638da497aSMark Johnston 	KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0,
22738da497aSMark Johnston 	    ("%s: invalid address %p", __func__, addr));
22838da497aSMark Johnston 	KASSERT(size % KASAN_SHADOW_SCALE == 0,
22938da497aSMark Johnston 	    ("%s: invalid size %zu", __func__, size));
23038da497aSMark Johnston 
23138da497aSMark Johnston 	shad = (void *)kasan_md_addr_to_shad((uintptr_t)addr);
23238da497aSMark Johnston 	size = size >> KASAN_SHADOW_SCALE_SHIFT;
23338da497aSMark Johnston 
23438da497aSMark Johnston 	__builtin_memset(shad, code, size);
23538da497aSMark Johnston }
23638da497aSMark Johnston 
23738da497aSMark Johnston /*
23838da497aSMark Johnston  * In an area of size 'sz_with_redz', mark the 'size' first bytes as valid,
23938da497aSMark Johnston  * and the rest as invalid. There are generally two use cases:
24038da497aSMark Johnston  *
24138da497aSMark Johnston  *  o kasan_mark(addr, origsize, size, code), with origsize < size. This marks
24238da497aSMark Johnston  *    the redzone at the end of the buffer as invalid. If the entire is to be
24338da497aSMark Johnston  *    marked invalid, origsize will be 0.
24438da497aSMark Johnston  *
24538da497aSMark Johnston  *  o kasan_mark(addr, size, size, 0). This marks the entire buffer as valid.
24638da497aSMark Johnston  */
24738da497aSMark Johnston void
24838da497aSMark Johnston kasan_mark(const void *addr, size_t size, size_t redzsize, uint8_t code)
24938da497aSMark Johnston {
25038da497aSMark Johnston 	size_t i, n, redz;
25138da497aSMark Johnston 	int8_t *shad;
25238da497aSMark Johnston 
25338da497aSMark Johnston 	if ((vm_offset_t)addr >= DMAP_MIN_ADDRESS &&
25438da497aSMark Johnston 	    (vm_offset_t)addr < DMAP_MAX_ADDRESS)
25538da497aSMark Johnston 		return;
25638da497aSMark Johnston 
25738da497aSMark Johnston 	KASSERT((vm_offset_t)addr >= VM_MIN_KERNEL_ADDRESS &&
25838da497aSMark Johnston 	    (vm_offset_t)addr < VM_MAX_KERNEL_ADDRESS,
25938da497aSMark Johnston 	    ("%s: invalid address %p", __func__, addr));
26038da497aSMark Johnston 	KASSERT((vm_offset_t)addr % KASAN_SHADOW_SCALE == 0,
26138da497aSMark Johnston 	    ("%s: invalid address %p", __func__, addr));
26238da497aSMark Johnston 	redz = redzsize - roundup(size, KASAN_SHADOW_SCALE);
26338da497aSMark Johnston 	KASSERT(redz % KASAN_SHADOW_SCALE == 0,
26438da497aSMark Johnston 	    ("%s: invalid size %zu", __func__, redz));
26538da497aSMark Johnston 	shad = (int8_t *)kasan_md_addr_to_shad((uintptr_t)addr);
26638da497aSMark Johnston 
26738da497aSMark Johnston 	/* Chunks of 8 bytes, valid. */
26838da497aSMark Johnston 	n = size / KASAN_SHADOW_SCALE;
26938da497aSMark Johnston 	for (i = 0; i < n; i++) {
27038da497aSMark Johnston 		*shad++ = 0;
27138da497aSMark Johnston 	}
27238da497aSMark Johnston 
27338da497aSMark Johnston 	/* Possibly one chunk, mid. */
27438da497aSMark Johnston 	if ((size & KASAN_SHADOW_MASK) != 0) {
27538da497aSMark Johnston 		*shad++ = (size & KASAN_SHADOW_MASK);
27638da497aSMark Johnston 	}
27738da497aSMark Johnston 
27838da497aSMark Johnston 	/* Chunks of 8 bytes, invalid. */
27938da497aSMark Johnston 	n = redz / KASAN_SHADOW_SCALE;
28038da497aSMark Johnston 	for (i = 0; i < n; i++) {
28138da497aSMark Johnston 		*shad++ = code;
28238da497aSMark Johnston 	}
28338da497aSMark Johnston }
28438da497aSMark Johnston 
28538da497aSMark Johnston /* -------------------------------------------------------------------------- */
28638da497aSMark Johnston 
28738da497aSMark Johnston #define ADDR_CROSSES_SCALE_BOUNDARY(addr, size) 		\
28838da497aSMark Johnston 	(addr >> KASAN_SHADOW_SCALE_SHIFT) !=			\
28938da497aSMark Johnston 	    ((addr + size - 1) >> KASAN_SHADOW_SCALE_SHIFT)
29038da497aSMark Johnston 
29138da497aSMark Johnston static __always_inline bool
29238da497aSMark Johnston kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code)
29338da497aSMark Johnston {
29438da497aSMark Johnston 	int8_t *byte = (int8_t *)kasan_md_addr_to_shad(addr);
29538da497aSMark Johnston 	int8_t last = (addr & KASAN_SHADOW_MASK) + 1;
29638da497aSMark Johnston 
29738da497aSMark Johnston 	if (__predict_true(*byte == 0 || last <= *byte)) {
29838da497aSMark Johnston 		return (true);
29938da497aSMark Johnston 	}
30038da497aSMark Johnston 	*code = *byte;
30138da497aSMark Johnston 	return (false);
30238da497aSMark Johnston }
30338da497aSMark Johnston 
30438da497aSMark Johnston static __always_inline bool
30538da497aSMark Johnston kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code)
30638da497aSMark Johnston {
30738da497aSMark Johnston 	int8_t *byte, last;
30838da497aSMark Johnston 
30938da497aSMark Johnston 	if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 2)) {
31038da497aSMark Johnston 		return (kasan_shadow_1byte_isvalid(addr, code) &&
31138da497aSMark Johnston 		    kasan_shadow_1byte_isvalid(addr+1, code));
31238da497aSMark Johnston 	}
31338da497aSMark Johnston 
31438da497aSMark Johnston 	byte = (int8_t *)kasan_md_addr_to_shad(addr);
31538da497aSMark Johnston 	last = ((addr + 1) & KASAN_SHADOW_MASK) + 1;
31638da497aSMark Johnston 
31738da497aSMark Johnston 	if (__predict_true(*byte == 0 || last <= *byte)) {
31838da497aSMark Johnston 		return (true);
31938da497aSMark Johnston 	}
32038da497aSMark Johnston 	*code = *byte;
32138da497aSMark Johnston 	return (false);
32238da497aSMark Johnston }
32338da497aSMark Johnston 
32438da497aSMark Johnston static __always_inline bool
32538da497aSMark Johnston kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code)
32638da497aSMark Johnston {
32738da497aSMark Johnston 	int8_t *byte, last;
32838da497aSMark Johnston 
32938da497aSMark Johnston 	if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 4)) {
33038da497aSMark Johnston 		return (kasan_shadow_2byte_isvalid(addr, code) &&
33138da497aSMark Johnston 		    kasan_shadow_2byte_isvalid(addr+2, code));
33238da497aSMark Johnston 	}
33338da497aSMark Johnston 
33438da497aSMark Johnston 	byte = (int8_t *)kasan_md_addr_to_shad(addr);
33538da497aSMark Johnston 	last = ((addr + 3) & KASAN_SHADOW_MASK) + 1;
33638da497aSMark Johnston 
33738da497aSMark Johnston 	if (__predict_true(*byte == 0 || last <= *byte)) {
33838da497aSMark Johnston 		return (true);
33938da497aSMark Johnston 	}
34038da497aSMark Johnston 	*code = *byte;
34138da497aSMark Johnston 	return (false);
34238da497aSMark Johnston }
34338da497aSMark Johnston 
34438da497aSMark Johnston static __always_inline bool
34538da497aSMark Johnston kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code)
34638da497aSMark Johnston {
34738da497aSMark Johnston 	int8_t *byte, last;
34838da497aSMark Johnston 
34938da497aSMark Johnston 	if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 8)) {
35038da497aSMark Johnston 		return (kasan_shadow_4byte_isvalid(addr, code) &&
35138da497aSMark Johnston 		    kasan_shadow_4byte_isvalid(addr+4, code));
35238da497aSMark Johnston 	}
35338da497aSMark Johnston 
35438da497aSMark Johnston 	byte = (int8_t *)kasan_md_addr_to_shad(addr);
35538da497aSMark Johnston 	last = ((addr + 7) & KASAN_SHADOW_MASK) + 1;
35638da497aSMark Johnston 
35738da497aSMark Johnston 	if (__predict_true(*byte == 0 || last <= *byte)) {
35838da497aSMark Johnston 		return (true);
35938da497aSMark Johnston 	}
36038da497aSMark Johnston 	*code = *byte;
36138da497aSMark Johnston 	return (false);
36238da497aSMark Johnston }
36338da497aSMark Johnston 
36438da497aSMark Johnston static __always_inline bool
36538da497aSMark Johnston kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code)
36638da497aSMark Johnston {
36738da497aSMark Johnston 	size_t i;
36838da497aSMark Johnston 
36938da497aSMark Johnston 	for (i = 0; i < size; i++) {
37038da497aSMark Johnston 		if (!kasan_shadow_1byte_isvalid(addr+i, code))
37138da497aSMark Johnston 			return (false);
37238da497aSMark Johnston 	}
37338da497aSMark Johnston 
37438da497aSMark Johnston 	return (true);
37538da497aSMark Johnston }
37638da497aSMark Johnston 
37738da497aSMark Johnston static __always_inline void
37838da497aSMark Johnston kasan_shadow_check(unsigned long addr, size_t size, bool write,
37938da497aSMark Johnston     unsigned long retaddr)
38038da497aSMark Johnston {
38138da497aSMark Johnston 	uint8_t code;
38238da497aSMark Johnston 	bool valid;
38338da497aSMark Johnston 
38438da497aSMark Johnston 	if (__predict_false(!kasan_enabled))
38538da497aSMark Johnston 		return;
38638da497aSMark Johnston 	if (__predict_false(size == 0))
38738da497aSMark Johnston 		return;
38838da497aSMark Johnston 	if (__predict_false(kasan_md_unsupported(addr)))
38938da497aSMark Johnston 		return;
390*35eb9b10SMitchell Horne 	if (KERNEL_PANICKED())
39138da497aSMark Johnston 		return;
39238da497aSMark Johnston 
39338da497aSMark Johnston 	if (__builtin_constant_p(size)) {
39438da497aSMark Johnston 		switch (size) {
39538da497aSMark Johnston 		case 1:
39638da497aSMark Johnston 			valid = kasan_shadow_1byte_isvalid(addr, &code);
39738da497aSMark Johnston 			break;
39838da497aSMark Johnston 		case 2:
39938da497aSMark Johnston 			valid = kasan_shadow_2byte_isvalid(addr, &code);
40038da497aSMark Johnston 			break;
40138da497aSMark Johnston 		case 4:
40238da497aSMark Johnston 			valid = kasan_shadow_4byte_isvalid(addr, &code);
40338da497aSMark Johnston 			break;
40438da497aSMark Johnston 		case 8:
40538da497aSMark Johnston 			valid = kasan_shadow_8byte_isvalid(addr, &code);
40638da497aSMark Johnston 			break;
40738da497aSMark Johnston 		default:
40838da497aSMark Johnston 			valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
40938da497aSMark Johnston 			break;
41038da497aSMark Johnston 		}
41138da497aSMark Johnston 	} else {
41238da497aSMark Johnston 		valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
41338da497aSMark Johnston 	}
41438da497aSMark Johnston 
41538da497aSMark Johnston 	if (__predict_false(!valid)) {
41638da497aSMark Johnston 		kasan_report(addr, size, write, retaddr, code);
41738da497aSMark Johnston 	}
41838da497aSMark Johnston }
41938da497aSMark Johnston 
42038da497aSMark Johnston /* -------------------------------------------------------------------------- */
42138da497aSMark Johnston 
42238da497aSMark Johnston void *
42338da497aSMark Johnston kasan_memcpy(void *dst, const void *src, size_t len)
42438da497aSMark Johnston {
42538da497aSMark Johnston 	kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR);
42638da497aSMark Johnston 	kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR);
42738da497aSMark Johnston 	return (__builtin_memcpy(dst, src, len));
42838da497aSMark Johnston }
42938da497aSMark Johnston 
43038da497aSMark Johnston int
43138da497aSMark Johnston kasan_memcmp(const void *b1, const void *b2, size_t len)
43238da497aSMark Johnston {
43338da497aSMark Johnston 	kasan_shadow_check((unsigned long)b1, len, false, __RET_ADDR);
43438da497aSMark Johnston 	kasan_shadow_check((unsigned long)b2, len, false, __RET_ADDR);
43538da497aSMark Johnston 	return (__builtin_memcmp(b1, b2, len));
43638da497aSMark Johnston }
43738da497aSMark Johnston 
43838da497aSMark Johnston void *
43938da497aSMark Johnston kasan_memset(void *b, int c, size_t len)
44038da497aSMark Johnston {
44138da497aSMark Johnston 	kasan_shadow_check((unsigned long)b, len, true, __RET_ADDR);
44238da497aSMark Johnston 	return (__builtin_memset(b, c, len));
44338da497aSMark Johnston }
44438da497aSMark Johnston 
44538da497aSMark Johnston void *
44638da497aSMark Johnston kasan_memmove(void *dst, const void *src, size_t len)
44738da497aSMark Johnston {
44838da497aSMark Johnston 	kasan_shadow_check((unsigned long)src, len, false, __RET_ADDR);
44938da497aSMark Johnston 	kasan_shadow_check((unsigned long)dst, len, true, __RET_ADDR);
45038da497aSMark Johnston 	return (__builtin_memmove(dst, src, len));
45138da497aSMark Johnston }
45238da497aSMark Johnston 
45338da497aSMark Johnston size_t
45438da497aSMark Johnston kasan_strlen(const char *str)
45538da497aSMark Johnston {
45638da497aSMark Johnston 	const char *s;
45738da497aSMark Johnston 
45838da497aSMark Johnston 	s = str;
45938da497aSMark Johnston 	while (1) {
46038da497aSMark Johnston 		kasan_shadow_check((unsigned long)s, 1, false, __RET_ADDR);
46138da497aSMark Johnston 		if (*s == '\0')
46238da497aSMark Johnston 			break;
46338da497aSMark Johnston 		s++;
46438da497aSMark Johnston 	}
46538da497aSMark Johnston 
46638da497aSMark Johnston 	return (s - str);
46738da497aSMark Johnston }
46838da497aSMark Johnston 
46938da497aSMark Johnston char *
47038da497aSMark Johnston kasan_strcpy(char *dst, const char *src)
47138da497aSMark Johnston {
47238da497aSMark Johnston 	char *save = dst;
47338da497aSMark Johnston 
47438da497aSMark Johnston 	while (1) {
47538da497aSMark Johnston 		kasan_shadow_check((unsigned long)src, 1, false, __RET_ADDR);
47638da497aSMark Johnston 		kasan_shadow_check((unsigned long)dst, 1, true, __RET_ADDR);
47738da497aSMark Johnston 		*dst = *src;
47838da497aSMark Johnston 		if (*src == '\0')
47938da497aSMark Johnston 			break;
48038da497aSMark Johnston 		src++, dst++;
48138da497aSMark Johnston 	}
48238da497aSMark Johnston 
48338da497aSMark Johnston 	return save;
48438da497aSMark Johnston }
48538da497aSMark Johnston 
48638da497aSMark Johnston int
48738da497aSMark Johnston kasan_strcmp(const char *s1, const char *s2)
48838da497aSMark Johnston {
48938da497aSMark Johnston 	while (1) {
49038da497aSMark Johnston 		kasan_shadow_check((unsigned long)s1, 1, false, __RET_ADDR);
49138da497aSMark Johnston 		kasan_shadow_check((unsigned long)s2, 1, false, __RET_ADDR);
49238da497aSMark Johnston 		if (*s1 != *s2)
49338da497aSMark Johnston 			break;
49438da497aSMark Johnston 		if (*s1 == '\0')
49538da497aSMark Johnston 			return 0;
49638da497aSMark Johnston 		s1++, s2++;
49738da497aSMark Johnston 	}
49838da497aSMark Johnston 
49938da497aSMark Johnston 	return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
50038da497aSMark Johnston }
50138da497aSMark Johnston 
50238da497aSMark Johnston int
50338da497aSMark Johnston kasan_copyin(const void *uaddr, void *kaddr, size_t len)
50438da497aSMark Johnston {
50538da497aSMark Johnston 	kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR);
50638da497aSMark Johnston 	return (copyin(uaddr, kaddr, len));
50738da497aSMark Johnston }
50838da497aSMark Johnston 
50938da497aSMark Johnston int
51038da497aSMark Johnston kasan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
51138da497aSMark Johnston {
51238da497aSMark Johnston 	kasan_shadow_check((unsigned long)kaddr, len, true, __RET_ADDR);
51338da497aSMark Johnston 	return (copyinstr(uaddr, kaddr, len, done));
51438da497aSMark Johnston }
51538da497aSMark Johnston 
51638da497aSMark Johnston int
51738da497aSMark Johnston kasan_copyout(const void *kaddr, void *uaddr, size_t len)
51838da497aSMark Johnston {
51938da497aSMark Johnston 	kasan_shadow_check((unsigned long)kaddr, len, false, __RET_ADDR);
52038da497aSMark Johnston 	return (copyout(kaddr, uaddr, len));
52138da497aSMark Johnston }
52238da497aSMark Johnston 
52338da497aSMark Johnston /* -------------------------------------------------------------------------- */
52438da497aSMark Johnston 
5256f179693SMark Johnston int
5266f179693SMark Johnston kasan_fubyte(volatile const void *base)
5276f179693SMark Johnston {
5286f179693SMark Johnston 	return (fubyte(base));
5296f179693SMark Johnston }
5306f179693SMark Johnston 
5316f179693SMark Johnston int
5326f179693SMark Johnston kasan_fuword16(volatile const void *base)
5336f179693SMark Johnston {
5346f179693SMark Johnston 	return (fuword16(base));
5356f179693SMark Johnston }
5366f179693SMark Johnston 
5376f179693SMark Johnston int
5386f179693SMark Johnston kasan_fueword(volatile const void *base, long *val)
5396f179693SMark Johnston {
5406f179693SMark Johnston 	kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR);
5416f179693SMark Johnston 	return (fueword(base, val));
5426f179693SMark Johnston }
5436f179693SMark Johnston 
5446f179693SMark Johnston int
5456f179693SMark Johnston kasan_fueword32(volatile const void *base, int32_t *val)
5466f179693SMark Johnston {
5476f179693SMark Johnston 	kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR);
5486f179693SMark Johnston 	return (fueword32(base, val));
5496f179693SMark Johnston }
5506f179693SMark Johnston 
5516f179693SMark Johnston int
5526f179693SMark Johnston kasan_fueword64(volatile const void *base, int64_t *val)
5536f179693SMark Johnston {
5546f179693SMark Johnston 	kasan_shadow_check((unsigned long)val, sizeof(*val), true, __RET_ADDR);
5556f179693SMark Johnston 	return (fueword64(base, val));
5566f179693SMark Johnston }
5576f179693SMark Johnston 
5586f179693SMark Johnston int
5596f179693SMark Johnston kasan_subyte(volatile void *base, int byte)
5606f179693SMark Johnston {
5616f179693SMark Johnston 	return (subyte(base, byte));
5626f179693SMark Johnston }
5636f179693SMark Johnston 
5646f179693SMark Johnston int
5656f179693SMark Johnston kasan_suword(volatile void *base, long word)
5666f179693SMark Johnston {
5676f179693SMark Johnston 	return (suword(base, word));
5686f179693SMark Johnston }
5696f179693SMark Johnston 
5706f179693SMark Johnston int
5716f179693SMark Johnston kasan_suword16(volatile void *base, int word)
5726f179693SMark Johnston {
5736f179693SMark Johnston 	return (suword16(base, word));
5746f179693SMark Johnston }
5756f179693SMark Johnston 
5766f179693SMark Johnston int
5776f179693SMark Johnston kasan_suword32(volatile void *base, int32_t word)
5786f179693SMark Johnston {
5796f179693SMark Johnston 	return (suword32(base, word));
5806f179693SMark Johnston }
5816f179693SMark Johnston 
5826f179693SMark Johnston int
5836f179693SMark Johnston kasan_suword64(volatile void *base, int64_t word)
5846f179693SMark Johnston {
5856f179693SMark Johnston 	return (suword64(base, word));
5866f179693SMark Johnston }
5876f179693SMark Johnston 
5886f179693SMark Johnston int
5896f179693SMark Johnston kasan_casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,
5906f179693SMark Johnston     uint32_t newval)
5916f179693SMark Johnston {
5926f179693SMark Johnston 	kasan_shadow_check((unsigned long)oldvalp, sizeof(*oldvalp), true,
5936f179693SMark Johnston 	    __RET_ADDR);
5946f179693SMark Johnston 	return (casueword32(base, oldval, oldvalp, newval));
5956f179693SMark Johnston }
5966f179693SMark Johnston 
5976f179693SMark Johnston int
5986f179693SMark Johnston kasan_casueword(volatile u_long *base, u_long oldval, u_long *oldvalp,
5996f179693SMark Johnston     u_long newval)
6006f179693SMark Johnston {
6016f179693SMark Johnston 	kasan_shadow_check((unsigned long)oldvalp, sizeof(*oldvalp), true,
6026f179693SMark Johnston 	    __RET_ADDR);
6036f179693SMark Johnston 	return (casueword(base, oldval, oldvalp, newval));
6046f179693SMark Johnston }
6056f179693SMark Johnston 
6066f179693SMark Johnston /* -------------------------------------------------------------------------- */
6076f179693SMark Johnston 
60838da497aSMark Johnston #include <machine/atomic.h>
60938da497aSMark Johnston #include <sys/atomic_san.h>
61038da497aSMark Johnston 
61138da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_ADD(name, type)				\
61238da497aSMark Johnston 	void kasan_atomic_add_##name(volatile type *ptr, type val)	\
61338da497aSMark Johnston 	{								\
61438da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
61538da497aSMark Johnston 		    __RET_ADDR);					\
61638da497aSMark Johnston 		atomic_add_##name(ptr, val);				\
61738da497aSMark Johnston 	}
61838da497aSMark Johnston 
61938da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_ADD(name, type)				\
62038da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_ADD(name, type)				\
62138da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_ADD(acq_##name, type)				\
62238da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_ADD(rel_##name, type)
62338da497aSMark Johnston 
62438da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
62538da497aSMark Johnston 	void kasan_atomic_subtract_##name(volatile type *ptr, type val)	\
62638da497aSMark Johnston 	{								\
62738da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
62838da497aSMark Johnston 		    __RET_ADDR);					\
62938da497aSMark Johnston 		atomic_subtract_##name(ptr, val);			\
63038da497aSMark Johnston 	}
63138da497aSMark Johnston 
63238da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
63338da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
63438da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type)			\
63538da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
63638da497aSMark Johnston 
63738da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_SET(name, type)				\
63838da497aSMark Johnston 	void kasan_atomic_set_##name(volatile type *ptr, type val)	\
63938da497aSMark Johnston 	{								\
64038da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
64138da497aSMark Johnston 		    __RET_ADDR);					\
64238da497aSMark Johnston 		atomic_set_##name(ptr, val);				\
64338da497aSMark Johnston 	}
64438da497aSMark Johnston 
64538da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_SET(name, type)				\
64638da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_SET(name, type)				\
64738da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_SET(acq_##name, type)				\
64838da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_SET(rel_##name, type)
64938da497aSMark Johnston 
65038da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_CLEAR(name, type)				\
65138da497aSMark Johnston 	void kasan_atomic_clear_##name(volatile type *ptr, type val)	\
65238da497aSMark Johnston 	{								\
65338da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
65438da497aSMark Johnston 		    __RET_ADDR);					\
65538da497aSMark Johnston 		atomic_clear_##name(ptr, val);				\
65638da497aSMark Johnston 	}
65738da497aSMark Johnston 
65838da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_CLEAR(name, type)				\
65938da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_CLEAR(name, type)				\
66038da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_CLEAR(acq_##name, type)			\
66138da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
66238da497aSMark Johnston 
66338da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_FETCHADD(name, type)				\
66438da497aSMark Johnston 	type kasan_atomic_fetchadd_##name(volatile type *ptr, type val)	\
66538da497aSMark Johnston 	{								\
66638da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
66738da497aSMark Johnston 		    __RET_ADDR);					\
66838da497aSMark Johnston 		return (atomic_fetchadd_##name(ptr, val));		\
66938da497aSMark Johnston 	}
67038da497aSMark Johnston 
67138da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_READANDCLEAR(name, type)			\
67238da497aSMark Johnston 	type kasan_atomic_readandclear_##name(volatile type *ptr)	\
67338da497aSMark Johnston 	{								\
67438da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
67538da497aSMark Johnston 		    __RET_ADDR);					\
67638da497aSMark Johnston 		return (atomic_readandclear_##name(ptr));		\
67738da497aSMark Johnston 	}
67838da497aSMark Johnston 
67938da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_TESTANDCLEAR(name, type)			\
68038da497aSMark Johnston 	int kasan_atomic_testandclear_##name(volatile type *ptr, u_int v) \
68138da497aSMark Johnston 	{								\
68238da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
68338da497aSMark Johnston 		    __RET_ADDR);					\
68438da497aSMark Johnston 		return (atomic_testandclear_##name(ptr, v));		\
68538da497aSMark Johnston 	}
68638da497aSMark Johnston 
68738da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_TESTANDSET(name, type)				\
68838da497aSMark Johnston 	int kasan_atomic_testandset_##name(volatile type *ptr, u_int v) \
68938da497aSMark Johnston 	{								\
69038da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
69138da497aSMark Johnston 		    __RET_ADDR);					\
69238da497aSMark Johnston 		return (atomic_testandset_##name(ptr, v));		\
69338da497aSMark Johnston 	}
69438da497aSMark Johnston 
69538da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_SWAP(name, type)				\
69638da497aSMark Johnston 	type kasan_atomic_swap_##name(volatile type *ptr, type val)	\
69738da497aSMark Johnston 	{								\
69838da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
69938da497aSMark Johnston 		    __RET_ADDR);					\
70038da497aSMark Johnston 		return (atomic_swap_##name(ptr, val));			\
70138da497aSMark Johnston 	}
70238da497aSMark Johnston 
70338da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_CMPSET(name, type)				\
70438da497aSMark Johnston 	int kasan_atomic_cmpset_##name(volatile type *ptr, type oval,	\
70538da497aSMark Johnston 	    type nval)							\
70638da497aSMark Johnston 	{								\
70738da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
70838da497aSMark Johnston 		    __RET_ADDR);					\
70938da497aSMark Johnston 		return (atomic_cmpset_##name(ptr, oval, nval));		\
71038da497aSMark Johnston 	}
71138da497aSMark Johnston 
71238da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_CMPSET(name, type)				\
71338da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_CMPSET(name, type)				\
71438da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_CMPSET(acq_##name, type)			\
71538da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
71638da497aSMark Johnston 
71738da497aSMark Johnston #define _ASAN_ATOMIC_FUNC_FCMPSET(name, type)				\
71838da497aSMark Johnston 	int kasan_atomic_fcmpset_##name(volatile type *ptr, type *oval,	\
71938da497aSMark Johnston 	    type nval)							\
72038da497aSMark Johnston 	{								\
72138da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
72238da497aSMark Johnston 		    __RET_ADDR);					\
72338da497aSMark Johnston 		return (atomic_fcmpset_##name(ptr, oval, nval));	\
72438da497aSMark Johnston 	}
72538da497aSMark Johnston 
72638da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_FCMPSET(name, type)				\
72738da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_FCMPSET(name, type)				\
72838da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_FCMPSET(acq_##name, type)			\
72938da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
73038da497aSMark Johnston 
73138da497aSMark Johnston #define ASAN_ATOMIC_FUNC_THREAD_FENCE(name)				\
73238da497aSMark Johnston 	void kasan_atomic_thread_fence_##name(void)			\
73338da497aSMark Johnston 	{								\
73438da497aSMark Johnston 		atomic_thread_fence_##name();				\
73538da497aSMark Johnston 	}
73638da497aSMark Johnston 
73738da497aSMark Johnston #define	_ASAN_ATOMIC_FUNC_LOAD(name, type)				\
73838da497aSMark Johnston 	type kasan_atomic_load_##name(volatile type *ptr)		\
73938da497aSMark Johnston 	{								\
74038da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
74138da497aSMark Johnston 		    __RET_ADDR);					\
74238da497aSMark Johnston 		return (atomic_load_##name(ptr));			\
74338da497aSMark Johnston 	}
74438da497aSMark Johnston 
74538da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_LOAD(name, type)				\
74638da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_LOAD(name, type)				\
74738da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_LOAD(acq_##name, type)
74838da497aSMark Johnston 
74938da497aSMark Johnston #define	_ASAN_ATOMIC_FUNC_STORE(name, type)				\
75038da497aSMark Johnston 	void kasan_atomic_store_##name(volatile type *ptr, type val)	\
75138da497aSMark Johnston 	{								\
75238da497aSMark Johnston 		kasan_shadow_check((uintptr_t)ptr, sizeof(type), true,	\
75338da497aSMark Johnston 		    __RET_ADDR);					\
75438da497aSMark Johnston 		atomic_store_##name(ptr, val);				\
75538da497aSMark Johnston 	}
75638da497aSMark Johnston 
75738da497aSMark Johnston #define	ASAN_ATOMIC_FUNC_STORE(name, type)				\
75838da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_STORE(name, type)				\
75938da497aSMark Johnston 	_ASAN_ATOMIC_FUNC_STORE(rel_##name, type)
76038da497aSMark Johnston 
76138da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(8, uint8_t);
76238da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(16, uint16_t);
76338da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(32, uint32_t);
76438da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(64, uint64_t);
76538da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(int, u_int);
76638da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(long, u_long);
76738da497aSMark Johnston ASAN_ATOMIC_FUNC_ADD(ptr, uintptr_t);
76838da497aSMark Johnston 
76938da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t);
77038da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t);
77138da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t);
77238da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t);
77338da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(int, u_int);
77438da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(long, u_long);
77538da497aSMark Johnston ASAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t);
77638da497aSMark Johnston 
77738da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(8, uint8_t);
77838da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(16, uint16_t);
77938da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(32, uint32_t);
78038da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(64, uint64_t);
78138da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(int, u_int);
78238da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(long, u_long);
78338da497aSMark Johnston ASAN_ATOMIC_FUNC_SET(ptr, uintptr_t);
78438da497aSMark Johnston 
78538da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(8, uint8_t);
78638da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(16, uint16_t);
78738da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(32, uint32_t);
78838da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(64, uint64_t);
78938da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(int, u_int);
79038da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(long, u_long);
79138da497aSMark Johnston ASAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t);
79238da497aSMark Johnston 
79338da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(32, uint32_t);
79438da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(64, uint64_t);
79538da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(int, u_int);
79638da497aSMark Johnston ASAN_ATOMIC_FUNC_FETCHADD(long, u_long);
79738da497aSMark Johnston 
79838da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t);
79938da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t);
80038da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(int, u_int);
80138da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(long, u_long);
80238da497aSMark Johnston ASAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t);
80338da497aSMark Johnston 
80438da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t);
80538da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t);
80638da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int);
80738da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long);
80838da497aSMark Johnston 
80938da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t);
81038da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t);
81138da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(int, u_int);
81238da497aSMark Johnston ASAN_ATOMIC_FUNC_TESTANDSET(long, u_long);
81338da497aSMark Johnston 
81438da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(32, uint32_t);
81538da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(64, uint64_t);
81638da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(int, u_int);
81738da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(long, u_long);
81838da497aSMark Johnston ASAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t);
81938da497aSMark Johnston 
82038da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(8, uint8_t);
82138da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(16, uint16_t);
82238da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(32, uint32_t);
82338da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(64, uint64_t);
82438da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(int, u_int);
82538da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(long, u_long);
82638da497aSMark Johnston ASAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t);
82738da497aSMark Johnston 
82838da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(8, uint8_t);
82938da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(16, uint16_t);
83038da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(32, uint32_t);
83138da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(64, uint64_t);
83238da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(int, u_int);
83338da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(long, u_long);
83438da497aSMark Johnston ASAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t);
83538da497aSMark Johnston 
83638da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(8, uint8_t);
83738da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(16, uint16_t);
83838da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(32, uint32_t);
83938da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(64, uint64_t);
84038da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(char, u_char);
84138da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(short, u_short);
84238da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(int, u_int);
84338da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(long, u_long);
84438da497aSMark Johnston ASAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t);
84538da497aSMark Johnston 
84638da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(8, uint8_t);
84738da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(16, uint16_t);
84838da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(32, uint32_t);
84938da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(64, uint64_t);
85038da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(char, u_char);
85138da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(short, u_short);
85238da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(int, u_int);
85338da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(long, u_long);
85438da497aSMark Johnston ASAN_ATOMIC_FUNC_STORE(ptr, uintptr_t);
85538da497aSMark Johnston 
85638da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(acq);
85738da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(rel);
85838da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel);
85938da497aSMark Johnston ASAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst);
86038da497aSMark Johnston 
86138da497aSMark Johnston void
86238da497aSMark Johnston kasan_atomic_interrupt_fence(void)
86338da497aSMark Johnston {
86438da497aSMark Johnston }
86538da497aSMark Johnston 
86638da497aSMark Johnston /* -------------------------------------------------------------------------- */
86738da497aSMark Johnston 
86838da497aSMark Johnston #include <sys/bus.h>
86938da497aSMark Johnston #include <machine/bus.h>
87038da497aSMark Johnston #include <sys/bus_san.h>
87138da497aSMark Johnston 
87238da497aSMark Johnston int
87338da497aSMark Johnston kasan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
87438da497aSMark Johnston     int flags, bus_space_handle_t *handlep)
87538da497aSMark Johnston {
87638da497aSMark Johnston 	return (bus_space_map(tag, hnd, size, flags, handlep));
87738da497aSMark Johnston }
87838da497aSMark Johnston 
87938da497aSMark Johnston void
88038da497aSMark Johnston kasan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
88138da497aSMark Johnston     bus_size_t size)
88238da497aSMark Johnston {
88338da497aSMark Johnston 	bus_space_unmap(tag, hnd, size);
88438da497aSMark Johnston }
88538da497aSMark Johnston 
88638da497aSMark Johnston int
88738da497aSMark Johnston kasan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
88838da497aSMark Johnston     bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
88938da497aSMark Johnston {
89038da497aSMark Johnston 	return (bus_space_subregion(tag, hnd, offset, size, handlep));
89138da497aSMark Johnston }
89238da497aSMark Johnston 
89338da497aSMark Johnston void
89438da497aSMark Johnston kasan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
89538da497aSMark Johnston     bus_size_t size)
89638da497aSMark Johnston {
89738da497aSMark Johnston 	bus_space_free(tag, hnd, size);
89838da497aSMark Johnston }
89938da497aSMark Johnston 
90038da497aSMark Johnston void
90138da497aSMark Johnston kasan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
90238da497aSMark Johnston     bus_size_t offset, bus_size_t size, int flags)
90338da497aSMark Johnston {
90438da497aSMark Johnston 	bus_space_barrier(tag, hnd, offset, size, flags);
90538da497aSMark Johnston }
90638da497aSMark Johnston 
90738da497aSMark Johnston #define ASAN_BUS_READ_FUNC(func, width, type)				\
90838da497aSMark Johnston 	type kasan_bus_space_read##func##_##width(bus_space_tag_t tag,	\
90938da497aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t offset)			\
91038da497aSMark Johnston 	{								\
91138da497aSMark Johnston 		return (bus_space_read##func##_##width(tag, hnd,	\
91238da497aSMark Johnston 		    offset));						\
91338da497aSMark Johnston 	}								\
91438da497aSMark Johnston 
91538da497aSMark Johnston #define ASAN_BUS_READ_PTR_FUNC(func, width, type)			\
91638da497aSMark Johnston 	void kasan_bus_space_read_##func##_##width(bus_space_tag_t tag,	\
91738da497aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t size, type *buf,		\
91838da497aSMark Johnston 	    bus_size_t count)						\
91938da497aSMark Johnston 	{								\
92038da497aSMark Johnston 		kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
92138da497aSMark Johnston 		    false, __RET_ADDR);					\
92238da497aSMark Johnston 		bus_space_read_##func##_##width(tag, hnd, size, buf, 	\
92338da497aSMark Johnston 		    count);						\
92438da497aSMark Johnston 	}
92538da497aSMark Johnston 
92638da497aSMark Johnston ASAN_BUS_READ_FUNC(, 1, uint8_t)
92738da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 1, uint8_t)
92838da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
92938da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
93038da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 1, uint8_t)
93138da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
93238da497aSMark Johnston 
93338da497aSMark Johnston ASAN_BUS_READ_FUNC(, 2, uint16_t)
93438da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 2, uint16_t)
93538da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
93638da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
93738da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
93838da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
93938da497aSMark Johnston 
94038da497aSMark Johnston ASAN_BUS_READ_FUNC(, 4, uint32_t)
94138da497aSMark Johnston ASAN_BUS_READ_FUNC(_stream, 4, uint32_t)
94238da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
94338da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
94438da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
94538da497aSMark Johnston ASAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
94638da497aSMark Johnston 
94738da497aSMark Johnston ASAN_BUS_READ_FUNC(, 8, uint64_t)
94838da497aSMark Johnston 
94938da497aSMark Johnston #define	ASAN_BUS_WRITE_FUNC(func, width, type)				\
95038da497aSMark Johnston 	void kasan_bus_space_write##func##_##width(bus_space_tag_t tag,	\
95138da497aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t offset, type value)	\
95238da497aSMark Johnston 	{								\
95338da497aSMark Johnston 		bus_space_write##func##_##width(tag, hnd, offset, value);\
95438da497aSMark Johnston 	}								\
95538da497aSMark Johnston 
95638da497aSMark Johnston #define	ASAN_BUS_WRITE_PTR_FUNC(func, width, type)			\
95738da497aSMark Johnston 	void kasan_bus_space_write_##func##_##width(bus_space_tag_t tag,\
95838da497aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t size, const type *buf,	\
95938da497aSMark Johnston 	    bus_size_t count)						\
96038da497aSMark Johnston 	{								\
96138da497aSMark Johnston 		kasan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
96238da497aSMark Johnston 		    true, __RET_ADDR);					\
96338da497aSMark Johnston 		bus_space_write_##func##_##width(tag, hnd, size, buf, 	\
96438da497aSMark Johnston 		    count);						\
96538da497aSMark Johnston 	}
96638da497aSMark Johnston 
96738da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 1, uint8_t)
96838da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
96938da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
97038da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
97138da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t)
97238da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
97338da497aSMark Johnston 
97438da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 2, uint16_t)
97538da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
97638da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
97738da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
97838da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t)
97938da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
98038da497aSMark Johnston 
98138da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 4, uint32_t)
98238da497aSMark Johnston ASAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
98338da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
98438da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
98538da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t)
98638da497aSMark Johnston ASAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
98738da497aSMark Johnston 
98838da497aSMark Johnston ASAN_BUS_WRITE_FUNC(, 8, uint64_t)
98938da497aSMark Johnston 
99038da497aSMark Johnston #define	ASAN_BUS_SET_FUNC(func, width, type)				\
99138da497aSMark Johnston 	void kasan_bus_space_set_##func##_##width(bus_space_tag_t tag,	\
99238da497aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t offset, type value,	\
99338da497aSMark Johnston 	    bus_size_t count)						\
99438da497aSMark Johnston 	{								\
99538da497aSMark Johnston 		bus_space_set_##func##_##width(tag, hnd, offset, value,	\
99638da497aSMark Johnston 		    count);						\
99738da497aSMark Johnston 	}
99838da497aSMark Johnston 
99938da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 1, uint8_t)
100038da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 1, uint8_t)
100138da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
100238da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
100338da497aSMark Johnston 
100438da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 2, uint16_t)
100538da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 2, uint16_t)
100638da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
100738da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
100838da497aSMark Johnston 
100938da497aSMark Johnston ASAN_BUS_SET_FUNC(multi, 4, uint32_t)
101038da497aSMark Johnston ASAN_BUS_SET_FUNC(region, 4, uint32_t)
101138da497aSMark Johnston ASAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
101238da497aSMark Johnston ASAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
101338da497aSMark Johnston 
101438da497aSMark Johnston /* -------------------------------------------------------------------------- */
101538da497aSMark Johnston 
101638da497aSMark Johnston void __asan_register_globals(struct __asan_global *, size_t);
101738da497aSMark Johnston void __asan_unregister_globals(struct __asan_global *, size_t);
101838da497aSMark Johnston 
101938da497aSMark Johnston void
102038da497aSMark Johnston __asan_register_globals(struct __asan_global *globals, size_t n)
102138da497aSMark Johnston {
102238da497aSMark Johnston 	size_t i;
102338da497aSMark Johnston 
102438da497aSMark Johnston 	for (i = 0; i < n; i++) {
102538da497aSMark Johnston 		kasan_mark(globals[i].beg, globals[i].size,
102638da497aSMark Johnston 		    globals[i].size_with_redzone, KASAN_GENERIC_REDZONE);
102738da497aSMark Johnston 	}
102838da497aSMark Johnston }
102938da497aSMark Johnston 
103038da497aSMark Johnston void
103138da497aSMark Johnston __asan_unregister_globals(struct __asan_global *globals, size_t n)
103238da497aSMark Johnston {
1033588c7a06SMark Johnston 	size_t i;
1034588c7a06SMark Johnston 
1035588c7a06SMark Johnston 	for (i = 0; i < n; i++) {
1036588c7a06SMark Johnston 		kasan_mark(globals[i].beg, globals[i].size_with_redzone,
1037588c7a06SMark Johnston 		    globals[i].size_with_redzone, 0);
1038588c7a06SMark Johnston 	}
103938da497aSMark Johnston }
104038da497aSMark Johnston 
104138da497aSMark Johnston #define ASAN_LOAD_STORE(size)					\
104238da497aSMark Johnston 	void __asan_load##size(unsigned long);			\
104338da497aSMark Johnston 	void __asan_load##size(unsigned long addr)		\
104438da497aSMark Johnston 	{							\
104538da497aSMark Johnston 		kasan_shadow_check(addr, size, false, __RET_ADDR);\
104638da497aSMark Johnston 	} 							\
104738da497aSMark Johnston 	void __asan_load##size##_noabort(unsigned long);	\
104838da497aSMark Johnston 	void __asan_load##size##_noabort(unsigned long addr)	\
104938da497aSMark Johnston 	{							\
105038da497aSMark Johnston 		kasan_shadow_check(addr, size, false, __RET_ADDR);\
105138da497aSMark Johnston 	}							\
105238da497aSMark Johnston 	void __asan_store##size(unsigned long);			\
105338da497aSMark Johnston 	void __asan_store##size(unsigned long addr)		\
105438da497aSMark Johnston 	{							\
105538da497aSMark Johnston 		kasan_shadow_check(addr, size, true, __RET_ADDR);\
105638da497aSMark Johnston 	}							\
105738da497aSMark Johnston 	void __asan_store##size##_noabort(unsigned long);	\
105838da497aSMark Johnston 	void __asan_store##size##_noabort(unsigned long addr)	\
105938da497aSMark Johnston 	{							\
106038da497aSMark Johnston 		kasan_shadow_check(addr, size, true, __RET_ADDR);\
106138da497aSMark Johnston 	}
106238da497aSMark Johnston 
106338da497aSMark Johnston ASAN_LOAD_STORE(1);
106438da497aSMark Johnston ASAN_LOAD_STORE(2);
106538da497aSMark Johnston ASAN_LOAD_STORE(4);
106638da497aSMark Johnston ASAN_LOAD_STORE(8);
106738da497aSMark Johnston ASAN_LOAD_STORE(16);
106838da497aSMark Johnston 
106938da497aSMark Johnston void __asan_loadN(unsigned long, size_t);
107038da497aSMark Johnston void __asan_loadN_noabort(unsigned long, size_t);
107138da497aSMark Johnston void __asan_storeN(unsigned long, size_t);
107238da497aSMark Johnston void __asan_storeN_noabort(unsigned long, size_t);
107338da497aSMark Johnston void __asan_handle_no_return(void);
107438da497aSMark Johnston 
107538da497aSMark Johnston void
107638da497aSMark Johnston __asan_loadN(unsigned long addr, size_t size)
107738da497aSMark Johnston {
107838da497aSMark Johnston 	kasan_shadow_check(addr, size, false, __RET_ADDR);
107938da497aSMark Johnston }
108038da497aSMark Johnston 
108138da497aSMark Johnston void
108238da497aSMark Johnston __asan_loadN_noabort(unsigned long addr, size_t size)
108338da497aSMark Johnston {
108438da497aSMark Johnston 	kasan_shadow_check(addr, size, false, __RET_ADDR);
108538da497aSMark Johnston }
108638da497aSMark Johnston 
108738da497aSMark Johnston void
108838da497aSMark Johnston __asan_storeN(unsigned long addr, size_t size)
108938da497aSMark Johnston {
109038da497aSMark Johnston 	kasan_shadow_check(addr, size, true, __RET_ADDR);
109138da497aSMark Johnston }
109238da497aSMark Johnston 
109338da497aSMark Johnston void
109438da497aSMark Johnston __asan_storeN_noabort(unsigned long addr, size_t size)
109538da497aSMark Johnston {
109638da497aSMark Johnston 	kasan_shadow_check(addr, size, true, __RET_ADDR);
109738da497aSMark Johnston }
109838da497aSMark Johnston 
109938da497aSMark Johnston void
110038da497aSMark Johnston __asan_handle_no_return(void)
110138da497aSMark Johnston {
110238da497aSMark Johnston 	/* nothing */
110338da497aSMark Johnston }
110438da497aSMark Johnston 
110538da497aSMark Johnston #define ASAN_SET_SHADOW(byte) \
110638da497aSMark Johnston 	void __asan_set_shadow_##byte(void *, size_t);			\
110738da497aSMark Johnston 	void __asan_set_shadow_##byte(void *addr, size_t size)		\
110838da497aSMark Johnston 	{								\
110938da497aSMark Johnston 		__builtin_memset((void *)addr, 0x##byte, size);		\
111038da497aSMark Johnston 	}
111138da497aSMark Johnston 
111238da497aSMark Johnston ASAN_SET_SHADOW(00);
111338da497aSMark Johnston ASAN_SET_SHADOW(f1);
111438da497aSMark Johnston ASAN_SET_SHADOW(f2);
111538da497aSMark Johnston ASAN_SET_SHADOW(f3);
111638da497aSMark Johnston ASAN_SET_SHADOW(f5);
111738da497aSMark Johnston ASAN_SET_SHADOW(f8);
111838da497aSMark Johnston 
111938da497aSMark Johnston void __asan_poison_stack_memory(const void *, size_t);
112038da497aSMark Johnston void __asan_unpoison_stack_memory(const void *, size_t);
112138da497aSMark Johnston 
112238da497aSMark Johnston void
112338da497aSMark Johnston __asan_poison_stack_memory(const void *addr, size_t size)
112438da497aSMark Johnston {
112538da497aSMark Johnston 	size = roundup(size, KASAN_SHADOW_SCALE);
112638da497aSMark Johnston 	kasan_shadow_Nbyte_fill(addr, size, KASAN_USE_AFTER_SCOPE);
112738da497aSMark Johnston }
112838da497aSMark Johnston 
112938da497aSMark Johnston void
113038da497aSMark Johnston __asan_unpoison_stack_memory(const void *addr, size_t size)
113138da497aSMark Johnston {
113238da497aSMark Johnston 	kasan_shadow_Nbyte_markvalid(addr, size);
113338da497aSMark Johnston }
113438da497aSMark Johnston 
113538da497aSMark Johnston void __asan_alloca_poison(const void *, size_t);
113638da497aSMark Johnston void __asan_allocas_unpoison(const void *, const void *);
113738da497aSMark Johnston 
113838da497aSMark Johnston void
113938da497aSMark Johnston __asan_alloca_poison(const void *addr, size_t size)
114038da497aSMark Johnston {
114138da497aSMark Johnston 	const void *l, *r;
114238da497aSMark Johnston 
114338da497aSMark Johnston 	KASSERT((vm_offset_t)addr % KASAN_ALLOCA_SCALE_SIZE == 0,
114438da497aSMark Johnston 	    ("%s: invalid address %p", __func__, addr));
114538da497aSMark Johnston 
114638da497aSMark Johnston 	l = (const uint8_t *)addr - KASAN_ALLOCA_SCALE_SIZE;
114738da497aSMark Johnston 	r = (const uint8_t *)addr + roundup(size, KASAN_ALLOCA_SCALE_SIZE);
114838da497aSMark Johnston 
114938da497aSMark Johnston 	kasan_shadow_Nbyte_fill(l, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_LEFT);
115038da497aSMark Johnston 	kasan_mark(addr, size, roundup(size, KASAN_ALLOCA_SCALE_SIZE),
115138da497aSMark Johnston 	    KASAN_STACK_MID);
115238da497aSMark Johnston 	kasan_shadow_Nbyte_fill(r, KASAN_ALLOCA_SCALE_SIZE, KASAN_STACK_RIGHT);
115338da497aSMark Johnston }
115438da497aSMark Johnston 
115538da497aSMark Johnston void
115638da497aSMark Johnston __asan_allocas_unpoison(const void *stkbegin, const void *stkend)
115738da497aSMark Johnston {
115838da497aSMark Johnston 	size_t size;
115938da497aSMark Johnston 
116038da497aSMark Johnston 	if (__predict_false(!stkbegin))
116138da497aSMark Johnston 		return;
116238da497aSMark Johnston 	if (__predict_false((uintptr_t)stkbegin > (uintptr_t)stkend))
116338da497aSMark Johnston 		return;
116438da497aSMark Johnston 	size = (uintptr_t)stkend - (uintptr_t)stkbegin;
116538da497aSMark Johnston 
116638da497aSMark Johnston 	kasan_shadow_Nbyte_fill(stkbegin, size, 0);
116738da497aSMark Johnston }
116838da497aSMark Johnston 
116938da497aSMark Johnston void __asan_poison_memory_region(const void *addr, size_t size);
117038da497aSMark Johnston void __asan_unpoison_memory_region(const void *addr, size_t size);
117138da497aSMark Johnston 
117238da497aSMark Johnston void
117338da497aSMark Johnston __asan_poison_memory_region(const void *addr, size_t size)
117438da497aSMark Johnston {
117538da497aSMark Johnston }
117638da497aSMark Johnston 
117738da497aSMark Johnston void
117838da497aSMark Johnston __asan_unpoison_memory_region(const void *addr, size_t size)
117938da497aSMark Johnston {
118038da497aSMark Johnston }
1181