Commit | Line | Data |
---|---|---|
a28a6e86 FL |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _LINUX_FORTIFY_STRING_H_ | |
3 | #define _LINUX_FORTIFY_STRING_H_ | |
4 | ||
c430f600 KC |
5 | #define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline)) |
6 | #define __RENAME(x) __asm__(#x) | |
7 | ||
8 | void fortify_panic(const char *name) __noreturn __cold; | |
9 | void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)"); | |
10 | void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)"); | |
11 | void __write_overflow(void) __compiletime_error("detected write beyond size of object (1st parameter)"); | |
a28a6e86 | 12 | |
95cadae3 QC |
13 | #define __compiletime_strlen(p) \ |
14 | ({ \ | |
15 | unsigned char *__p = (unsigned char *)(p); \ | |
16 | size_t __ret = (size_t)-1; \ | |
17 | size_t __p_size = __builtin_object_size(p, 1); \ | |
18 | if (__p_size != (size_t)-1) { \ | |
19 | size_t __p_len = __p_size - 1; \ | |
20 | if (__builtin_constant_p(__p[__p_len]) && \ | |
21 | __p[__p_len] == '\0') \ | |
22 | __ret = __builtin_strlen(__p); \ | |
23 | } \ | |
24 | __ret; \ | |
3009f891 KC |
25 | }) |
26 | ||
a28a6e86 FL |
27 | #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) |
28 | extern void *__underlying_memchr(const void *p, int c, __kernel_size_t size) __RENAME(memchr); | |
29 | extern int __underlying_memcmp(const void *p, const void *q, __kernel_size_t size) __RENAME(memcmp); | |
30 | extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy); | |
31 | extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove); | |
32 | extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset); | |
33 | extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat); | |
34 | extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy); | |
35 | extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen); | |
36 | extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat); | |
37 | extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy); | |
38 | #else | |
39 | #define __underlying_memchr __builtin_memchr | |
40 | #define __underlying_memcmp __builtin_memcmp | |
41 | #define __underlying_memcpy __builtin_memcpy | |
42 | #define __underlying_memmove __builtin_memmove | |
43 | #define __underlying_memset __builtin_memset | |
44 | #define __underlying_strcat __builtin_strcat | |
45 | #define __underlying_strcpy __builtin_strcpy | |
46 | #define __underlying_strlen __builtin_strlen | |
47 | #define __underlying_strncat __builtin_strncat | |
48 | #define __underlying_strncpy __builtin_strncpy | |
49 | #endif | |
50 | ||
51 | __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size) | |
52 | { | |
53 | size_t p_size = __builtin_object_size(p, 1); | |
54 | ||
55 | if (__builtin_constant_p(size) && p_size < size) | |
56 | __write_overflow(); | |
57 | if (p_size < size) | |
58 | fortify_panic(__func__); | |
59 | return __underlying_strncpy(p, q, size); | |
60 | } | |
61 | ||
62 | __FORTIFY_INLINE char *strcat(char *p, const char *q) | |
63 | { | |
64 | size_t p_size = __builtin_object_size(p, 1); | |
65 | ||
66 | if (p_size == (size_t)-1) | |
67 | return __underlying_strcat(p, q); | |
68 | if (strlcat(p, q, p_size) >= p_size) | |
69 | fortify_panic(__func__); | |
70 | return p; | |
71 | } | |
72 | ||
369cd216 KC |
73 | extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen); |
74 | __FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen) | |
75 | { | |
76 | size_t p_size = __builtin_object_size(p, 1); | |
3009f891 KC |
77 | size_t p_len = __compiletime_strlen(p); |
78 | size_t ret; | |
79 | ||
80 | /* We can take compile-time actions when maxlen is const. */ | |
81 | if (__builtin_constant_p(maxlen) && p_len != (size_t)-1) { | |
82 | /* If p is const, we can use its compile-time-known len. */ | |
83 | if (maxlen >= p_size) | |
84 | return p_len; | |
85 | } | |
369cd216 | 86 | |
3009f891 KC |
87 | /* Do not check characters beyond the end of p. */ |
88 | ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size); | |
369cd216 KC |
89 | if (p_size <= ret && maxlen != ret) |
90 | fortify_panic(__func__); | |
91 | return ret; | |
92 | } | |
93 | ||
3009f891 | 94 | /* defined after fortified strnlen to reuse it. */ |
a28a6e86 FL |
95 | __FORTIFY_INLINE __kernel_size_t strlen(const char *p) |
96 | { | |
97 | __kernel_size_t ret; | |
98 | size_t p_size = __builtin_object_size(p, 1); | |
99 | ||
3009f891 KC |
100 | /* Give up if we don't know how large p is. */ |
101 | if (p_size == (size_t)-1) | |
a28a6e86 FL |
102 | return __underlying_strlen(p); |
103 | ret = strnlen(p, p_size); | |
104 | if (p_size <= ret) | |
105 | fortify_panic(__func__); | |
106 | return ret; | |
107 | } | |
108 | ||
a28a6e86 FL |
109 | /* defined after fortified strlen to reuse it */ |
110 | extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy); | |
111 | __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size) | |
112 | { | |
a28a6e86 FL |
113 | size_t p_size = __builtin_object_size(p, 1); |
114 | size_t q_size = __builtin_object_size(q, 1); | |
3009f891 KC |
115 | size_t q_len; /* Full count of source string length. */ |
116 | size_t len; /* Count of characters going into destination. */ | |
a28a6e86 FL |
117 | |
118 | if (p_size == (size_t)-1 && q_size == (size_t)-1) | |
119 | return __real_strlcpy(p, q, size); | |
3009f891 KC |
120 | q_len = strlen(q); |
121 | len = (q_len >= size) ? size - 1 : q_len; | |
122 | if (__builtin_constant_p(size) && __builtin_constant_p(q_len) && size) { | |
123 | /* Write size is always larger than destination. */ | |
124 | if (len >= p_size) | |
a28a6e86 | 125 | __write_overflow(); |
3009f891 KC |
126 | } |
127 | if (size) { | |
a28a6e86 FL |
128 | if (len >= p_size) |
129 | fortify_panic(__func__); | |
130 | __underlying_memcpy(p, q, len); | |
131 | p[len] = '\0'; | |
132 | } | |
3009f891 | 133 | return q_len; |
a28a6e86 FL |
134 | } |
135 | ||
136 | /* defined after fortified strnlen to reuse it */ | |
137 | extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy); | |
138 | __FORTIFY_INLINE ssize_t strscpy(char *p, const char *q, size_t size) | |
139 | { | |
140 | size_t len; | |
141 | /* Use string size rather than possible enclosing struct size. */ | |
142 | size_t p_size = __builtin_object_size(p, 1); | |
143 | size_t q_size = __builtin_object_size(q, 1); | |
144 | ||
145 | /* If we cannot get size of p and q default to call strscpy. */ | |
146 | if (p_size == (size_t) -1 && q_size == (size_t) -1) | |
147 | return __real_strscpy(p, q, size); | |
148 | ||
149 | /* | |
150 | * If size can be known at compile time and is greater than | |
151 | * p_size, generate a compile time write overflow error. | |
152 | */ | |
153 | if (__builtin_constant_p(size) && size > p_size) | |
154 | __write_overflow(); | |
155 | ||
156 | /* | |
157 | * This call protects from read overflow, because len will default to q | |
158 | * length if it smaller than size. | |
159 | */ | |
160 | len = strnlen(q, size); | |
161 | /* | |
162 | * If len equals size, we will copy only size bytes which leads to | |
163 | * -E2BIG being returned. | |
164 | * Otherwise we will copy len + 1 because of the final '\O'. | |
165 | */ | |
166 | len = len == size ? size : len + 1; | |
167 | ||
168 | /* | |
169 | * Generate a runtime write overflow error if len is greater than | |
170 | * p_size. | |
171 | */ | |
172 | if (len > p_size) | |
173 | fortify_panic(__func__); | |
174 | ||
175 | /* | |
176 | * We can now safely call vanilla strscpy because we are protected from: | |
177 | * 1. Read overflow thanks to call to strnlen(). | |
178 | * 2. Write overflow thanks to above ifs. | |
179 | */ | |
180 | return __real_strscpy(p, q, len); | |
181 | } | |
182 | ||
183 | /* defined after fortified strlen and strnlen to reuse them */ | |
184 | __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count) | |
185 | { | |
186 | size_t p_len, copy_len; | |
187 | size_t p_size = __builtin_object_size(p, 1); | |
188 | size_t q_size = __builtin_object_size(q, 1); | |
189 | ||
190 | if (p_size == (size_t)-1 && q_size == (size_t)-1) | |
191 | return __underlying_strncat(p, q, count); | |
192 | p_len = strlen(p); | |
193 | copy_len = strnlen(q, count); | |
194 | if (p_size < p_len + copy_len + 1) | |
195 | fortify_panic(__func__); | |
196 | __underlying_memcpy(p + p_len, q, copy_len); | |
197 | p[p_len + copy_len] = '\0'; | |
198 | return p; | |
199 | } | |
200 | ||
201 | __FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size) | |
202 | { | |
203 | size_t p_size = __builtin_object_size(p, 0); | |
204 | ||
205 | if (__builtin_constant_p(size) && p_size < size) | |
206 | __write_overflow(); | |
207 | if (p_size < size) | |
208 | fortify_panic(__func__); | |
209 | return __underlying_memset(p, c, size); | |
210 | } | |
211 | ||
212 | __FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size) | |
213 | { | |
214 | size_t p_size = __builtin_object_size(p, 0); | |
215 | size_t q_size = __builtin_object_size(q, 0); | |
216 | ||
217 | if (__builtin_constant_p(size)) { | |
218 | if (p_size < size) | |
219 | __write_overflow(); | |
220 | if (q_size < size) | |
221 | __read_overflow2(); | |
222 | } | |
223 | if (p_size < size || q_size < size) | |
224 | fortify_panic(__func__); | |
225 | return __underlying_memcpy(p, q, size); | |
226 | } | |
227 | ||
228 | __FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size) | |
229 | { | |
230 | size_t p_size = __builtin_object_size(p, 0); | |
231 | size_t q_size = __builtin_object_size(q, 0); | |
232 | ||
233 | if (__builtin_constant_p(size)) { | |
234 | if (p_size < size) | |
235 | __write_overflow(); | |
236 | if (q_size < size) | |
237 | __read_overflow2(); | |
238 | } | |
239 | if (p_size < size || q_size < size) | |
240 | fortify_panic(__func__); | |
241 | return __underlying_memmove(p, q, size); | |
242 | } | |
243 | ||
244 | extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan); | |
245 | __FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size) | |
246 | { | |
247 | size_t p_size = __builtin_object_size(p, 0); | |
248 | ||
249 | if (__builtin_constant_p(size) && p_size < size) | |
250 | __read_overflow(); | |
251 | if (p_size < size) | |
252 | fortify_panic(__func__); | |
253 | return __real_memscan(p, c, size); | |
254 | } | |
255 | ||
256 | __FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size) | |
257 | { | |
258 | size_t p_size = __builtin_object_size(p, 0); | |
259 | size_t q_size = __builtin_object_size(q, 0); | |
260 | ||
261 | if (__builtin_constant_p(size)) { | |
262 | if (p_size < size) | |
263 | __read_overflow(); | |
264 | if (q_size < size) | |
265 | __read_overflow2(); | |
266 | } | |
267 | if (p_size < size || q_size < size) | |
268 | fortify_panic(__func__); | |
269 | return __underlying_memcmp(p, q, size); | |
270 | } | |
271 | ||
272 | __FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size) | |
273 | { | |
274 | size_t p_size = __builtin_object_size(p, 0); | |
275 | ||
276 | if (__builtin_constant_p(size) && p_size < size) | |
277 | __read_overflow(); | |
278 | if (p_size < size) | |
279 | fortify_panic(__func__); | |
280 | return __underlying_memchr(p, c, size); | |
281 | } | |
282 | ||
283 | void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv); | |
284 | __FORTIFY_INLINE void *memchr_inv(const void *p, int c, size_t size) | |
285 | { | |
286 | size_t p_size = __builtin_object_size(p, 0); | |
287 | ||
288 | if (__builtin_constant_p(size) && p_size < size) | |
289 | __read_overflow(); | |
290 | if (p_size < size) | |
291 | fortify_panic(__func__); | |
292 | return __real_memchr_inv(p, c, size); | |
293 | } | |
294 | ||
295 | extern void *__real_kmemdup(const void *src, size_t len, gfp_t gfp) __RENAME(kmemdup); | |
296 | __FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp) | |
297 | { | |
298 | size_t p_size = __builtin_object_size(p, 0); | |
299 | ||
300 | if (__builtin_constant_p(size) && p_size < size) | |
301 | __read_overflow(); | |
302 | if (p_size < size) | |
303 | fortify_panic(__func__); | |
304 | return __real_kmemdup(p, size, gfp); | |
305 | } | |
306 | ||
307 | /* defined after fortified strlen and memcpy to reuse them */ | |
308 | __FORTIFY_INLINE char *strcpy(char *p, const char *q) | |
309 | { | |
310 | size_t p_size = __builtin_object_size(p, 1); | |
311 | size_t q_size = __builtin_object_size(q, 1); | |
312 | size_t size; | |
313 | ||
314 | if (p_size == (size_t)-1 && q_size == (size_t)-1) | |
315 | return __underlying_strcpy(p, q); | |
316 | size = strlen(q) + 1; | |
072af0c6 KC |
317 | /* Compile-time check for const size overflow. */ |
318 | if (__builtin_constant_p(size) && p_size < size) | |
319 | __write_overflow(); | |
320 | /* Run-time check for dynamic size overflow. */ | |
a28a6e86 FL |
321 | if (p_size < size) |
322 | fortify_panic(__func__); | |
323 | memcpy(p, q, size); | |
324 | return p; | |
325 | } | |
326 | ||
327 | /* Don't use these outside the FORITFY_SOURCE implementation */ | |
328 | #undef __underlying_memchr | |
329 | #undef __underlying_memcmp | |
330 | #undef __underlying_memcpy | |
331 | #undef __underlying_memmove | |
332 | #undef __underlying_memset | |
333 | #undef __underlying_strcat | |
334 | #undef __underlying_strcpy | |
335 | #undef __underlying_strlen | |
336 | #undef __underlying_strncat | |
337 | #undef __underlying_strncpy | |
338 | ||
339 | #endif /* _LINUX_FORTIFY_STRING_H_ */ |