Commit 9946eaf5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull hardening fixes from Kees Cook:
 "Address a KUnit stack initialization regression that got tickled on
  m68k, and solve a Clang(v14 and earlier) bug found by 0day:

   - Fix stackinit KUnit regression on m68k

   - Use ARRAY_SIZE() for memtostr*()/strtomem*()"

* tag 'hardening-v6.14-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*()
  compiler.h: Introduce __must_be_byte_array()
  compiler.h: Move C string helpers into C-only kernel section
  stackinit: Fix comment for test_small_end
  stackinit: Keep selftest union size small on m68k
parents f4a45f14 6270f4de
Loading
Loading
Loading
Loading
+19 −13
Original line number Diff line number Diff line
@@ -191,6 +191,25 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
	__v;								\
})

#ifdef __CHECKER__
#define __BUILD_BUG_ON_ZERO_MSG(e, msg) (0)
#else /* __CHECKER__ */
#define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);}))
#endif /* __CHECKER__ */

/* &a[0] degrades to a pointer: a different type from an array */
#define __is_array(a)		(!__same_type((a), &(a)[0]))
#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_array(a), \
							"must be array")

#define __is_byte_array(a)	(__is_array(a) && sizeof((a)[0]) == 1)
#define __must_be_byte_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_byte_array(a), \
							"must be byte array")

/* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */
#define __must_be_cstr(p) \
	__BUILD_BUG_ON_ZERO_MSG(__annotated(p, nonstring), "must be cstr (NUL-terminated)")

#endif /* __KERNEL__ */

/**
@@ -231,19 +250,6 @@ static inline void *offset_to_ptr(const int *off)

#define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym))

#ifdef __CHECKER__
#define __BUILD_BUG_ON_ZERO_MSG(e, msg) (0)
#else /* __CHECKER__ */
#define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);}))
#endif /* __CHECKER__ */

/* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")

/* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */
#define __must_be_cstr(p) \
	__BUILD_BUG_ON_ZERO_MSG(__annotated(p, nonstring), "must be cstr (NUL-terminated)")

/*
 * This returns a constant expression while determining if an argument is
 * a constant expression, most importantly without evaluating the argument.
+8 −4
Original line number Diff line number Diff line
@@ -414,7 +414,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
 * must be discoverable by the compiler.
 */
#define strtomem_pad(dest, src, pad)	do {				\
	const size_t _dest_len = __builtin_object_size(dest, 1);	\
	const size_t _dest_len = __must_be_byte_array(dest) +		\
				 ARRAY_SIZE(dest);			\
	const size_t _src_len = __builtin_object_size(src, 1);		\
									\
	BUILD_BUG_ON(!__builtin_constant_p(_dest_len) ||		\
@@ -437,7 +438,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
 * must be discoverable by the compiler.
 */
#define strtomem(dest, src)	do {					\
	const size_t _dest_len = __builtin_object_size(dest, 1);	\
	const size_t _dest_len = __must_be_byte_array(dest) +		\
				 ARRAY_SIZE(dest);			\
	const size_t _src_len = __builtin_object_size(src, 1);		\
									\
	BUILD_BUG_ON(!__builtin_constant_p(_dest_len) ||		\
@@ -456,7 +458,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
 * Note that sizes of @dest and @src must be known at compile-time.
 */
#define memtostr(dest, src)	do {					\
	const size_t _dest_len = __builtin_object_size(dest, 1);	\
	const size_t _dest_len = __must_be_byte_array(dest) +		\
				 ARRAY_SIZE(dest);			\
	const size_t _src_len = __builtin_object_size(src, 1);		\
	const size_t _src_chars = strnlen(src, _src_len);		\
	const size_t _copy_len = min(_dest_len - 1, _src_chars);	\
@@ -481,7 +484,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
 * Note that sizes of @dest and @src must be known at compile-time.
 */
#define memtostr_pad(dest, src)		do {				\
	const size_t _dest_len = __builtin_object_size(dest, 1);	\
	const size_t _dest_len = __must_be_byte_array(dest) +		\
				 ARRAY_SIZE(dest);			\
	const size_t _src_len = __builtin_object_size(src, 1);		\
	const size_t _src_chars = strnlen(src, _src_len);		\
	const size_t _copy_len = min(_dest_len - 1, _src_chars);	\
+4 −2
Original line number Diff line number Diff line
@@ -75,8 +75,10 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
 */
#ifdef CONFIG_M68K
#define FILL_SIZE_STRING		8
#define FILL_SIZE_ARRAY			2
#else
#define FILL_SIZE_STRING		16
#define FILL_SIZE_ARRAY			8
#endif

#define INIT_CLONE_SCALAR		/**/
@@ -345,11 +347,11 @@ union test_small_start {
	short three;
	unsigned long four;
	struct big_struct {
		unsigned long array[8];
		unsigned long array[FILL_SIZE_ARRAY];
	} big;
};

/* Mismatched sizes, with one and two being small */
/* Mismatched sizes, with three and four being small */
union test_small_end {
	short one;
	unsigned long two;