1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_FORTIFY_STRING_H_
3 #define _LINUX_FORTIFY_STRING_H_
4 
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)");
12 
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;							\
25 })
26 
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 
strncpy(char * p,const char * q,__kernel_size_t size)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 
strcat(char * p,const char * q)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 
73 extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
strnlen(const char * p,__kernel_size_t maxlen)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);
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 	}
86 
87 	/* Do not check characters beyond the end of p. */
88 	ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
89 	if (p_size <= ret && maxlen != ret)
90 		fortify_panic(__func__);
91 	return ret;
92 }
93 
94 /* defined after fortified strnlen to reuse it. */
strlen(const char * p)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 
100 	/* Give up if we don't know how large p is. */
101 	if (p_size == (size_t)-1)
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 
109 /* defined after fortified strlen to reuse it */
110 extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
strlcpy(char * p,const char * q,size_t size)111 __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
112 {
113 	size_t p_size = __builtin_object_size(p, 1);
114 	size_t q_size = __builtin_object_size(q, 1);
115 	size_t q_len;	/* Full count of source string length. */
116 	size_t len;	/* Count of characters going into destination. */
117 
118 	if (p_size == (size_t)-1 && q_size == (size_t)-1)
119 		return __real_strlcpy(p, q, size);
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)
125 			__write_overflow();
126 	}
127 	if (size) {
128 		if (len >= p_size)
129 			fortify_panic(__func__);
130 		__underlying_memcpy(p, q, len);
131 		p[len] = '\0';
132 	}
133 	return q_len;
134 }
135 
136 /* defined after fortified strnlen to reuse it */
137 extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy);
strscpy(char * p,const char * q,size_t size)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 */
strncat(char * p,const char * q,__kernel_size_t count)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 
memset(void * p,int c,__kernel_size_t size)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 
memcpy(void * p,const void * q,__kernel_size_t size)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 
memmove(void * p,const void * q,__kernel_size_t size)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);
memscan(void * p,int c,__kernel_size_t size)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 
memcmp(const void * p,const void * q,__kernel_size_t size)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 
memchr(const void * p,int c,__kernel_size_t size)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);
memchr_inv(const void * p,int c,size_t size)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);
kmemdup(const void * p,size_t size,gfp_t gfp)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 */
strcpy(char * p,const char * q)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;
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. */
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_ */
340