History

Merge tag 'memcpy-v5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull FORTIFY_SOURCE updates from Kees Cook: "This series consists of two halves: - strict compile-time buffer size checking under FORTIFY_SOURCE for the memcpy()-family of functions (for extensive details and rationale, see the first commit) - enabling FORTIFY_SOURCE for Clang, which has had many overlapping bugs that we've finally worked past" * tag 'memcpy-v5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: fortify: Add Clang support fortify: Make sure strlen() may still be used as a constant expression fortify: Use __diagnose_as() for better diagnostic coverage fortify: Make pointer arguments const Compiler Attributes: Add __diagnose_as for Clang Compiler Attributes: Add __overloadable for Clang Compiler Attributes: Add __pass_object_size for Clang fortify: Replace open-coded __gnu_inline attribute fortify: Update compile-time tests for Clang 14 fortify: Detect struct member overflows in memset() at compile-time fortify: Detect struct member overflows in memmove() at compile-time fortify: Detect struct member overflows in memcpy() at compile-time

Linus Torvalds committed 4 years ago

Commit 4be240b2 parents 3f72821 281d0c913 files · +272 −56Browse files

Unified · Split

13 files
  1. arch/x86/boot/compressed/misc.c +2 −1
  2. arch/x86/lib/memcpy_32.c +1 −0
  3. include/linux/compiler_attributes.h +39 −0
  4. include/linux/fortify-string.h +188 −50
  5. lib/Makefile +2 −1
  6. lib/string_helpers.c +6 −0
  7. lib/test_fortify/read_overflow2_field-memcpy.c +5 −0
  8. lib/test_fortify/read_overflow2_field-memmove.c +5 −0
  9. lib/test_fortify/write_overflow_field-memcpy.c +5 −0
  10. lib/test_fortify/write_overflow_field-memmove.c +5 −0
  11. lib/test_fortify/write_overflow_field-memset.c +5 −0
  12. scripts/test_fortify.sh +6 −2
  13. security/Kconfig +3 −2
arch/x86/boot/compressed/misc.c+2−1
@@ -37,10 +37,11 @@ · 36 unmodified lines
37 * try to define their own functions if these are not defined as macros.37 * try to define their own functions if these are not defined as macros.
38 */38 */
39#define memzero(s, n) memset((s), 0, (n))39#define memzero(s, n) memset((s), 0, (n))
40#ifndef memmove
40#define memmove memmove41#define memmove memmove
41
42/* Functions used by the included decompressor code below. */42/* Functions used by the included decompressor code below. */
43void *memmove(void *dest, const void *src, size_t n);43void *memmove(void *dest, const void *src, size_t n);
44#endif
44 45
45/*46/*
46 * This is set up by the setup-routine at boot-time47 * This is set up by the setup-routine at boot-time
arch/x86/lib/memcpy_32.c+1−0
@@ -4,6 +4,7 @@ · 3 unmodified lines
4 4
5#undef memcpy5#undef memcpy
6#undef memset6#undef memset
7#undef memmove
7 8
8__visible void *memcpy(void *to, const void *from, size_t n)9__visible void *memcpy(void *to, const void *from, size_t n)
9{10{
include/linux/compiler_attributes.h+39−0
@@ -100,6 +100,19 @@ · 99 unmodified lines
100# define __copy(symbol)100# define __copy(symbol)
101#endif101#endif
102 102
103/*
104 * Optional: not supported by gcc
105 * Optional: only supported since clang >= 14.0
106 * Optional: not supported by icc
107 *
108 * clang: https://clang.llvm.org/docs/AttributeReference.html#diagnose_as_builtin
109 */
110#if __has_attribute(__diagnose_as_builtin__)
111# define __diagnose_as(builtin...) __attribute__((__diagnose_as_builtin__(builtin)))
112#else
113# define __diagnose_as(builtin...)
114#endif
115
103/*116/*
104 * Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated'117 * Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated'
105 * attribute warnings entirely and for good") for more information.118 * attribute warnings entirely and for good") for more information.
@@ -257,12 +270,38 @@ · 151 unmodified lines
257 */270 */
258#define __noreturn __attribute__((__noreturn__))271#define __noreturn __attribute__((__noreturn__))
259 272
273/*
274 * Optional: not supported by gcc.
275 * Optional: not supported by icc.
276 *
277 * clang: https://clang.llvm.org/docs/AttributeReference.html#overloadable
278 */
279#if __has_attribute(__overloadable__)
280# define __overloadable __attribute__((__overloadable__))
281#else
282# define __overloadable
283#endif
284
260/*285/*
261 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute286 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute
262 * clang: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute287 * clang: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
263 */288 */
264#define __packed __attribute__((__packed__))289#define __packed __attribute__((__packed__))
265 290
291/*
292 * Note: the "type" argument should match any __builtin_object_size(p, type) usage.
293 *
294 * Optional: not supported by gcc.
295 * Optional: not supported by icc.
296 *
297 * clang: https://clang.llvm.org/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size
298 */
299#if __has_attribute(__pass_object_size__)
300# define __pass_object_size(type) __attribute__((__pass_object_size__(type)))
301#else
302# define __pass_object_size(type)
303#endif
304
266/*305/*
267 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute306 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
268 */307 */
include/linux/fortify-string.h+188−50
@@ -2,13 +2,17 @@ · 1 unmodified line
2#ifndef _LINUX_FORTIFY_STRING_H_2#ifndef _LINUX_FORTIFY_STRING_H_
3#define _LINUX_FORTIFY_STRING_H_3#define _LINUX_FORTIFY_STRING_H_
4 4
5#define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline))5#include <linux/const.h>
6
7#define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable
6#define __RENAME(x) __asm__(#x)8#define __RENAME(x) __asm__(#x)
7 9
8void fortify_panic(const char *name) __noreturn __cold;10void fortify_panic(const char *name) __noreturn __cold;
9void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)");11void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)");
10void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)");12void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)");
13void __read_overflow2_field(size_t avail, size_t wanted) __compiletime_warning("detected read beyond size of field (2nd parameter); maybe use struct_group()?");
11void __write_overflow(void) __compiletime_error("detected write beyond size of object (1st parameter)");14void __write_overflow(void) __compiletime_error("detected write beyond size of object (1st parameter)");
15void __write_overflow_field(size_t avail, size_t wanted) __compiletime_warning("detected write beyond size of field (1st parameter); maybe use struct_group()?");
12 16
13#define __compiletime_strlen(p) \17#define __compiletime_strlen(p) \
14({ \18({ \
@@ -48,7 +52,17 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) · 33 unmodified lines
48#define __underlying_strncpy __builtin_strncpy52#define __underlying_strncpy __builtin_strncpy
49#endif53#endif
50 54
51__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)55/*
56 * Clang's use of __builtin_object_size() within inlines needs hinting via
57 * __pass_object_size(). The preference is to only ever use type 1 (member
58 * size, rather than struct size), but there remain some stragglers using
59 * type 0 that will be converted in the future.
60 */
61#define POS __pass_object_size(1)
62#define POS0 __pass_object_size(0)
63
64__FORTIFY_INLINE __diagnose_as(__builtin_strncpy, 1, 2, 3)
65char *strncpy(char * const POS p, const char *q, __kernel_size_t size)
52{66{
53 size_t p_size = __builtin_object_size(p, 1);67 size_t p_size = __builtin_object_size(p, 1);
54 68
@@ -59,7 +73,8 @@ __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size) · 4 unmodified lines
59 return __underlying_strncpy(p, q, size);73 return __underlying_strncpy(p, q, size);
60}74}
61 75
62__FORTIFY_INLINE char *strcat(char *p, const char *q)76__FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2)
77char *strcat(char * const POS p, const char *q)
63{78{
64 size_t p_size = __builtin_object_size(p, 1);79 size_t p_size = __builtin_object_size(p, 1);
65 80
@@ -71,7 +86,7 @@ __FORTIFY_INLINE char *strcat(char *p, const char *q) · 5 unmodified lines
71}86}
72 87
73extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);88extern __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)89__FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size_t maxlen)
75{90{
76 size_t p_size = __builtin_object_size(p, 1);91 size_t p_size = __builtin_object_size(p, 1);
77 size_t p_len = __compiletime_strlen(p);92 size_t p_len = __compiletime_strlen(p);
@@ -91,8 +106,16 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen) · 13 unmodified lines
91 return ret;106 return ret;
92}107}
93 108
94/* defined after fortified strnlen to reuse it. */109/*
95__FORTIFY_INLINE __kernel_size_t strlen(const char *p)110 * Defined after fortified strnlen to reuse it. However, it must still be
111 * possible for strlen() to be used on compile-time strings for use in
112 * static initializers (i.e. as a constant expression).
113 */
114#define strlen(p) \
115 __builtin_choose_expr(__is_constexpr(__builtin_strlen(p)), \
116 __builtin_strlen(p), __fortify_strlen(p))
117__FORTIFY_INLINE __diagnose_as(__builtin_strlen, 1)
118__kernel_size_t __fortify_strlen(const char * const POS p)
96{119{
97 __kernel_size_t ret;120 __kernel_size_t ret;
98 size_t p_size = __builtin_object_size(p, 1);121 size_t p_size = __builtin_object_size(p, 1);
@@ -108,7 +131,7 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p) · 9 unmodified lines
108 131
109/* defined after fortified strlen to reuse it */132/* defined after fortified strlen to reuse it */
110extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);133extern 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)134__FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, size_t size)
112{135{
113 size_t p_size = __builtin_object_size(p, 1);136 size_t p_size = __builtin_object_size(p, 1);
114 size_t q_size = __builtin_object_size(q, 1);137 size_t q_size = __builtin_object_size(q, 1);
@@ -135,7 +158,7 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size) · 20 unmodified lines
135 158
136/* defined after fortified strnlen to reuse it */159/* defined after fortified strnlen to reuse it */
137extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy);160extern 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)161__FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, size_t size)
139{162{
140 size_t len;163 size_t len;
141 /* Use string size rather than possible enclosing struct size. */164 /* Use string size rather than possible enclosing struct size. */
@@ -181,7 +204,8 @@ __FORTIFY_INLINE ssize_t strscpy(char *p, const char *q, size_t size) · 39 unmodified lines
181}204}
182 205
183/* defined after fortified strlen and strnlen to reuse them */206/* defined after fortified strlen and strnlen to reuse them */
184__FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)207__FORTIFY_INLINE __diagnose_as(__builtin_strncat, 1, 2, 3)
208char *strncat(char * const POS p, const char * const POS q, __kernel_size_t count)
185{209{
186 size_t p_len, copy_len;210 size_t p_len, copy_len;
187 size_t p_size = __builtin_object_size(p, 1);211 size_t p_size = __builtin_object_size(p, 1);
@@ -198,51 +222,161 @@ __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count) · 10 unmodified lines
198 return p;222 return p;
199}223}
200 224
201__FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size)225__FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size,
226 const size_t p_size,
227 const size_t p_size_field)
202{228{
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)) {229 if (__builtin_constant_p(size)) {
218 if (p_size < size)230 /*
231 * Length argument is a constant expression, so we
232 * can perform compile-time bounds checking where
233 * buffer sizes are known.
234 */
235
236 /* Error when size is larger than enclosing struct. */
237 if (p_size > p_size_field && p_size < size)
219 __write_overflow();238 __write_overflow();
220 if (q_size < size)239
221 __read_overflow2();240 /* Warn when write size is larger than dest field. */
241 if (p_size_field < size)
242 __write_overflow_field(p_size_field, size);
222 }243 }
223 if (p_size < size || q_size < size)244 /*
224 fortify_panic(__func__);245 * At this point, length argument may not be a constant expression,
225 return __underlying_memcpy(p, q, size);246 * so run-time bounds checking can be done where buffer sizes are
247 * known. (This is not an "else" because the above checks may only
248 * be compile-time warnings, and we want to still warn for run-time
249 * overflows.)
250 */
251
252 /*
253 * Always stop accesses beyond the struct that contains the
254 * field, when the buffer's remaining size is known.
255 * (The -1 test is to optimize away checks where the buffer
256 * lengths are unknown.)
257 */
258 if (p_size != (size_t)(-1) && p_size < size)
259 fortify_panic("memset");
226}260}
227 261
228__FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)262#define __fortify_memset_chk(p, c, size, p_size, p_size_field) ({ \
229{263 size_t __fortify_size = (size_t)(size); \
230 size_t p_size = __builtin_object_size(p, 0);264 fortify_memset_chk(__fortify_size, p_size, p_size_field), \
231 size_t q_size = __builtin_object_size(q, 0);265 __underlying_memset(p, c, __fortify_size); \
266})
232 267
268/*
269 * __builtin_object_size() must be captured here to avoid evaluating argument
270 * side-effects further into the macro layers.
271 */
272#define memset(p, c, s) __fortify_memset_chk(p, c, s, \
273 __builtin_object_size(p, 0), __builtin_object_size(p, 1))
274
275/*
276 * To make sure the compiler can enforce protection against buffer overflows,
277 * memcpy(), memmove(), and memset() must not be used beyond individual
278 * struct members. If you need to copy across multiple members, please use
279 * struct_group() to create a named mirror of an anonymous struct union.
280 * (e.g. see struct sk_buff.) Read overflow checking is currently only
281 * done when a write overflow is also present, or when building with W=1.
282 *
283 * Mitigation coverage matrix
284 * Bounds checking at:
285 * +-------+-------+-------+-------+
286 * | Compile time | Run time |
287 * memcpy() argument sizes: | write | read | write | read |
288 * dest source length +-------+-------+-------+-------+
289 * memcpy(known, known, constant) | y | y | n/a | n/a |
290 * memcpy(known, unknown, constant) | y | n | n/a | V |
291 * memcpy(known, known, dynamic) | n | n | B | B |
292 * memcpy(known, unknown, dynamic) | n | n | B | V |
293 * memcpy(unknown, known, constant) | n | y | V | n/a |
294 * memcpy(unknown, unknown, constant) | n | n | V | V |
295 * memcpy(unknown, known, dynamic) | n | n | V | B |
296 * memcpy(unknown, unknown, dynamic) | n | n | V | V |
297 * +-------+-------+-------+-------+
298 *
299 * y = perform deterministic compile-time bounds checking
300 * n = cannot perform deterministic compile-time bounds checking
301 * n/a = no run-time bounds checking needed since compile-time deterministic
302 * B = can perform run-time bounds checking (currently unimplemented)
303 * V = vulnerable to run-time overflow (will need refactoring to solve)
304 *
305 */
306__FORTIFY_INLINE void fortify_memcpy_chk(__kernel_size_t size,
307 const size_t p_size,
308 const size_t q_size,
309 const size_t p_size_field,
310 const size_t q_size_field,
311 const char *func)
312{
233 if (__builtin_constant_p(size)) {313 if (__builtin_constant_p(size)) {
234 if (p_size < size)314 /*
315 * Length argument is a constant expression, so we
316 * can perform compile-time bounds checking where
317 * buffer sizes are known.
318 */
319
320 /* Error when size is larger than enclosing struct. */
321 if (p_size > p_size_field && p_size < size)
235 __write_overflow();322 __write_overflow();
236 if (q_size < size)323 if (q_size > q_size_field && q_size < size)
237 __read_overflow2();324 __read_overflow2();
325
326 /* Warn when write size argument larger than dest field. */
327 if (p_size_field < size)
328 __write_overflow_field(p_size_field, size);
329 /*
330 * Warn for source field over-read when building with W=1
331 * or when an over-write happened, so both can be fixed at
332 * the same time.
333 */
334 if ((IS_ENABLED(KBUILD_EXTRA_WARN1) || p_size_field < size) &&
335 q_size_field < size)
336 __read_overflow2_field(q_size_field, size);
238 }337 }
239 if (p_size < size || q_size < size)338 /*
240 fortify_panic(__func__);339 * At this point, length argument may not be a constant expression,
241 return __underlying_memmove(p, q, size);340 * so run-time bounds checking can be done where buffer sizes are
341 * known. (This is not an "else" because the above checks may only
342 * be compile-time warnings, and we want to still warn for run-time
343 * overflows.)
344 */
345
346 /*
347 * Always stop accesses beyond the struct that contains the
348 * field, when the buffer's remaining size is known.
349 * (The -1 test is to optimize away checks where the buffer
350 * lengths are unknown.)
351 */
352 if ((p_size != (size_t)(-1) && p_size < size) ||
353 (q_size != (size_t)(-1) && q_size < size))
354 fortify_panic(func);
242}355}
243 356
357#define __fortify_memcpy_chk(p, q, size, p_size, q_size, \
358 p_size_field, q_size_field, op) ({ \
359 size_t __fortify_size = (size_t)(size); \
360 fortify_memcpy_chk(__fortify_size, p_size, q_size, \
361 p_size_field, q_size_field, #op); \
362 __underlying_##op(p, q, __fortify_size); \
363})
364
365/*
366 * __builtin_object_size() must be captured here to avoid evaluating argument
367 * side-effects further into the macro layers.
368 */
369#define memcpy(p, q, s) __fortify_memcpy_chk(p, q, s, \
370 __builtin_object_size(p, 0), __builtin_object_size(q, 0), \
371 __builtin_object_size(p, 1), __builtin_object_size(q, 1), \
372 memcpy)
373#define memmove(p, q, s) __fortify_memcpy_chk(p, q, s, \
374 __builtin_object_size(p, 0), __builtin_object_size(q, 0), \
375 __builtin_object_size(p, 1), __builtin_object_size(q, 1), \
376 memmove)
377
244extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);378extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);
245__FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size)379__FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size)
246{380{
247 size_t p_size = __builtin_object_size(p, 0);381 size_t p_size = __builtin_object_size(p, 0);
248 382
@@ -253,7 +387,8 @@ __FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size) · 4 unmodified lines
253 return __real_memscan(p, c, size);387 return __real_memscan(p, c, size);
254}388}
255 389
256__FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size)390__FORTIFY_INLINE __diagnose_as(__builtin_memcmp, 1, 2, 3)
391int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t size)
257{392{
258 size_t p_size = __builtin_object_size(p, 0);393 size_t p_size = __builtin_object_size(p, 0);
259 size_t q_size = __builtin_object_size(q, 0);394 size_t q_size = __builtin_object_size(q, 0);
@@ -269,7 +404,8 @@ __FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size) · 9 unmodified lines
269 return __underlying_memcmp(p, q, size);404 return __underlying_memcmp(p, q, size);
270}405}
271 406
272__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)407__FORTIFY_INLINE __diagnose_as(__builtin_memchr, 1, 2, 3)
408void *memchr(const void * const POS0 p, int c, __kernel_size_t size)
273{409{
274 size_t p_size = __builtin_object_size(p, 0);410 size_t p_size = __builtin_object_size(p, 0);
275 411
@@ -281,7 +417,7 @@ __FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size) · 5 unmodified lines
281}417}
282 418
283void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv);419void *__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)420__FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size)
285{421{
286 size_t p_size = __builtin_object_size(p, 0);422 size_t p_size = __builtin_object_size(p, 0);
287 423
@@ -293,7 +429,7 @@ __FORTIFY_INLINE void *memchr_inv(const void *p, int c, size_t size) · 5 unmodified lines
293}429}
294 430
295extern void *__real_kmemdup(const void *src, size_t len, gfp_t gfp) __RENAME(kmemdup);431extern 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)432__FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp)
297{433{
298 size_t p_size = __builtin_object_size(p, 0);434 size_t p_size = __builtin_object_size(p, 0);
299 435
@@ -304,13 +440,15 @@ __FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp) · 4 unmodified lines
304 return __real_kmemdup(p, size, gfp);440 return __real_kmemdup(p, size, gfp);
305}441}
306 442
307/* defined after fortified strlen and memcpy to reuse them */443/* Defined after fortified strlen to reuse it. */
308__FORTIFY_INLINE char *strcpy(char *p, const char *q)444__FORTIFY_INLINE __diagnose_as(__builtin_strcpy, 1, 2)
445char *strcpy(char * const POS p, const char * const POS q)
309{446{
310 size_t p_size = __builtin_object_size(p, 1);447 size_t p_size = __builtin_object_size(p, 1);
311 size_t q_size = __builtin_object_size(q, 1);448 size_t q_size = __builtin_object_size(q, 1);
312 size_t size;449 size_t size;
313 450
451 /* If neither buffer size is known, immediately give up. */
314 if (p_size == (size_t)-1 && q_size == (size_t)-1)452 if (p_size == (size_t)-1 && q_size == (size_t)-1)
315 return __underlying_strcpy(p, q);453 return __underlying_strcpy(p, q);
316 size = strlen(q) + 1;454 size = strlen(q) + 1;
@@ -320,20 +458,20 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q) · 3 unmodified lines
320 /* Run-time check for dynamic size overflow. */458 /* Run-time check for dynamic size overflow. */
321 if (p_size < size)459 if (p_size < size)
322 fortify_panic(__func__);460 fortify_panic(__func__);
323 memcpy(p, q, size);461 __underlying_memcpy(p, q, size);
324 return p;462 return p;
325}463}
326 464
327/* Don't use these outside the FORITFY_SOURCE implementation */465/* Don't use these outside the FORITFY_SOURCE implementation */
328#undef __underlying_memchr466#undef __underlying_memchr
329#undef __underlying_memcmp467#undef __underlying_memcmp
330#undef __underlying_memcpy
331#undef __underlying_memmove
332#undef __underlying_memset
333#undef __underlying_strcat468#undef __underlying_strcat
334#undef __underlying_strcpy469#undef __underlying_strcpy
335#undef __underlying_strlen470#undef __underlying_strlen
336#undef __underlying_strncat471#undef __underlying_strncat
337#undef __underlying_strncpy472#undef __underlying_strncpy
338 473
474#undef POS
475#undef POS0
476
339#endif /* _LINUX_FORTIFY_STRING_H_ */477#endif /* _LINUX_FORTIFY_STRING_H_ */
lib/Makefile+2−1
@@ -377,7 +377,8 @@ TEST_FORTIFY_LOG = test_fortify.log · 376 unmodified lines
377quiet_cmd_test_fortify = TEST $@377quiet_cmd_test_fortify = TEST $@
378 cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \378 cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \
379 $< $@ "$(NM)" $(CC) $(c_flags) \379 $< $@ "$(NM)" $(CC) $(c_flags) \
380 $(call cc-disable-warning,fortify-source)380 $(call cc-disable-warning,fortify-source) \
381 -DKBUILD_EXTRA_WARN1
381 382
382targets += $(TEST_FORTIFY_LOGS)383targets += $(TEST_FORTIFY_LOGS)
383clean-files += $(TEST_FORTIFY_LOGS)384clean-files += $(TEST_FORTIFY_LOGS)
lib/string_helpers.c+6−0
@@ -968,6 +968,12 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, · 967 unmodified lines
968EXPORT_SYMBOL(memcpy_and_pad);968EXPORT_SYMBOL(memcpy_and_pad);
969 969
970#ifdef CONFIG_FORTIFY_SOURCE970#ifdef CONFIG_FORTIFY_SOURCE
971/* These are placeholders for fortify compile-time warnings. */
972void __read_overflow2_field(size_t avail, size_t wanted) { }
973EXPORT_SYMBOL(__read_overflow2_field);
974void __write_overflow_field(size_t avail, size_t wanted) { }
975EXPORT_SYMBOL(__write_overflow_field);
976
971void fortify_panic(const char *name)977void fortify_panic(const char *name)
972{978{
973 pr_emerg("detected buffer overflow in %s\n", name);979 pr_emerg("detected buffer overflow in %s\n", name);
lib/test_fortify/read_overflow2_field-memcpy.c+5−0
@@ -0,0 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0-only
2#define TEST \
3 memcpy(large, instance.buf, sizeof(instance.buf) + 1)
4
5#include "test_fortify.h"
lib/test_fortify/read_overflow2_field-memmove.c+5−0
@@ -0,0 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0-only
2#define TEST \
3 memmove(large, instance.buf, sizeof(instance.buf) + 1)
4
5#include "test_fortify.h"
lib/test_fortify/write_overflow_field-memcpy.c+5−0
@@ -0,0 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0-only
2#define TEST \
3 memcpy(instance.buf, large, sizeof(instance.buf) + 1)
4
5#include "test_fortify.h"
lib/test_fortify/write_overflow_field-memmove.c+5−0
@@ -0,0 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0-only
2#define TEST \
3 memmove(instance.buf, large, sizeof(instance.buf) + 1)
4
5#include "test_fortify.h"
lib/test_fortify/write_overflow_field-memset.c+5−0
@@ -0,0 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0-only
2#define TEST \
3 memset(instance.buf, 0x42, sizeof(instance.buf) + 1)
4
5#include "test_fortify.h"
scripts/test_fortify.sh+6−2
@@ -46,8 +46,12 @@ if "$@" -Werror -c "$IN" -o "$OUT".o 2> "$TMP" ; then · 45 unmodified lines
46 status="warning: unsafe ${FUNC}() usage lacked '$WANT' symbol in $IN"46 status="warning: unsafe ${FUNC}() usage lacked '$WANT' symbol in $IN"
47 fi47 fi
48else48else
49 # If the build failed, check for the warning in the stderr (gcc).49 # If the build failed, check for the warning in the stderr.
50 if ! grep -q -m1 "error: call to .\b${WANT}\b." "$TMP" ; then50 # GCC:
51 # ./include/linux/fortify-string.h:316:25: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning]
52 # Clang 14:
53 # ./include/linux/fortify-string.h:316:4: error: call to __write_overflow_field declared with 'warning' attribute: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror,-Wattribute-warning]
54 if ! grep -Eq -m1 "error: call to .?\b${WANT}\b.?" "$TMP" ; then
51 status="warning: unsafe ${FUNC}() usage lacked '$WANT' warning in $IN"55 status="warning: unsafe ${FUNC}() usage lacked '$WANT' warning in $IN"
52 fi56 fi
53fi57fi
security/Kconfig+3−2
@@ -177,9 +177,10 @@ config HARDENED_USERCOPY_PAGESPAN · 176 unmodified lines
177config FORTIFY_SOURCE177config FORTIFY_SOURCE
178 bool "Harden common str/mem functions against buffer overflows"178 bool "Harden common str/mem functions against buffer overflows"
179 depends on ARCH_HAS_FORTIFY_SOURCE179 depends on ARCH_HAS_FORTIFY_SOURCE
180 # https://bugs.llvm.org/show_bug.cgi?id=50322
181 # https://bugs.llvm.org/show_bug.cgi?id=41459180 # https://bugs.llvm.org/show_bug.cgi?id=41459
182 depends on !CC_IS_CLANG181 depends on !CC_IS_CLANG || CLANG_VERSION >= 120001
182 # https://github.com/llvm/llvm-project/issues/53645
183 depends on !CC_IS_CLANG || !X86_32
183 help184 help
184 Detect overflows of buffers in common string and memory functions185 Detect overflows of buffers in common string and memory functions
185 where the compiler can determine and validate the buffer sizes.186 where the compiler can determine and validate the buffer sizes.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t