xref: /openbmc/linux/include/linux/instrumented.h (revision d70e2ecb)
136e4d4ddSMarco Elver /* SPDX-License-Identifier: GPL-2.0 */
236e4d4ddSMarco Elver 
336e4d4ddSMarco Elver /*
436e4d4ddSMarco Elver  * This header provides generic wrappers for memory access instrumentation that
575cf0290SAlexander Potapenko  * the compiler cannot emit for: KASAN, KCSAN, KMSAN.
636e4d4ddSMarco Elver  */
736e4d4ddSMarco Elver #ifndef _LINUX_INSTRUMENTED_H
836e4d4ddSMarco Elver #define _LINUX_INSTRUMENTED_H
936e4d4ddSMarco Elver 
1036e4d4ddSMarco Elver #include <linux/compiler.h>
1136e4d4ddSMarco Elver #include <linux/kasan-checks.h>
1236e4d4ddSMarco Elver #include <linux/kcsan-checks.h>
1375cf0290SAlexander Potapenko #include <linux/kmsan-checks.h>
1436e4d4ddSMarco Elver #include <linux/types.h>
1536e4d4ddSMarco Elver 
1636e4d4ddSMarco Elver /**
1736e4d4ddSMarco Elver  * instrument_read - instrument regular read access
18*d70e2ecbSRandy Dunlap  * @v: address of access
19*d70e2ecbSRandy Dunlap  * @size: size of access
2036e4d4ddSMarco Elver  *
2136e4d4ddSMarco Elver  * Instrument a regular read access. The instrumentation should be inserted
2236e4d4ddSMarco Elver  * before the actual read happens.
2336e4d4ddSMarco Elver  */
instrument_read(const volatile void * v,size_t size)2436e4d4ddSMarco Elver static __always_inline void instrument_read(const volatile void *v, size_t size)
2536e4d4ddSMarco Elver {
2636e4d4ddSMarco Elver 	kasan_check_read(v, size);
2736e4d4ddSMarco Elver 	kcsan_check_read(v, size);
2836e4d4ddSMarco Elver }
2936e4d4ddSMarco Elver 
3036e4d4ddSMarco Elver /**
3136e4d4ddSMarco Elver  * instrument_write - instrument regular write access
32*d70e2ecbSRandy Dunlap  * @v: address of access
33*d70e2ecbSRandy Dunlap  * @size: size of access
3436e4d4ddSMarco Elver  *
3536e4d4ddSMarco Elver  * Instrument a regular write access. The instrumentation should be inserted
3636e4d4ddSMarco Elver  * before the actual write happens.
3736e4d4ddSMarco Elver  */
instrument_write(const volatile void * v,size_t size)3836e4d4ddSMarco Elver static __always_inline void instrument_write(const volatile void *v, size_t size)
3936e4d4ddSMarco Elver {
4036e4d4ddSMarco Elver 	kasan_check_write(v, size);
4136e4d4ddSMarco Elver 	kcsan_check_write(v, size);
4236e4d4ddSMarco Elver }
4336e4d4ddSMarco Elver 
4436e4d4ddSMarco Elver /**
4500047c2eSMarco Elver  * instrument_read_write - instrument regular read-write access
46*d70e2ecbSRandy Dunlap  * @v: address of access
47*d70e2ecbSRandy Dunlap  * @size: size of access
4800047c2eSMarco Elver  *
4900047c2eSMarco Elver  * Instrument a regular write access. The instrumentation should be inserted
5000047c2eSMarco Elver  * before the actual write happens.
5100047c2eSMarco Elver  */
instrument_read_write(const volatile void * v,size_t size)5200047c2eSMarco Elver static __always_inline void instrument_read_write(const volatile void *v, size_t size)
5300047c2eSMarco Elver {
5400047c2eSMarco Elver 	kasan_check_write(v, size);
5500047c2eSMarco Elver 	kcsan_check_read_write(v, size);
5600047c2eSMarco Elver }
5700047c2eSMarco Elver 
5800047c2eSMarco Elver /**
5936e4d4ddSMarco Elver  * instrument_atomic_read - instrument atomic read access
60*d70e2ecbSRandy Dunlap  * @v: address of access
61*d70e2ecbSRandy Dunlap  * @size: size of access
6236e4d4ddSMarco Elver  *
6336e4d4ddSMarco Elver  * Instrument an atomic read access. The instrumentation should be inserted
6436e4d4ddSMarco Elver  * before the actual read happens.
6536e4d4ddSMarco Elver  */
instrument_atomic_read(const volatile void * v,size_t size)6636e4d4ddSMarco Elver static __always_inline void instrument_atomic_read(const volatile void *v, size_t size)
6736e4d4ddSMarco Elver {
6836e4d4ddSMarco Elver 	kasan_check_read(v, size);
6936e4d4ddSMarco Elver 	kcsan_check_atomic_read(v, size);
7036e4d4ddSMarco Elver }
7136e4d4ddSMarco Elver 
7236e4d4ddSMarco Elver /**
7336e4d4ddSMarco Elver  * instrument_atomic_write - instrument atomic write access
74*d70e2ecbSRandy Dunlap  * @v: address of access
75*d70e2ecbSRandy Dunlap  * @size: size of access
7636e4d4ddSMarco Elver  *
7736e4d4ddSMarco Elver  * Instrument an atomic write access. The instrumentation should be inserted
7836e4d4ddSMarco Elver  * before the actual write happens.
7936e4d4ddSMarco Elver  */
instrument_atomic_write(const volatile void * v,size_t size)8036e4d4ddSMarco Elver static __always_inline void instrument_atomic_write(const volatile void *v, size_t size)
8136e4d4ddSMarco Elver {
8236e4d4ddSMarco Elver 	kasan_check_write(v, size);
8336e4d4ddSMarco Elver 	kcsan_check_atomic_write(v, size);
8436e4d4ddSMarco Elver }
8536e4d4ddSMarco Elver 
8636e4d4ddSMarco Elver /**
8700047c2eSMarco Elver  * instrument_atomic_read_write - instrument atomic read-write access
88*d70e2ecbSRandy Dunlap  * @v: address of access
89*d70e2ecbSRandy Dunlap  * @size: size of access
9000047c2eSMarco Elver  *
9100047c2eSMarco Elver  * Instrument an atomic read-write access. The instrumentation should be
9200047c2eSMarco Elver  * inserted before the actual write happens.
9300047c2eSMarco Elver  */
instrument_atomic_read_write(const volatile void * v,size_t size)9400047c2eSMarco Elver static __always_inline void instrument_atomic_read_write(const volatile void *v, size_t size)
9500047c2eSMarco Elver {
9600047c2eSMarco Elver 	kasan_check_write(v, size);
9700047c2eSMarco Elver 	kcsan_check_atomic_read_write(v, size);
9800047c2eSMarco Elver }
9900047c2eSMarco Elver 
10000047c2eSMarco Elver /**
10136e4d4ddSMarco Elver  * instrument_copy_to_user - instrument reads of copy_to_user
102*d70e2ecbSRandy Dunlap  * @to: destination address
103*d70e2ecbSRandy Dunlap  * @from: source address
104*d70e2ecbSRandy Dunlap  * @n: number of bytes to copy
10536e4d4ddSMarco Elver  *
10636e4d4ddSMarco Elver  * Instrument reads from kernel memory, that are due to copy_to_user (and
10736e4d4ddSMarco Elver  * variants). The instrumentation must be inserted before the accesses.
10836e4d4ddSMarco Elver  */
10936e4d4ddSMarco Elver static __always_inline void
instrument_copy_to_user(void __user * to,const void * from,unsigned long n)11036e4d4ddSMarco Elver instrument_copy_to_user(void __user *to, const void *from, unsigned long n)
11136e4d4ddSMarco Elver {
11236e4d4ddSMarco Elver 	kasan_check_read(from, n);
11336e4d4ddSMarco Elver 	kcsan_check_read(from, n);
11475cf0290SAlexander Potapenko 	kmsan_copy_to_user(to, from, n, 0);
11536e4d4ddSMarco Elver }
11636e4d4ddSMarco Elver 
11736e4d4ddSMarco Elver /**
11833b75c1dSAlexander Potapenko  * instrument_copy_from_user_before - add instrumentation before copy_from_user
119*d70e2ecbSRandy Dunlap  * @to: destination address
120*d70e2ecbSRandy Dunlap  * @from: source address
121*d70e2ecbSRandy Dunlap  * @n: number of bytes to copy
12236e4d4ddSMarco Elver  *
12336e4d4ddSMarco Elver  * Instrument writes to kernel memory, that are due to copy_from_user (and
12436e4d4ddSMarco Elver  * variants). The instrumentation should be inserted before the accesses.
12536e4d4ddSMarco Elver  */
12636e4d4ddSMarco Elver static __always_inline void
instrument_copy_from_user_before(const void * to,const void __user * from,unsigned long n)12733b75c1dSAlexander Potapenko instrument_copy_from_user_before(const void *to, const void __user *from, unsigned long n)
12836e4d4ddSMarco Elver {
12936e4d4ddSMarco Elver 	kasan_check_write(to, n);
13036e4d4ddSMarco Elver 	kcsan_check_write(to, n);
13136e4d4ddSMarco Elver }
13236e4d4ddSMarco Elver 
13333b75c1dSAlexander Potapenko /**
13433b75c1dSAlexander Potapenko  * instrument_copy_from_user_after - add instrumentation after copy_from_user
135*d70e2ecbSRandy Dunlap  * @to: destination address
136*d70e2ecbSRandy Dunlap  * @from: source address
137*d70e2ecbSRandy Dunlap  * @n: number of bytes to copy
138*d70e2ecbSRandy Dunlap  * @left: number of bytes not copied (as returned by copy_from_user)
13933b75c1dSAlexander Potapenko  *
14033b75c1dSAlexander Potapenko  * Instrument writes to kernel memory, that are due to copy_from_user (and
14133b75c1dSAlexander Potapenko  * variants). The instrumentation should be inserted after the accesses.
14233b75c1dSAlexander Potapenko  */
14333b75c1dSAlexander Potapenko static __always_inline void
instrument_copy_from_user_after(const void * to,const void __user * from,unsigned long n,unsigned long left)14433b75c1dSAlexander Potapenko instrument_copy_from_user_after(const void *to, const void __user *from,
14533b75c1dSAlexander Potapenko 				unsigned long n, unsigned long left)
14633b75c1dSAlexander Potapenko {
14775cf0290SAlexander Potapenko 	kmsan_unpoison_memory(to, n - left);
14833b75c1dSAlexander Potapenko }
14933b75c1dSAlexander Potapenko 
150888f84a6SAlexander Potapenko /**
151888f84a6SAlexander Potapenko  * instrument_get_user() - add instrumentation to get_user()-like macros
152*d70e2ecbSRandy Dunlap  * @to: destination variable, may not be address-taken
153888f84a6SAlexander Potapenko  *
154888f84a6SAlexander Potapenko  * get_user() and friends are fragile, so it may depend on the implementation
155888f84a6SAlexander Potapenko  * whether the instrumentation happens before or after the data is copied from
156888f84a6SAlexander Potapenko  * the userspace.
157888f84a6SAlexander Potapenko  */
158888f84a6SAlexander Potapenko #define instrument_get_user(to)				\
159888f84a6SAlexander Potapenko ({							\
16075cf0290SAlexander Potapenko 	u64 __tmp = (u64)(to);				\
16175cf0290SAlexander Potapenko 	kmsan_unpoison_memory(&__tmp, sizeof(__tmp));	\
16275cf0290SAlexander Potapenko 	to = __tmp;					\
163888f84a6SAlexander Potapenko })
164888f84a6SAlexander Potapenko 
16575cf0290SAlexander Potapenko 
166888f84a6SAlexander Potapenko /**
167888f84a6SAlexander Potapenko  * instrument_put_user() - add instrumentation to put_user()-like macros
168*d70e2ecbSRandy Dunlap  * @from: source address
169*d70e2ecbSRandy Dunlap  * @ptr: userspace pointer to copy to
170*d70e2ecbSRandy Dunlap  * @size: number of bytes to copy
171888f84a6SAlexander Potapenko  *
172888f84a6SAlexander Potapenko  * put_user() and friends are fragile, so it may depend on the implementation
173888f84a6SAlexander Potapenko  * whether the instrumentation happens before or after the data is copied from
174888f84a6SAlexander Potapenko  * the userspace.
175888f84a6SAlexander Potapenko  */
176888f84a6SAlexander Potapenko #define instrument_put_user(from, ptr, size)			\
177888f84a6SAlexander Potapenko ({								\
17875cf0290SAlexander Potapenko 	kmsan_copy_to_user(ptr, &from, sizeof(from), 0);	\
179888f84a6SAlexander Potapenko })
180888f84a6SAlexander Potapenko 
18136e4d4ddSMarco Elver #endif /* _LINUX_INSTRUMENTED_H */
182