mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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
					
				
					 1 changed files with 29 additions and 26 deletions
				
			
		| 
						 | 
					@ -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();					\
 | 
				
			||||||
 | 
						KUNIT_EXPECT_FALSE(test, READ_ONCE(fail_data.report_found));	\
 | 
				
			||||||
	WRITE_ONCE(fail_data.report_expected, true);			\
 | 
						WRITE_ONCE(fail_data.report_expected, true);			\
 | 
				
			||||||
	WRITE_ONCE(fail_data.report_found, false);		\
 | 
					 | 
				
			||||||
	kunit_add_named_resource(test,				\
 | 
					 | 
				
			||||||
				NULL,				\
 | 
					 | 
				
			||||||
				NULL,				\
 | 
					 | 
				
			||||||
				&resource,			\
 | 
					 | 
				
			||||||
				"kasan_data", &fail_data);	\
 | 
					 | 
				
			||||||
	barrier();							\
 | 
						barrier();							\
 | 
				
			||||||
	expression;							\
 | 
						expression;							\
 | 
				
			||||||
	barrier();							\
 | 
						barrier();							\
 | 
				
			||||||
	if (kasan_async_mode_enabled())				\
 | 
					 | 
				
			||||||
		kasan_force_async_fault();			\
 | 
					 | 
				
			||||||
	barrier();						\
 | 
					 | 
				
			||||||
	KUNIT_EXPECT_EQ(test,						\
 | 
						KUNIT_EXPECT_EQ(test,						\
 | 
				
			||||||
			READ_ONCE(fail_data.report_expected),		\
 | 
								READ_ONCE(fail_data.report_expected),		\
 | 
				
			||||||
			READ_ONCE(fail_data.report_found));		\
 | 
								READ_ONCE(fail_data.report_found));		\
 | 
				
			||||||
	if (IS_ENABLED(CONFIG_KASAN_HW_TAGS) &&			\
 | 
						if (IS_ENABLED(CONFIG_KASAN_HW_TAGS)) {				\
 | 
				
			||||||
	    !kasan_async_mode_enabled()) {			\
 | 
					 | 
				
			||||||
		if (READ_ONCE(fail_data.report_found))			\
 | 
							if (READ_ONCE(fail_data.report_found))			\
 | 
				
			||||||
			kasan_enable_tagging_sync();			\
 | 
								kasan_enable_tagging_sync();			\
 | 
				
			||||||
		migrate_enable();					\
 | 
							migrate_enable();					\
 | 
				
			||||||
	}								\
 | 
						}								\
 | 
				
			||||||
 | 
						WRITE_ONCE(fail_data.report_found, false);			\
 | 
				
			||||||
 | 
						WRITE_ONCE(fail_data.report_expected, false);			\
 | 
				
			||||||
} 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 a new issue