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
18d70e2ecbSRandy Dunlap * @v: address of access
19d70e2ecbSRandy 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
32d70e2ecbSRandy Dunlap * @v: address of access
33d70e2ecbSRandy 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
46d70e2ecbSRandy Dunlap * @v: address of access
47d70e2ecbSRandy 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
60d70e2ecbSRandy Dunlap * @v: address of access
61d70e2ecbSRandy 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
74d70e2ecbSRandy Dunlap * @v: address of access
75d70e2ecbSRandy 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
88d70e2ecbSRandy Dunlap * @v: address of access
89d70e2ecbSRandy 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
102d70e2ecbSRandy Dunlap * @to: destination address
103d70e2ecbSRandy Dunlap * @from: source address
104d70e2ecbSRandy 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
119d70e2ecbSRandy Dunlap * @to: destination address
120d70e2ecbSRandy Dunlap * @from: source address
121d70e2ecbSRandy 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
135d70e2ecbSRandy Dunlap * @to: destination address
136d70e2ecbSRandy Dunlap * @from: source address
137d70e2ecbSRandy Dunlap * @n: number of bytes to copy
138d70e2ecbSRandy 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 /**
151*922621a6SAlexander Potapenko * instrument_memcpy_before - add instrumentation before non-instrumented memcpy
152*922621a6SAlexander Potapenko * @to: destination address
153*922621a6SAlexander Potapenko * @from: source address
154*922621a6SAlexander Potapenko * @n: number of bytes to copy
155*922621a6SAlexander Potapenko *
156*922621a6SAlexander Potapenko * Instrument memory accesses that happen in custom memcpy implementations. The
157*922621a6SAlexander Potapenko * instrumentation should be inserted before the memcpy call.
158*922621a6SAlexander Potapenko */
instrument_memcpy_before(void * to,const void * from,unsigned long n)159*922621a6SAlexander Potapenko static __always_inline void instrument_memcpy_before(void *to, const void *from,
160*922621a6SAlexander Potapenko unsigned long n)
161*922621a6SAlexander Potapenko {
162*922621a6SAlexander Potapenko kasan_check_write(to, n);
163*922621a6SAlexander Potapenko kasan_check_read(from, n);
164*922621a6SAlexander Potapenko kcsan_check_write(to, n);
165*922621a6SAlexander Potapenko kcsan_check_read(from, n);
166*922621a6SAlexander Potapenko }
167*922621a6SAlexander Potapenko
168*922621a6SAlexander Potapenko /**
169*922621a6SAlexander Potapenko * instrument_memcpy_after - add instrumentation after non-instrumented memcpy
170*922621a6SAlexander Potapenko * @to: destination address
171*922621a6SAlexander Potapenko * @from: source address
172*922621a6SAlexander Potapenko * @n: number of bytes to copy
173*922621a6SAlexander Potapenko * @left: number of bytes not copied (if known)
174*922621a6SAlexander Potapenko *
175*922621a6SAlexander Potapenko * Instrument memory accesses that happen in custom memcpy implementations. The
176*922621a6SAlexander Potapenko * instrumentation should be inserted after the memcpy call.
177*922621a6SAlexander Potapenko */
instrument_memcpy_after(void * to,const void * from,unsigned long n,unsigned long left)178*922621a6SAlexander Potapenko static __always_inline void instrument_memcpy_after(void *to, const void *from,
179*922621a6SAlexander Potapenko unsigned long n,
180*922621a6SAlexander Potapenko unsigned long left)
181*922621a6SAlexander Potapenko {
182*922621a6SAlexander Potapenko kmsan_memmove(to, from, n - left);
183*922621a6SAlexander Potapenko }
184*922621a6SAlexander Potapenko
185*922621a6SAlexander Potapenko /**
186888f84a6SAlexander Potapenko * instrument_get_user() - add instrumentation to get_user()-like macros
187d70e2ecbSRandy Dunlap * @to: destination variable, may not be address-taken
188888f84a6SAlexander Potapenko *
189888f84a6SAlexander Potapenko * get_user() and friends are fragile, so it may depend on the implementation
190888f84a6SAlexander Potapenko * whether the instrumentation happens before or after the data is copied from
191888f84a6SAlexander Potapenko * the userspace.
192888f84a6SAlexander Potapenko */
193888f84a6SAlexander Potapenko #define instrument_get_user(to) \
194888f84a6SAlexander Potapenko ({ \
19575cf0290SAlexander Potapenko u64 __tmp = (u64)(to); \
19675cf0290SAlexander Potapenko kmsan_unpoison_memory(&__tmp, sizeof(__tmp)); \
19775cf0290SAlexander Potapenko to = __tmp; \
198888f84a6SAlexander Potapenko })
199888f84a6SAlexander Potapenko
20075cf0290SAlexander Potapenko
201888f84a6SAlexander Potapenko /**
202888f84a6SAlexander Potapenko * instrument_put_user() - add instrumentation to put_user()-like macros
203d70e2ecbSRandy Dunlap * @from: source address
204d70e2ecbSRandy Dunlap * @ptr: userspace pointer to copy to
205d70e2ecbSRandy Dunlap * @size: number of bytes to copy
206888f84a6SAlexander Potapenko *
207888f84a6SAlexander Potapenko * put_user() and friends are fragile, so it may depend on the implementation
208888f84a6SAlexander Potapenko * whether the instrumentation happens before or after the data is copied from
209888f84a6SAlexander Potapenko * the userspace.
210888f84a6SAlexander Potapenko */
211888f84a6SAlexander Potapenko #define instrument_put_user(from, ptr, size) \
212888f84a6SAlexander Potapenko ({ \
21375cf0290SAlexander Potapenko kmsan_copy_to_user(ptr, &from, sizeof(from), 0); \
214888f84a6SAlexander Potapenko })
215888f84a6SAlexander Potapenko
21636e4d4ddSMarco Elver #endif /* _LINUX_INSTRUMENTED_H */
217