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
3737 * try to define their own functions if these are not defined as macros.
3838 */
3939 #define memzero(s, n) memset((s), 0, (n))
40+#ifndef memmove
4041 #define memmove memmove
41−
4242 /* Functions used by the included decompressor code below. */
4343 void *memmove(void *dest, const void *src, size_t n);
44+#endif
4445
4546 /*
4647 * 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
44
55 #undef memcpy
66 #undef memset
7+#undef memmove
78
89 __visible void *memcpy(void *to, const void *from, size_t n)
910 {
include/linux/compiler_attributes.h+39−0
@@ -100,6 +100,19 @@ · 99 unmodified lines
100100 # define __copy(symbol)
101101 #endif
102102
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+
103116 /*
104117 * Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated'
105118 * attribute warnings entirely and for good") for more information.
@@ -257,12 +270,38 @@ · 151 unmodified lines
257270 */
258271 #define __noreturn __attribute__((__noreturn__))
259272
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+
260285 /*
261286 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute
262287 * clang: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
263288 */
264289 #define __packed __attribute__((__packed__))
265290
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+
266305 /*
267306 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
268307 */
include/linux/fortify-string.h+188−50
@@ -2,13 +2,17 @@ · 1 unmodified line
22 #ifndef _LINUX_FORTIFY_STRING_H_
33 #define _LINUX_FORTIFY_STRING_H_
44
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
68 #define __RENAME(x) __asm__(#x)
79
810 void fortify_panic(const char *name) __noreturn __cold;
911 void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)");
1012 void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)");
13+void __read_overflow2_field(size_t avail, size_t wanted) __compiletime_warning("detected read beyond size of field (2nd parameter); maybe use struct_group()?");
1114 void __write_overflow(void) __compiletime_error("detected write beyond size of object (1st parameter)");
15+void __write_overflow_field(size_t avail, size_t wanted) __compiletime_warning("detected write beyond size of field (1st parameter); maybe use struct_group()?");
1216
1317 #define __compiletime_strlen(p) \
1418 ({ \
@@ -48,7 +52,17 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) · 33 unmodified lines
4852 #define __underlying_strncpy __builtin_strncpy
4953 #endif
5054
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)
65+char *strncpy(char * const POS p, const char *q, __kernel_size_t size)
5266 {
5367 size_t p_size = __builtin_object_size(p, 1);
5468
@@ -59,7 +73,8 @@ __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size) · 4 unmodified lines
5973 return __underlying_strncpy(p, q, size);
6074 }
6175
62−__FORTIFY_INLINE char *strcat(char *p, const char *q)
76+__FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2)
77+char *strcat(char * const POS p, const char *q)
6378 {
6479 size_t p_size = __builtin_object_size(p, 1);
6580
@@ -71,7 +86,7 @@ __FORTIFY_INLINE char *strcat(char *p, const char *q) · 5 unmodified lines
7186 }
7287
7388 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)
89+__FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size_t maxlen)
7590 {
7691 size_t p_size = __builtin_object_size(p, 1);
7792 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
91106 return ret;
92107 }
93108
94−/* defined after fortified strnlen to reuse it. */
95−__FORTIFY_INLINE __kernel_size_t strlen(const char *p)
109+/*
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)
96119 {
97120 __kernel_size_t ret;
98121 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
108131
109132 /* defined after fortified strlen to reuse it */
110133 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)
134+__FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, size_t size)
112135 {
113136 size_t p_size = __builtin_object_size(p, 1);
114137 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
135158
136159 /* defined after fortified strnlen to reuse it */
137160 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)
161+__FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, size_t size)
139162 {
140163 size_t len;
141164 /* 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
181204 }
182205
183206 /* 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)
208+char *strncat(char * const POS p, const char * const POS q, __kernel_size_t count)
185209 {
186210 size_t p_len, copy_len;
187211 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
198222 return p;
199223 }
200224
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)
202228 {
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−
217229 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)
219238 __write_overflow();
220− if (q_size < size)
221− __read_overflow2();
239+
240+ /* Warn when write size is larger than dest field. */
241+ if (p_size_field < size)
242+ __write_overflow_field(p_size_field, size);
222243 }
223− if (p_size < size || q_size < size)
224− fortify_panic(__func__);
225− return __underlying_memcpy(p, q, size);
244+ /*
245+ * At this point, length argument may not be a constant expression,
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");
226260 }
227261
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);
262+#define __fortify_memset_chk(p, c, size, p_size, p_size_field) ({ \
263+ size_t __fortify_size = (size_t)(size); \
264+ fortify_memset_chk(__fortify_size, p_size, p_size_field), \
265+ __underlying_memset(p, c, __fortify_size); \
266+})
232267
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+{
233313 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)
235322 __write_overflow();
236− if (q_size < size)
323+ if (q_size > q_size_field && q_size < size)
237324 __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);
238337 }
239− if (p_size < size || q_size < size)
240− fortify_panic(__func__);
241− return __underlying_memmove(p, q, size);
338+ /*
339+ * At this point, length argument may not be a constant expression,
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);
242355 }
243356
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+
244378 extern 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)
246380 {
247381 size_t p_size = __builtin_object_size(p, 0);
248382
@@ -253,7 +387,8 @@ __FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size) · 4 unmodified lines
253387 return __real_memscan(p, c, size);
254388 }
255389
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)
391+int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t size)
257392 {
258393 size_t p_size = __builtin_object_size(p, 0);
259394 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
269404 return __underlying_memcmp(p, q, size);
270405 }
271406
272−__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
407+__FORTIFY_INLINE __diagnose_as(__builtin_memchr, 1, 2, 3)
408+void *memchr(const void * const POS0 p, int c, __kernel_size_t size)
273409 {
274410 size_t p_size = __builtin_object_size(p, 0);
275411
@@ -281,7 +417,7 @@ __FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size) · 5 unmodified lines
281417 }
282418
283419 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)
420+__FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size)
285421 {
286422 size_t p_size = __builtin_object_size(p, 0);
287423
@@ -293,7 +429,7 @@ __FORTIFY_INLINE void *memchr_inv(const void *p, int c, size_t size) · 5 unmodified lines
293429 }
294430
295431 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)
432+__FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp)
297433 {
298434 size_t p_size = __builtin_object_size(p, 0);
299435
@@ -304,13 +440,15 @@ __FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp) · 4 unmodified lines
304440 return __real_kmemdup(p, size, gfp);
305441 }
306442
307−/* defined after fortified strlen and memcpy to reuse them */
308−__FORTIFY_INLINE char *strcpy(char *p, const char *q)
443+/* Defined after fortified strlen to reuse it. */
444+__FORTIFY_INLINE __diagnose_as(__builtin_strcpy, 1, 2)
445+char *strcpy(char * const POS p, const char * const POS q)
309446 {
310447 size_t p_size = __builtin_object_size(p, 1);
311448 size_t q_size = __builtin_object_size(q, 1);
312449 size_t size;
313450
451+ /* If neither buffer size is known, immediately give up. */
314452 if (p_size == (size_t)-1 && q_size == (size_t)-1)
315453 return __underlying_strcpy(p, q);
316454 size = strlen(q) + 1;
@@ -320,20 +458,20 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q) · 3 unmodified lines
320458 /* Run-time check for dynamic size overflow. */
321459 if (p_size < size)
322460 fortify_panic(__func__);
323− memcpy(p, q, size);
461+ __underlying_memcpy(p, q, size);
324462 return p;
325463 }
326464
327465 /* Don't use these outside the FORITFY_SOURCE implementation */
328466 #undef __underlying_memchr
329467 #undef __underlying_memcmp
330−#undef __underlying_memcpy
331−#undef __underlying_memmove
332−#undef __underlying_memset
333468 #undef __underlying_strcat
334469 #undef __underlying_strcpy
335470 #undef __underlying_strlen
336471 #undef __underlying_strncat
337472 #undef __underlying_strncpy
338473
474+#undef POS
475+#undef POS0
476+
339477 #endif /* _LINUX_FORTIFY_STRING_H_ */
lib/Makefile+2−1
@@ -377,7 +377,8 @@ TEST_FORTIFY_LOG = test_fortify.log · 376 unmodified lines
377377 quiet_cmd_test_fortify = TEST $@
378378 cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \
379379 $< $@ "$(NM)" $(CC) $(c_flags) \
380− $(call cc-disable-warning,fortify-source)
380+ $(call cc-disable-warning,fortify-source) \
381+ -DKBUILD_EXTRA_WARN1
381382
382383 targets += $(TEST_FORTIFY_LOGS)
383384 clean-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
968968 EXPORT_SYMBOL(memcpy_and_pad);
969969
970970 #ifdef CONFIG_FORTIFY_SOURCE
971+/* These are placeholders for fortify compile-time warnings. */
972+void __read_overflow2_field(size_t avail, size_t wanted) { }
973+EXPORT_SYMBOL(__read_overflow2_field);
974+void __write_overflow_field(size_t avail, size_t wanted) { }
975+EXPORT_SYMBOL(__write_overflow_field);
976+
971977 void fortify_panic(const char *name)
972978 {
973979 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
4646 status="warning: unsafe ${FUNC}() usage lacked '$WANT' symbol in $IN"
4747 fi
4848 else
49− # If the build failed, check for the warning in the stderr (gcc).
50− if ! grep -q -m1 "error: call to .\b${WANT}\b." "$TMP" ; then
49+ # If the build failed, check for the warning in the stderr.
50+ # 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
5155 status="warning: unsafe ${FUNC}() usage lacked '$WANT' warning in $IN"
5256 fi
5357 fi
security/Kconfig+3−2
@@ -177,9 +177,10 @@ config HARDENED_USERCOPY_PAGESPAN · 176 unmodified lines
177177 config FORTIFY_SOURCE
178178 bool "Harden common str/mem functions against buffer overflows"
179179 depends on ARCH_HAS_FORTIFY_SOURCE
180− # https://bugs.llvm.org/show_bug.cgi?id=50322
181180 # https://bugs.llvm.org/show_bug.cgi?id=41459
182− depends on !CC_IS_CLANG
181+ 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
183184 help
184185 Detect overflows of buffers in common string and memory functions
185186 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