mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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_sync()		mte_enable_kernel_sync()
 | 
				
			||||||
#define arch_enable_tagging_async()		mte_enable_kernel_async()
 | 
					#define arch_enable_tagging_async()		mte_enable_kernel_async()
 | 
				
			||||||
#define arch_set_tagging_report_once(state)	mte_set_report_once(state)
 | 
					#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_init_tags(max_tag)			mte_init_tags(max_tag)
 | 
				
			||||||
#define arch_get_random_tag()			mte_get_random_tag()
 | 
					#define arch_get_random_tag()			mte_get_random_tag()
 | 
				
			||||||
#define arch_get_mem_tag(addr)			mte_get_mem_tag(addr)
 | 
					#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
 | 
					 * resource named "kasan_data". Do not use this name for KUnit resources
 | 
				
			||||||
 * outside of KASAN tests.
 | 
					 * outside of KASAN tests.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * For hardware tag-based KASAN, when a tag fault happens, tag checking is
 | 
					 * For hardware tag-based KASAN in sync mode, when a tag fault happens, tag
 | 
				
			||||||
 * normally auto-disabled. When this happens, this test handler reenables
 | 
					 * 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
 | 
					 * tag checking. As tag checking can be only disabled or enabled per CPU,
 | 
				
			||||||
 * handler disables migration (preemption).
 | 
					 * this handler disables migration (preemption).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Since the compiler doesn't see that the expression can change the fail_data
 | 
					 * 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.
 | 
					 * 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.
 | 
					 * expression to prevent that.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#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())			\
 | 
				
			||||||
		migrate_disable();				\
 | 
							migrate_disable();				\
 | 
				
			||||||
	WRITE_ONCE(fail_data.report_expected, true);		\
 | 
						WRITE_ONCE(fail_data.report_expected, true);		\
 | 
				
			||||||
	WRITE_ONCE(fail_data.report_found, false);		\
 | 
						WRITE_ONCE(fail_data.report_found, false);		\
 | 
				
			||||||
| 
						 | 
					@ -92,10 +93,14 @@ static void kasan_test_exit(struct kunit *test)
 | 
				
			||||||
	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();				\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -252,4 +252,10 @@ void kasan_enable_tagging_sync(void)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(kasan_enable_tagging_sync);
 | 
					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
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -304,6 +304,9 @@ static inline const void *arch_kasan_set_tag(const void *addr, u8 tag)
 | 
				
			||||||
#ifndef arch_set_tagging_report_once
 | 
					#ifndef arch_set_tagging_report_once
 | 
				
			||||||
#define arch_set_tagging_report_once(state)
 | 
					#define arch_set_tagging_report_once(state)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef arch_force_async_tag_fault
 | 
				
			||||||
 | 
					#define arch_force_async_tag_fault()
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifndef arch_get_random_tag
 | 
					#ifndef arch_get_random_tag
 | 
				
			||||||
#define arch_get_random_tag()	(0xFF)
 | 
					#define arch_get_random_tag()	(0xFF)
 | 
				
			||||||
#endif
 | 
					#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_enable_tagging_async()		arch_enable_tagging_async()
 | 
				
			||||||
#define hw_init_tags(max_tag)			arch_init_tags(max_tag)
 | 
					#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_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_random_tag()			arch_get_random_tag()
 | 
				
			||||||
#define hw_get_mem_tag(addr)			arch_get_mem_tag(addr)
 | 
					#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))
 | 
					#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_set_tagging_report_once(bool state);
 | 
				
			||||||
void kasan_enable_tagging_sync(void);
 | 
					void kasan_enable_tagging_sync(void);
 | 
				
			||||||
 | 
					void kasan_force_async_fault(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else /* CONFIG_KASAN_HW_TAGS || CONFIG_KASAN_KUNIT_TEST */
 | 
					#else /* CONFIG_KASAN_HW_TAGS || CONFIG_KASAN_KUNIT_TEST */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void kasan_set_tagging_report_once(bool state) { }
 | 
					static inline void kasan_set_tagging_report_once(bool state) { }
 | 
				
			||||||
static inline void kasan_enable_tagging_sync(void) { }
 | 
					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 */
 | 
					#endif /* CONFIG_KASAN_HW_TAGS || CONFIG_KASAN_KUNIT_TEST */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -366,6 +366,11 @@ void kasan_report_async(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long flags;
 | 
						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);
 | 
						start_report(&flags);
 | 
				
			||||||
	pr_err("BUG: KASAN: invalid-access\n");
 | 
						pr_err("BUG: KASAN: invalid-access\n");
 | 
				
			||||||
	pr_err("Asynchronous mode enabled: no access details available\n");
 | 
						pr_err("Asynchronous mode enabled: no access details available\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue