Commit 3bf8a459 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull hardening fixes from Kees Cook:

 - lib/prime_numbers: KUnit test should not select PRIME_NUMBERS (Geert
   Uytterhoeven)

 - ubsan: Fix panic from test_ubsan_out_of_bounds (Mostafa Saleh)

 - ubsan: Remove 'default UBSAN' from UBSAN_INTEGER_WRAP (Nathan
   Chancellor)

 - string: Add load_unaligned_zeropad() code path to sized_strscpy()
   (Peter Collingbourne)

 - kasan: Add strscpy() test to trigger tag fault on arm64 (Vincenzo
   Frascino)

 - Disable GCC randstruct for COMPILE_TEST

* tag 'hardening-v6.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  lib/prime_numbers: KUnit test should not select PRIME_NUMBERS
  ubsan: Fix panic from test_ubsan_out_of_bounds
  lib/Kconfig.ubsan: Remove 'default UBSAN' from UBSAN_INTEGER_WRAP
  hardening: Disable GCC randstruct for COMPILE_TEST
  kasan: Add strscpy() test to trigger tag fault on arm64
  string: Add load_unaligned_zeropad() code path to sized_strscpy()
parents 30d451e3 3f292517
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3290,7 +3290,7 @@ config GCD_KUNIT_TEST
config PRIME_NUMBERS_KUNIT_TEST
	tristate "Prime number generator test" if !KUNIT_ALL_TESTS
	depends on KUNIT
	select PRIME_NUMBERS
	depends on PRIME_NUMBERS
	default KUNIT_ALL_TESTS
	help
	  This option enables the KUnit test suite for the {is,next}_prime_number
+0 −1
Original line number Diff line number Diff line
@@ -118,7 +118,6 @@ config UBSAN_UNREACHABLE

config UBSAN_INTEGER_WRAP
	bool "Perform checking for integer arithmetic wrap-around"
	default UBSAN
	depends on !COMPILE_TEST
	depends on $(cc-option,-fsanitize-undefined-ignore-overflow-pattern=all)
	depends on $(cc-option,-fsanitize=signed-integer-overflow)
+10 −3
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
	if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
		return -E2BIG;

#ifndef CONFIG_DCACHE_WORD_ACCESS
#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
	/*
	 * If src is unaligned, don't cross a page boundary,
@@ -133,12 +134,14 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
	/* If src or dest is unaligned, don't do word-at-a-time. */
	if (((long) dest | (long) src) & (sizeof(long) - 1))
		max = 0;
#endif
#endif

	/*
	 * read_word_at_a_time() below may read uninitialized bytes after the
	 * trailing zero and use them in comparisons. Disable this optimization
	 * under KMSAN to prevent false positive reports.
	 * load_unaligned_zeropad() or read_word_at_a_time() below may read
	 * uninitialized bytes after the trailing zero and use them in
	 * comparisons. Disable this optimization under KMSAN to prevent
	 * false positive reports.
	 */
	if (IS_ENABLED(CONFIG_KMSAN))
		max = 0;
@@ -146,7 +149,11 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
	while (max >= sizeof(unsigned long)) {
		unsigned long c, data;

#ifdef CONFIG_DCACHE_WORD_ACCESS
		c = load_unaligned_zeropad(src+res);
#else
		c = read_word_at_a_time(src+res);
#endif
		if (has_zero(c, &data, &constants)) {
			data = prep_zero_mask(c, data, &constants);
			data = create_zero_mask(data);
+11 −7
Original line number Diff line number Diff line
@@ -77,18 +77,22 @@ static void test_ubsan_shift_out_of_bounds(void)

static void test_ubsan_out_of_bounds(void)
{
	volatile int i = 4, j = 5, k = -1;
	volatile char above[4] = { }; /* Protect surrounding memory. */
	volatile int arr[4];
	volatile char below[4] = { }; /* Protect surrounding memory. */
	int i = 4, j = 4, k = -1;
	volatile struct {
		char above[4]; /* Protect surrounding memory. */
		int arr[4];
		char below[4]; /* Protect surrounding memory. */
	} data;

	above[0] = below[0];
	OPTIMIZER_HIDE_VAR(i);
	OPTIMIZER_HIDE_VAR(j);
	OPTIMIZER_HIDE_VAR(k);

	UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "above");
	arr[j] = i;
	data.arr[j] = i;

	UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "below");
	arr[k] = i;
	data.arr[k] = i;
}

enum ubsan_test_enum {
+20 −0
Original line number Diff line number Diff line
@@ -1567,6 +1567,7 @@ static void kasan_memcmp(struct kunit *test)
static void kasan_strings(struct kunit *test)
{
	char *ptr;
	char *src;
	size_t size = 24;

	/*
@@ -1578,6 +1579,25 @@ static void kasan_strings(struct kunit *test)
	ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO);
	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);

	src = kmalloc(KASAN_GRANULE_SIZE, GFP_KERNEL | __GFP_ZERO);
	strscpy(src, "f0cacc1a0000000", KASAN_GRANULE_SIZE);

	/*
	 * Make sure that strscpy() does not trigger KASAN if it overreads into
	 * poisoned memory.
	 *
	 * The expected size does not include the terminator '\0'
	 * so it is (KASAN_GRANULE_SIZE - 2) ==
	 * KASAN_GRANULE_SIZE - ("initial removed character" + "\0").
	 */
	KUNIT_EXPECT_EQ(test, KASAN_GRANULE_SIZE - 2,
			strscpy(ptr, src + 1, KASAN_GRANULE_SIZE));

	/* strscpy should fail if the first byte is unreadable. */
	KUNIT_EXPECT_KASAN_FAIL(test, strscpy(ptr, src + KASAN_GRANULE_SIZE,
					      KASAN_GRANULE_SIZE));

	kfree(src);
	kfree(ptr);

	/*
Loading