Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0 */
2 :
3 : /*
4 : * This header provides generic wrappers for memory access instrumentation that
5 : * the compiler cannot emit for: KASAN, KCSAN, KMSAN.
6 : */
7 : #ifndef _LINUX_INSTRUMENTED_H
8 : #define _LINUX_INSTRUMENTED_H
9 :
10 : #include <linux/compiler.h>
11 : #include <linux/kasan-checks.h>
12 : #include <linux/kcsan-checks.h>
13 : #include <linux/kmsan-checks.h>
14 : #include <linux/types.h>
15 :
16 : /**
17 : * instrument_read - instrument regular read access
18 : * @v: address of access
19 : * @size: size of access
20 : *
21 : * Instrument a regular read access. The instrumentation should be inserted
22 : * before the actual read happens.
23 : */
24 : static __always_inline void instrument_read(const volatile void *v, size_t size)
25 : {
26 : kasan_check_read(v, size);
27 : kcsan_check_read(v, size);
28 : }
29 :
30 : /**
31 : * instrument_write - instrument regular write access
32 : * @v: address of access
33 : * @size: size of access
34 : *
35 : * Instrument a regular write access. The instrumentation should be inserted
36 : * before the actual write happens.
37 : */
38 : static __always_inline void instrument_write(const volatile void *v, size_t size)
39 : {
40 14701243 : kasan_check_write(v, size);
41 14701243 : kcsan_check_write(v, size);
42 : }
43 :
44 : /**
45 : * instrument_read_write - instrument regular read-write access
46 : * @v: address of access
47 : * @size: size of access
48 : *
49 : * Instrument a regular write access. The instrumentation should be inserted
50 : * before the actual write happens.
51 : */
52 : static __always_inline void instrument_read_write(const volatile void *v, size_t size)
53 : {
54 758 : kasan_check_write(v, size);
55 758 : kcsan_check_read_write(v, size);
56 : }
57 :
58 : /**
59 : * instrument_atomic_read - instrument atomic read access
60 : * @v: address of access
61 : * @size: size of access
62 : *
63 : * Instrument an atomic read access. The instrumentation should be inserted
64 : * before the actual read happens.
65 : */
66 : static __always_inline void instrument_atomic_read(const volatile void *v, size_t size)
67 : {
68 152827805 : kasan_check_read(v, size);
69 152827805 : kcsan_check_atomic_read(v, size);
70 : }
71 :
72 : /**
73 : * instrument_atomic_write - instrument atomic write access
74 : * @v: address of access
75 : * @size: size of access
76 : *
77 : * Instrument an atomic write access. The instrumentation should be inserted
78 : * before the actual write happens.
79 : */
80 : static __always_inline void instrument_atomic_write(const volatile void *v, size_t size)
81 : {
82 8257971 : kasan_check_write(v, size);
83 8257971 : kcsan_check_atomic_write(v, size);
84 : }
85 :
86 : /**
87 : * instrument_atomic_read_write - instrument atomic read-write access
88 : * @v: address of access
89 : * @size: size of access
90 : *
91 : * Instrument an atomic read-write access. The instrumentation should be
92 : * inserted before the actual write happens.
93 : */
94 : static __always_inline void instrument_atomic_read_write(const volatile void *v, size_t size)
95 : {
96 249189 : kasan_check_write(v, size);
97 249189 : kcsan_check_atomic_read_write(v, size);
98 : }
99 :
100 : /**
101 : * instrument_copy_to_user - instrument reads of copy_to_user
102 : * @to: destination address
103 : * @from: source address
104 : * @n: number of bytes to copy
105 : *
106 : * Instrument reads from kernel memory, that are due to copy_to_user (and
107 : * variants). The instrumentation must be inserted before the accesses.
108 : */
109 : static __always_inline void
110 : instrument_copy_to_user(void __user *to, const void *from, unsigned long n)
111 : {
112 0 : kasan_check_read(from, n);
113 0 : kcsan_check_read(from, n);
114 0 : kmsan_copy_to_user(to, from, n, 0);
115 : }
116 :
117 : /**
118 : * instrument_copy_from_user_before - add instrumentation before copy_from_user
119 : * @to: destination address
120 : * @from: source address
121 : * @n: number of bytes to copy
122 : *
123 : * Instrument writes to kernel memory, that are due to copy_from_user (and
124 : * variants). The instrumentation should be inserted before the accesses.
125 : */
126 : static __always_inline void
127 : instrument_copy_from_user_before(const void *to, const void __user *from, unsigned long n)
128 : {
129 0 : kasan_check_write(to, n);
130 0 : kcsan_check_write(to, n);
131 : }
132 :
133 : /**
134 : * instrument_copy_from_user_after - add instrumentation after copy_from_user
135 : * @to: destination address
136 : * @from: source address
137 : * @n: number of bytes to copy
138 : * @left: number of bytes not copied (as returned by copy_from_user)
139 : *
140 : * Instrument writes to kernel memory, that are due to copy_from_user (and
141 : * variants). The instrumentation should be inserted after the accesses.
142 : */
143 : static __always_inline void
144 : instrument_copy_from_user_after(const void *to, const void __user *from,
145 : unsigned long n, unsigned long left)
146 : {
147 0 : kmsan_unpoison_memory(to, n - left);
148 : }
149 :
150 : /**
151 : * instrument_get_user() - add instrumentation to get_user()-like macros
152 : * @to: destination variable, may not be address-taken
153 : *
154 : * get_user() and friends are fragile, so it may depend on the implementation
155 : * whether the instrumentation happens before or after the data is copied from
156 : * the userspace.
157 : */
158 : #define instrument_get_user(to) \
159 : ({ \
160 : u64 __tmp = (u64)(to); \
161 : kmsan_unpoison_memory(&__tmp, sizeof(__tmp)); \
162 : to = __tmp; \
163 : })
164 :
165 :
166 : /**
167 : * instrument_put_user() - add instrumentation to put_user()-like macros
168 : * @from: source address
169 : * @ptr: userspace pointer to copy to
170 : * @size: number of bytes to copy
171 : *
172 : * put_user() and friends are fragile, so it may depend on the implementation
173 : * whether the instrumentation happens before or after the data is copied from
174 : * the userspace.
175 : */
176 : #define instrument_put_user(from, ptr, size) \
177 : ({ \
178 : kmsan_copy_to_user(ptr, &from, sizeof(from), 0); \
179 : })
180 :
181 : #endif /* _LINUX_INSTRUMENTED_H */
|