forked from mirrors/linux
		
	kasan, arm64: tests supports for HW_TAGS async mode
This change adds KASAN-KUnit tests support for the async HW_TAGS mode. In async mode, tag fault aren't being generated synchronously when a bad access happens, but are instead explicitly checked for by the kernel. As each KASAN-KUnit test expect a fault to happen before the test is over, check for faults as a part of the test handler. Acked-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Andrey Konovalov <andreyknvl@google.com> Tested-by: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com> Link: https://lore.kernel.org/r/20210315132019.33202-10-vincenzo.frascino@arm.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
		
							parent
							
								
									eab0e6e17d
								
							
						
					
					
						commit
						e80a76aa1a
					
				
					 5 changed files with 29 additions and 6 deletions
				
			
		|  | @ -246,6 +246,7 @@ static inline const void *__tag_set(const void *addr, u8 tag) | |||
| #define arch_enable_tagging_sync()		mte_enable_kernel_sync() | ||||
| #define arch_enable_tagging_async()		mte_enable_kernel_async() | ||||
| #define arch_set_tagging_report_once(state)	mte_set_report_once(state) | ||||
| #define arch_force_async_tag_fault()		mte_check_tfsr_exit() | ||||
| #define arch_init_tags(max_tag)			mte_init_tags(max_tag) | ||||
| #define arch_get_random_tag()			mte_get_random_tag() | ||||
| #define arch_get_mem_tag(addr)			mte_get_mem_tag(addr) | ||||
|  |  | |||
|  | @ -69,10 +69,10 @@ static void kasan_test_exit(struct kunit *test) | |||
|  * resource named "kasan_data". Do not use this name for KUnit resources | ||||
|  * outside of KASAN tests. | ||||
|  * | ||||
|  * For hardware tag-based KASAN, when a tag fault happens, tag checking is | ||||
|  * normally auto-disabled. When this happens, this test handler reenables | ||||
|  * tag checking. As tag checking can be only disabled or enabled per CPU, this | ||||
|  * handler disables migration (preemption). | ||||
|  * For hardware tag-based KASAN in sync mode, when a tag fault happens, tag | ||||
|  * checking is auto-disabled. When this happens, this test handler reenables | ||||
|  * tag checking. As tag checking can be only disabled or enabled per CPU, | ||||
|  * this handler disables migration (preemption). | ||||
|  * | ||||
|  * Since the compiler doesn't see that the expression can change the fail_data | ||||
|  * fields, it can reorder or optimize away the accesses to those fields. | ||||
|  | @ -80,7 +80,8 @@ static void kasan_test_exit(struct kunit *test) | |||
|  * expression to prevent that. | ||||
|  */ | ||||
| #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())			\ | ||||
| 		migrate_disable();				\ | ||||
| 	WRITE_ONCE(fail_data.report_expected, true);		\ | ||||
| 	WRITE_ONCE(fail_data.report_found, false);		\ | ||||
|  | @ -92,10 +93,14 @@ static void kasan_test_exit(struct kunit *test) | |||
| 	barrier();						\ | ||||
| 	expression;						\ | ||||
| 	barrier();						\ | ||||
| 	if (kasan_async_mode_enabled())				\ | ||||
| 		kasan_force_async_fault();			\ | ||||
| 	barrier();						\ | ||||
| 	KUNIT_EXPECT_EQ(test,					\ | ||||
| 			READ_ONCE(fail_data.report_expected),	\ | ||||
| 			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))		\ | ||||
| 			kasan_enable_tagging_sync();		\ | ||||
| 		migrate_enable();				\ | ||||
|  |  | |||
|  | @ -252,4 +252,10 @@ void kasan_enable_tagging_sync(void) | |||
| } | ||||
| EXPORT_SYMBOL_GPL(kasan_enable_tagging_sync); | ||||
| 
 | ||||
| void kasan_force_async_fault(void) | ||||
| { | ||||
| 	hw_force_async_tag_fault(); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(kasan_force_async_fault); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -304,6 +304,9 @@ static inline const void *arch_kasan_set_tag(const void *addr, u8 tag) | |||
| #ifndef arch_set_tagging_report_once | ||||
| #define arch_set_tagging_report_once(state) | ||||
| #endif | ||||
| #ifndef arch_force_async_tag_fault | ||||
| #define arch_force_async_tag_fault() | ||||
| #endif | ||||
| #ifndef arch_get_random_tag | ||||
| #define arch_get_random_tag()	(0xFF) | ||||
| #endif | ||||
|  | @ -318,6 +321,7 @@ static inline const void *arch_kasan_set_tag(const void *addr, u8 tag) | |||
| #define hw_enable_tagging_async()		arch_enable_tagging_async() | ||||
| #define hw_init_tags(max_tag)			arch_init_tags(max_tag) | ||||
| #define hw_set_tagging_report_once(state)	arch_set_tagging_report_once(state) | ||||
| #define hw_force_async_tag_fault()		arch_force_async_tag_fault() | ||||
| #define hw_get_random_tag()			arch_get_random_tag() | ||||
| #define hw_get_mem_tag(addr)			arch_get_mem_tag(addr) | ||||
| #define hw_set_mem_tag_range(addr, size, tag)	arch_set_mem_tag_range((addr), (size), (tag)) | ||||
|  | @ -334,11 +338,13 @@ static inline const void *arch_kasan_set_tag(const void *addr, u8 tag) | |||
| 
 | ||||
| void kasan_set_tagging_report_once(bool state); | ||||
| void kasan_enable_tagging_sync(void); | ||||
| void kasan_force_async_fault(void); | ||||
| 
 | ||||
| #else /* CONFIG_KASAN_HW_TAGS || CONFIG_KASAN_KUNIT_TEST */ | ||||
| 
 | ||||
| static inline void kasan_set_tagging_report_once(bool state) { } | ||||
| static inline void kasan_enable_tagging_sync(void) { } | ||||
| static inline void kasan_force_async_fault(void) { } | ||||
| 
 | ||||
| #endif /* CONFIG_KASAN_HW_TAGS || CONFIG_KASAN_KUNIT_TEST */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -366,6 +366,11 @@ void kasan_report_async(void) | |||
| { | ||||
| 	unsigned long flags; | ||||
| 
 | ||||
| #if IS_ENABLED(CONFIG_KUNIT) | ||||
| 	if (current->kunit_test) | ||||
| 		kasan_update_kunit_status(current->kunit_test); | ||||
| #endif /* IS_ENABLED(CONFIG_KUNIT) */ | ||||
| 
 | ||||
| 	start_report(&flags); | ||||
| 	pr_err("BUG: KASAN: invalid-access\n"); | ||||
| 	pr_err("Asynchronous mode enabled: no access details available\n"); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Andrey Konovalov
						Andrey Konovalov