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