mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-08 14:23:19 +00:00
kasan: add atomic tests
Test that KASan can detect some unsafe atomic accesses. As discussed in the linked thread below, these tests attempt to cover the most common uses of atomics and, therefore, aren't exhaustive. Link: https://lkml.kernel.org/r/20240202113259.3045705-1-paul.heidekrueger@tum.de Link: https://lore.kernel.org/all/20240131210041.686657-1-paul.heidekrueger@tum.de/T/#u Signed-off-by: Paul Heidekrüger <paul.heidekrueger@tum.de> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=214055 Acked-by: Mark Rutland <mark.rutland@arm.com> Cc: Marco Elver <elver@google.com> Cc: Andrey Konovalov <andreyknvl@gmail.com> Cc: Alexander Potapenko <glider@google.com> Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Vincenzo Frascino <vincenzo.frascino@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
09dacb7875
commit
4e76c8cc33
@ -697,6 +697,84 @@ static void kmalloc_uaf3(struct kunit *test)
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr1)[8]);
|
||||
}
|
||||
|
||||
static void kasan_atomics_helper(struct kunit *test, void *unsafe, void *safe)
|
||||
{
|
||||
int *i_unsafe = (int *)unsafe;
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, READ_ONCE(*i_unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, WRITE_ONCE(*i_unsafe, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, smp_load_acquire(i_unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, smp_store_release(i_unsafe, 42));
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_read(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_set(unsafe, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_add(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_sub(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_inc(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_dec(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_and(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_andnot(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_or(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_xor(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_xchg(unsafe, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_cmpxchg(unsafe, 21, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_try_cmpxchg(unsafe, safe, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_try_cmpxchg(safe, unsafe, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_sub_and_test(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_dec_and_test(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_inc_and_test(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_add_negative(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_add_unless(unsafe, 21, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_inc_not_zero(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_inc_unless_negative(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_dec_unless_positive(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_dec_if_positive(unsafe));
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_read(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_set(unsafe, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_add(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_sub(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_inc(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_dec(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_and(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_andnot(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_or(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_xor(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_xchg(unsafe, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_cmpxchg(unsafe, 21, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_try_cmpxchg(unsafe, safe, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_try_cmpxchg(safe, unsafe, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_sub_and_test(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_dec_and_test(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_inc_and_test(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_add_negative(42, unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_add_unless(unsafe, 21, 42));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_inc_not_zero(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_inc_unless_negative(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_dec_unless_positive(unsafe));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, atomic_long_dec_if_positive(unsafe));
|
||||
}
|
||||
|
||||
static void kasan_atomics(struct kunit *test)
|
||||
{
|
||||
void *a1, *a2;
|
||||
|
||||
/*
|
||||
* Just as with kasan_bitops_tags(), we allocate 48 bytes of memory such
|
||||
* that the following 16 bytes will make up the redzone.
|
||||
*/
|
||||
a1 = kzalloc(48, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, a1);
|
||||
a2 = kzalloc(sizeof(int), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, a1);
|
||||
|
||||
/* Use atomics to access the redzone. */
|
||||
kasan_atomics_helper(test, a1 + 48, a2);
|
||||
|
||||
kfree(a1);
|
||||
kfree(a2);
|
||||
}
|
||||
|
||||
static void kmalloc_double_kzfree(struct kunit *test)
|
||||
{
|
||||
char *ptr;
|
||||
@ -1883,6 +1961,7 @@ static struct kunit_case kasan_kunit_test_cases[] = {
|
||||
KUNIT_CASE(kasan_strings),
|
||||
KUNIT_CASE(kasan_bitops_generic),
|
||||
KUNIT_CASE(kasan_bitops_tags),
|
||||
KUNIT_CASE(kasan_atomics),
|
||||
KUNIT_CASE(vmalloc_helpers_tags),
|
||||
KUNIT_CASE(vmalloc_oob),
|
||||
KUNIT_CASE(vmap_tags),
|
||||
|
Loading…
Reference in New Issue
Block a user