kasan: detect false-positives in tests
Currently, KASAN-KUnit tests can check that a particular annotated part of code causes a KASAN report. However, they do not check that no unwanted reports happen between the annotated parts. This patch implements these checks. It is done by setting report_data.report_found to false in kasan_test_init() and at the end of KUNIT_EXPECT_KASAN_FAIL() and then checking that it remains false at the beginning of KUNIT_EXPECT_KASAN_FAIL() and in kasan_test_exit(). kunit_add_named_resource() call is moved to kasan_test_init(), and the value of fail_data.report_expected is kept as false in between KUNIT_EXPECT_KASAN_FAIL() annotations for consistency. Link: https://lkml.kernel.org/r/48079c52cc329fbc52f4386996598d58022fb872.1617207873.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Reviewed-by: Marco Elver <elver@google.com> Cc: Alexander Potapenko <glider@google.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
23f61f0fe1
commit
99734b535d
|
@ -54,6 +54,10 @@ static int kasan_test_init(struct kunit *test)
|
||||||
|
|
||||||
multishot = kasan_save_enable_multi_shot();
|
multishot = kasan_save_enable_multi_shot();
|
||||||
kasan_set_tagging_report_once(false);
|
kasan_set_tagging_report_once(false);
|
||||||
|
fail_data.report_found = false;
|
||||||
|
fail_data.report_expected = false;
|
||||||
|
kunit_add_named_resource(test, NULL, NULL, &resource,
|
||||||
|
"kasan_data", &fail_data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +65,7 @@ static void kasan_test_exit(struct kunit *test)
|
||||||
{
|
{
|
||||||
kasan_set_tagging_report_once(true);
|
kasan_set_tagging_report_once(true);
|
||||||
kasan_restore_multi_shot(multishot);
|
kasan_restore_multi_shot(multishot);
|
||||||
|
KUNIT_EXPECT_FALSE(test, fail_data.report_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,33 +83,31 @@ static void kasan_test_exit(struct kunit *test)
|
||||||
* fields, it can reorder or optimize away the accesses to those fields.
|
* fields, it can reorder or optimize away the accesses to those fields.
|
||||||
* Use READ/WRITE_ONCE() for the accesses and compiler barriers around the
|
* Use READ/WRITE_ONCE() for the accesses and compiler barriers around the
|
||||||
* expression to prevent that.
|
* expression to prevent that.
|
||||||
|
*
|
||||||
|
* In between KUNIT_EXPECT_KASAN_FAIL checks, fail_data.report_found is kept as
|
||||||
|
* false. This allows detecting KASAN reports that happen outside of the checks
|
||||||
|
* by asserting !fail_data.report_found at the start of KUNIT_EXPECT_KASAN_FAIL
|
||||||
|
* and in kasan_test_exit.
|
||||||
*/
|
*/
|
||||||
#define KUNIT_EXPECT_KASAN_FAIL(test, expression) do { \
|
#define KUNIT_EXPECT_KASAN_FAIL(test, expression) do { \
|
||||||
if (IS_ENABLED(CONFIG_KASAN_HW_TAGS) && \
|
if (IS_ENABLED(CONFIG_KASAN_HW_TAGS) && \
|
||||||
!kasan_async_mode_enabled()) \
|
!kasan_async_mode_enabled()) \
|
||||||
migrate_disable(); \
|
migrate_disable(); \
|
||||||
WRITE_ONCE(fail_data.report_expected, true); \
|
KUNIT_EXPECT_FALSE(test, READ_ONCE(fail_data.report_found)); \
|
||||||
WRITE_ONCE(fail_data.report_found, false); \
|
WRITE_ONCE(fail_data.report_expected, true); \
|
||||||
kunit_add_named_resource(test, \
|
barrier(); \
|
||||||
NULL, \
|
expression; \
|
||||||
NULL, \
|
barrier(); \
|
||||||
&resource, \
|
KUNIT_EXPECT_EQ(test, \
|
||||||
"kasan_data", &fail_data); \
|
READ_ONCE(fail_data.report_expected), \
|
||||||
barrier(); \
|
READ_ONCE(fail_data.report_found)); \
|
||||||
expression; \
|
if (IS_ENABLED(CONFIG_KASAN_HW_TAGS)) { \
|
||||||
barrier(); \
|
if (READ_ONCE(fail_data.report_found)) \
|
||||||
if (kasan_async_mode_enabled()) \
|
kasan_enable_tagging_sync(); \
|
||||||
kasan_force_async_fault(); \
|
migrate_enable(); \
|
||||||
barrier(); \
|
} \
|
||||||
KUNIT_EXPECT_EQ(test, \
|
WRITE_ONCE(fail_data.report_found, false); \
|
||||||
READ_ONCE(fail_data.report_expected), \
|
WRITE_ONCE(fail_data.report_expected, false); \
|
||||||
READ_ONCE(fail_data.report_found)); \
|
|
||||||
if (IS_ENABLED(CONFIG_KASAN_HW_TAGS) && \
|
|
||||||
!kasan_async_mode_enabled()) { \
|
|
||||||
if (READ_ONCE(fail_data.report_found)) \
|
|
||||||
kasan_enable_tagging_sync(); \
|
|
||||||
migrate_enable(); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define KASAN_TEST_NEEDS_CONFIG_ON(test, config) do { \
|
#define KASAN_TEST_NEEDS_CONFIG_ON(test, config) do { \
|
||||||
|
|
Loading…
Reference in New Issue