* [PATCH v5 0/2] kasan: unify kasan_enabled() and remove arch-specific implementations @ 2025-08-07 19:40 Sabyrzhan Tasbolatov 2025-08-07 19:40 ` [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes Sabyrzhan Tasbolatov 2025-08-07 19:40 ` [PATCH v5 2/2] kasan: call kasan_init_generic in kasan_init Sabyrzhan Tasbolatov 0 siblings, 2 replies; 13+ messages in thread From: Sabyrzhan Tasbolatov @ 2025-08-07 19:40 UTC (permalink / raw) To: ryabinin.a.a, bhe, hca, christophe.leroy, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov Cc: alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm, snovitoll This patch series addresses the fragmentation in KASAN initialization across architectures by introducing a unified approach that eliminates duplicate static keys and arch-specific kasan_arch_is_ready() implementations. The core issue is that different architectures have inconsistent approaches to KASAN readiness tracking: - PowerPC, LoongArch, and UML arch, each implement own kasan_arch_is_ready() - Only HW_TAGS mode had a unified static key (kasan_flag_enabled) - Generic and SW_TAGS modes relied on arch-specific solutions or always-on behavior Changes in v5: - Unified patches where arch (powerpc, UML, loongarch) selects ARCH_DEFER_KASAN in the first patch not to break bisectability. So in v5 we have 2 patches now in the series instead of 9. - Removed kasan_arch_is_ready completely as there is no user - Removed __wrappers in v4, left only those where it's necessary due to different implementations Tested on: - powerpc - selects ARCH_DEFER_KASAN Built ppc64_defconfig (PPC_BOOK3S_64) - OK Booted via qemu-system-ppc64 - OK I have not tested in v4 powerpc without KASAN enabled. In v4 arch/powerpc/Kconfig it was: select ARCH_DEFER_KASAN if PPC_RADIX_MMU and compiling with ppc64_defconfig caused: lib/stackdepot.o:(__jump_table+0x8): undefined reference to `kasan_flag_enabled' I have fixed it in v5 via adding KASAN condition: select ARCH_DEFER_KASAN if KASAN && PPC_RADIX_MMU - um - selects ARCH_DEFER_KASAN KASAN_GENERIC && KASAN_INLINE && STATIC_LINK Before: In file included from mm/kasan/common.c:32: mm/kasan/kasan.h:550:2: error: #error kasan_arch_is_ready only works in KASAN generic outline mode! 550 | #error kasan_arch_is_ready only works in KASAN generic outline mode After (with auto-selected ARCH_DEFER_KASAN): ./arch/um/include/asm/kasan.h:29:2: error: #error UML does not work in KASAN_INLINE mode with STATIC_LINK enabled! 29 | #error UML does not work in KASAN_INLINE mode with STATIC_LINK enabled! KASAN_GENERIC && KASAN_OUTLINE && STATIC_LINK && Before: ./linux boots. After (with auto-selected ARCH_DEFER_KASAN): ./linux boots. KASAN_GENERIC && KASAN_OUTLINE && !STATIC_LINK Before: ./linux boots After (with auto-disabled !ARCH_DEFER_KASAN): ./linux boots - loongarch - selects ARCH_DEFER_KASAN Built defconfig with KASAN_GENERIC - OK Haven't tested the boot. Asking Loongarch developers to verify - N/A But should be good, since Loongarch does not have specific "kasan_init()" call like UML does. It selects ARCH_DEFER_KASAN and calls kasan_init() in the end of setup_arch() after jump_label_init(). Previous v4 thread: https://lore.kernel.org/all/20250805142622.560992-1-snovitoll@gmail.com/ Previous v3 thread: https://lore.kernel.org/all/20250717142732.292822-1-snovitoll@gmail.com/ Previous v2 thread: https://lore.kernel.org/all/20250626153147.145312-1-snovitoll@gmail.com/ Sabyrzhan Tasbolatov (2): kasan: introduce ARCH_DEFER_KASAN and unify static key across modes kasan: call kasan_init_generic in kasan_init arch/arm/mm/kasan_init.c | 2 +- arch/arm64/mm/kasan_init.c | 4 +--- arch/loongarch/Kconfig | 1 + arch/loongarch/include/asm/kasan.h | 7 ------ arch/loongarch/mm/kasan_init.c | 8 +++---- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/kasan.h | 12 ---------- arch/powerpc/mm/kasan/init_32.c | 2 +- arch/powerpc/mm/kasan/init_book3e_64.c | 2 +- arch/powerpc/mm/kasan/init_book3s_64.c | 6 +---- arch/riscv/mm/kasan_init.c | 1 + arch/s390/kernel/early.c | 3 ++- arch/um/Kconfig | 1 + arch/um/include/asm/kasan.h | 5 ++-- arch/um/kernel/mem.c | 10 ++++++-- arch/x86/mm/kasan_init_64.c | 2 +- arch/xtensa/mm/kasan_init.c | 2 +- include/linux/kasan-enabled.h | 32 ++++++++++++++++++-------- include/linux/kasan.h | 6 +++++ lib/Kconfig.kasan | 8 +++++++ mm/kasan/common.c | 17 ++++++++++---- mm/kasan/generic.c | 19 +++++++++++---- mm/kasan/hw_tags.c | 9 +------- mm/kasan/kasan.h | 8 ++++++- mm/kasan/shadow.c | 12 +++++----- mm/kasan/sw_tags.c | 1 + mm/kasan/tags.c | 2 +- 27 files changed, 107 insertions(+), 76 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes 2025-08-07 19:40 [PATCH v5 0/2] kasan: unify kasan_enabled() and remove arch-specific implementations Sabyrzhan Tasbolatov @ 2025-08-07 19:40 ` Sabyrzhan Tasbolatov 2025-08-08 5:03 ` Christophe Leroy 2025-08-07 19:40 ` [PATCH v5 2/2] kasan: call kasan_init_generic in kasan_init Sabyrzhan Tasbolatov 1 sibling, 1 reply; 13+ messages in thread From: Sabyrzhan Tasbolatov @ 2025-08-07 19:40 UTC (permalink / raw) To: ryabinin.a.a, bhe, hca, christophe.leroy, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov Cc: alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm, snovitoll Introduce CONFIG_ARCH_DEFER_KASAN to identify architectures [1] that need to defer KASAN initialization until shadow memory is properly set up, and unify the static key infrastructure across all KASAN modes. [1] PowerPC, UML, LoongArch selects ARCH_DEFER_KASAN. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049 Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> --- Changes in v5: - Unified patches where arch (powerpc, UML, loongarch) selects ARCH_DEFER_KASAN in the first patch not to break bisectability - Removed kasan_arch_is_ready completely as there is no user - Removed __wrappers in v4, left only those where it's necessary due to different implementations Changes in v4: - Fixed HW_TAGS static key functionality (was broken in v3) - Merged configuration and implementation for atomicity --- arch/loongarch/Kconfig | 1 + arch/loongarch/include/asm/kasan.h | 7 ------ arch/loongarch/mm/kasan_init.c | 8 +++---- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/kasan.h | 12 ---------- arch/powerpc/mm/kasan/init_32.c | 2 +- arch/powerpc/mm/kasan/init_book3e_64.c | 2 +- arch/powerpc/mm/kasan/init_book3s_64.c | 6 +---- arch/um/Kconfig | 1 + arch/um/include/asm/kasan.h | 5 ++-- arch/um/kernel/mem.c | 10 ++++++-- include/linux/kasan-enabled.h | 32 ++++++++++++++++++-------- include/linux/kasan.h | 6 +++++ lib/Kconfig.kasan | 8 +++++++ mm/kasan/common.c | 17 ++++++++++---- mm/kasan/generic.c | 19 +++++++++++---- mm/kasan/hw_tags.c | 9 +------- mm/kasan/kasan.h | 8 ++++++- mm/kasan/shadow.c | 12 +++++----- mm/kasan/sw_tags.c | 1 + mm/kasan/tags.c | 2 +- 21 files changed, 100 insertions(+), 69 deletions(-) diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index f0abc38c40a..cd64b2bc12d 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -9,6 +9,7 @@ config LOONGARCH select ACPI_PPTT if ACPI select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI select ARCH_BINFMT_ELF_STATE + select ARCH_DEFER_KASAN if KASAN select ARCH_DISABLE_KASAN_INLINE select ARCH_ENABLE_MEMORY_HOTPLUG select ARCH_ENABLE_MEMORY_HOTREMOVE diff --git a/arch/loongarch/include/asm/kasan.h b/arch/loongarch/include/asm/kasan.h index 62f139a9c87..0e50e5b5e05 100644 --- a/arch/loongarch/include/asm/kasan.h +++ b/arch/loongarch/include/asm/kasan.h @@ -66,7 +66,6 @@ #define XKPRANGE_WC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_WC_KASAN_OFFSET) #define XKVRANGE_VC_SHADOW_OFFSET (KASAN_SHADOW_START + XKVRANGE_VC_KASAN_OFFSET) -extern bool kasan_early_stage; extern unsigned char kasan_early_shadow_page[PAGE_SIZE]; #define kasan_mem_to_shadow kasan_mem_to_shadow @@ -75,12 +74,6 @@ void *kasan_mem_to_shadow(const void *addr); #define kasan_shadow_to_mem kasan_shadow_to_mem const void *kasan_shadow_to_mem(const void *shadow_addr); -#define kasan_arch_is_ready kasan_arch_is_ready -static __always_inline bool kasan_arch_is_ready(void) -{ - return !kasan_early_stage; -} - #define addr_has_metadata addr_has_metadata static __always_inline bool addr_has_metadata(const void *addr) { diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c index d2681272d8f..170da98ad4f 100644 --- a/arch/loongarch/mm/kasan_init.c +++ b/arch/loongarch/mm/kasan_init.c @@ -40,11 +40,9 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); #define __pte_none(early, pte) (early ? pte_none(pte) : \ ((pte_val(pte) & _PFN_MASK) == (unsigned long)__pa(kasan_early_shadow_page))) -bool kasan_early_stage = true; - void *kasan_mem_to_shadow(const void *addr) { - if (!kasan_arch_is_ready()) { + if (!kasan_enabled()) { return (void *)(kasan_early_shadow_page); } else { unsigned long maddr = (unsigned long)addr; @@ -298,7 +296,8 @@ void __init kasan_init(void) kasan_populate_early_shadow(kasan_mem_to_shadow((void *)VMALLOC_START), kasan_mem_to_shadow((void *)KFENCE_AREA_END)); - kasan_early_stage = false; + /* Enable KASAN here before kasan_mem_to_shadow(). */ + kasan_init_generic(); /* Populate the linear mapping */ for_each_mem_range(i, &pa_start, &pa_end) { @@ -329,5 +328,4 @@ void __init kasan_init(void) /* At this point kasan is fully initialized. Enable error messages */ init_task.kasan_depth = 0; - pr_info("KernelAddressSanitizer initialized.\n"); } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 93402a1d9c9..a324dcdb8eb 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -122,6 +122,7 @@ config PPC # Please keep this list sorted alphabetically. # select ARCH_32BIT_OFF_T if PPC32 + select ARCH_DEFER_KASAN if KASAN && PPC_RADIX_MMU select ARCH_DISABLE_KASAN_INLINE if PPC_RADIX_MMU select ARCH_DMA_DEFAULT_COHERENT if !NOT_COHERENT_CACHE select ARCH_ENABLE_MEMORY_HOTPLUG diff --git a/arch/powerpc/include/asm/kasan.h b/arch/powerpc/include/asm/kasan.h index b5bbb94c51f..957a57c1db5 100644 --- a/arch/powerpc/include/asm/kasan.h +++ b/arch/powerpc/include/asm/kasan.h @@ -53,18 +53,6 @@ #endif #ifdef CONFIG_KASAN -#ifdef CONFIG_PPC_BOOK3S_64 -DECLARE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); - -static __always_inline bool kasan_arch_is_ready(void) -{ - if (static_branch_likely(&powerpc_kasan_enabled_key)) - return true; - return false; -} - -#define kasan_arch_is_ready kasan_arch_is_ready -#endif void kasan_early_init(void); void kasan_mmu_init(void); diff --git a/arch/powerpc/mm/kasan/init_32.c b/arch/powerpc/mm/kasan/init_32.c index 03666d790a5..1d083597464 100644 --- a/arch/powerpc/mm/kasan/init_32.c +++ b/arch/powerpc/mm/kasan/init_32.c @@ -165,7 +165,7 @@ void __init kasan_init(void) /* At this point kasan is fully initialized. Enable error messages */ init_task.kasan_depth = 0; - pr_info("KASAN init done\n"); + kasan_init_generic(); } void __init kasan_late_init(void) diff --git a/arch/powerpc/mm/kasan/init_book3e_64.c b/arch/powerpc/mm/kasan/init_book3e_64.c index 60c78aac0f6..0d3a73d6d4b 100644 --- a/arch/powerpc/mm/kasan/init_book3e_64.c +++ b/arch/powerpc/mm/kasan/init_book3e_64.c @@ -127,7 +127,7 @@ void __init kasan_init(void) /* Enable error messages */ init_task.kasan_depth = 0; - pr_info("KASAN init done\n"); + kasan_init_generic(); } void __init kasan_late_init(void) { } diff --git a/arch/powerpc/mm/kasan/init_book3s_64.c b/arch/powerpc/mm/kasan/init_book3s_64.c index 7d959544c07..dcafa641804 100644 --- a/arch/powerpc/mm/kasan/init_book3s_64.c +++ b/arch/powerpc/mm/kasan/init_book3s_64.c @@ -19,8 +19,6 @@ #include <linux/memblock.h> #include <asm/pgalloc.h> -DEFINE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); - static void __init kasan_init_phys_region(void *start, void *end) { unsigned long k_start, k_end, k_cur; @@ -92,11 +90,9 @@ void __init kasan_init(void) */ memset(kasan_early_shadow_page, 0, PAGE_SIZE); - static_branch_inc(&powerpc_kasan_enabled_key); - /* Enable error messages */ init_task.kasan_depth = 0; - pr_info("KASAN init done\n"); + kasan_init_generic(); } void __init kasan_early_init(void) { } diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 9083bfdb773..a12cc072ab1 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -5,6 +5,7 @@ menu "UML-specific options" config UML bool default y + select ARCH_DEFER_KASAN if STATIC_LINK select ARCH_WANTS_DYNAMIC_TASK_STRUCT select ARCH_HAS_CACHE_LINE_SIZE select ARCH_HAS_CPU_FINALIZE_INIT diff --git a/arch/um/include/asm/kasan.h b/arch/um/include/asm/kasan.h index f97bb1f7b85..b54a4e937fd 100644 --- a/arch/um/include/asm/kasan.h +++ b/arch/um/include/asm/kasan.h @@ -24,10 +24,9 @@ #ifdef CONFIG_KASAN void kasan_init(void); -extern int kasan_um_is_ready; -#ifdef CONFIG_STATIC_LINK -#define kasan_arch_is_ready() (kasan_um_is_ready) +#if defined(CONFIG_STATIC_LINK) && defined(CONFIG_KASAN_INLINE) +#error UML does not work in KASAN_INLINE mode with STATIC_LINK enabled! #endif #else static inline void kasan_init(void) { } diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 76bec7de81b..261fdcd21be 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -21,9 +21,9 @@ #include <os.h> #include <um_malloc.h> #include <linux/sched/task.h> +#include <linux/kasan.h> #ifdef CONFIG_KASAN -int kasan_um_is_ready; void kasan_init(void) { /* @@ -32,7 +32,10 @@ void kasan_init(void) */ kasan_map_memory((void *)KASAN_SHADOW_START, KASAN_SHADOW_SIZE); init_task.kasan_depth = 0; - kasan_um_is_ready = true; + /* Since kasan_init() is called before main(), + * KASAN is initialized but the enablement is deferred after + * jump_label_init(). See arch_mm_preinit(). + */ } static void (*kasan_init_ptr)(void) @@ -58,6 +61,9 @@ static unsigned long brk_end; void __init arch_mm_preinit(void) { + /* Safe to call after jump_label_init(). Enables KASAN. */ + kasan_init_generic(); + /* clear the zero-page */ memset(empty_zero_page, 0, PAGE_SIZE); diff --git a/include/linux/kasan-enabled.h b/include/linux/kasan-enabled.h index 6f612d69ea0..9eca967d852 100644 --- a/include/linux/kasan-enabled.h +++ b/include/linux/kasan-enabled.h @@ -4,32 +4,46 @@ #include <linux/static_key.h> -#ifdef CONFIG_KASAN_HW_TAGS - +#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS) +/* + * Global runtime flag for KASAN modes that need runtime control. + * Used by ARCH_DEFER_KASAN architectures and HW_TAGS mode. + */ DECLARE_STATIC_KEY_FALSE(kasan_flag_enabled); +/* + * Runtime control for shadow memory initialization or HW_TAGS mode. + * Uses static key for architectures that need deferred KASAN or HW_TAGS. + */ static __always_inline bool kasan_enabled(void) { return static_branch_likely(&kasan_flag_enabled); } -static inline bool kasan_hw_tags_enabled(void) +static inline void kasan_enable(void) { - return kasan_enabled(); + static_branch_enable(&kasan_flag_enabled); } - -#else /* CONFIG_KASAN_HW_TAGS */ - -static inline bool kasan_enabled(void) +#else +/* For architectures that can enable KASAN early, use compile-time check. */ +static __always_inline bool kasan_enabled(void) { return IS_ENABLED(CONFIG_KASAN); } +static inline void kasan_enable(void) {} +#endif /* CONFIG_ARCH_DEFER_KASAN || CONFIG_KASAN_HW_TAGS */ + +#ifdef CONFIG_KASAN_HW_TAGS +static inline bool kasan_hw_tags_enabled(void) +{ + return kasan_enabled(); +} +#else static inline bool kasan_hw_tags_enabled(void) { return false; } - #endif /* CONFIG_KASAN_HW_TAGS */ #endif /* LINUX_KASAN_ENABLED_H */ diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 890011071f2..51a8293d1af 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -543,6 +543,12 @@ void kasan_report_async(void); #endif /* CONFIG_KASAN_HW_TAGS */ +#ifdef CONFIG_KASAN_GENERIC +void __init kasan_init_generic(void); +#else +static inline void kasan_init_generic(void) { } +#endif + #ifdef CONFIG_KASAN_SW_TAGS void __init kasan_init_sw_tags(void); #else diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index f82889a830f..38456560c85 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -19,6 +19,14 @@ config ARCH_DISABLE_KASAN_INLINE Disables both inline and stack instrumentation. Selected by architectures that do not support these instrumentation types. +config ARCH_DEFER_KASAN + bool + help + Architectures should select this if they need to defer KASAN + initialization until shadow memory is properly set up. This + enables runtime control via static keys. Otherwise, KASAN uses + compile-time constants for better performance. + config CC_HAS_KASAN_GENERIC def_bool $(cc-option, -fsanitize=kernel-address) diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 9142964ab9c..d9d389870a2 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -32,6 +32,15 @@ #include "kasan.h" #include "../slab.h" +#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS) +/* + * Definition of the unified static key declared in kasan-enabled.h. + * This provides consistent runtime enable/disable across KASAN modes. + */ +DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); +EXPORT_SYMBOL(kasan_flag_enabled); +#endif + struct slab *kasan_addr_to_slab(const void *addr) { if (virt_addr_valid(addr)) @@ -246,7 +255,7 @@ static inline void poison_slab_object(struct kmem_cache *cache, void *object, bool __kasan_slab_pre_free(struct kmem_cache *cache, void *object, unsigned long ip) { - if (!kasan_arch_is_ready() || is_kfence_address(object)) + if (is_kfence_address(object)) return false; return check_slab_allocation(cache, object, ip); } @@ -254,7 +263,7 @@ bool __kasan_slab_pre_free(struct kmem_cache *cache, void *object, bool __kasan_slab_free(struct kmem_cache *cache, void *object, bool init, bool still_accessible) { - if (!kasan_arch_is_ready() || is_kfence_address(object)) + if (is_kfence_address(object)) return false; /* @@ -293,7 +302,7 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *object, bool init, static inline bool check_page_allocation(void *ptr, unsigned long ip) { - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return false; if (ptr != page_address(virt_to_head_page(ptr))) { @@ -522,7 +531,7 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned long ip) return true; } - if (is_kfence_address(ptr) || !kasan_arch_is_ready()) + if (is_kfence_address(ptr)) return true; slab = folio_slab(folio); diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c index d54e89f8c3e..b413c46b3e0 100644 --- a/mm/kasan/generic.c +++ b/mm/kasan/generic.c @@ -36,6 +36,17 @@ #include "kasan.h" #include "../slab.h" +/* + * Initialize Generic KASAN and enable runtime checks. + * This should be called from arch kasan_init() once shadow memory is ready. + */ +void __init kasan_init_generic(void) +{ + kasan_enable(); + + pr_info("KernelAddressSanitizer initialized (generic)\n"); +} + /* * All functions below always inlined so compiler could * perform better optimizations in each of __asan_loadX/__assn_storeX @@ -165,7 +176,7 @@ static __always_inline bool check_region_inline(const void *addr, size_t size, bool write, unsigned long ret_ip) { - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return true; if (unlikely(size == 0)) @@ -193,7 +204,7 @@ bool kasan_byte_accessible(const void *addr) { s8 shadow_byte; - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return true; shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(addr)); @@ -495,7 +506,7 @@ static void release_alloc_meta(struct kasan_alloc_meta *meta) static void release_free_meta(const void *object, struct kasan_free_meta *meta) { - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return; /* Check if free meta is valid. */ @@ -562,7 +573,7 @@ void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags) kasan_save_track(&alloc_meta->alloc_track, flags); } -void kasan_save_free_info(struct kmem_cache *cache, void *object) +void __kasan_save_free_info(struct kmem_cache *cache, void *object) { struct kasan_free_meta *free_meta; diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c index 9a6927394b5..c8289a3feab 100644 --- a/mm/kasan/hw_tags.c +++ b/mm/kasan/hw_tags.c @@ -45,13 +45,6 @@ static enum kasan_arg kasan_arg __ro_after_init; static enum kasan_arg_mode kasan_arg_mode __ro_after_init; static enum kasan_arg_vmalloc kasan_arg_vmalloc __initdata; -/* - * Whether KASAN is enabled at all. - * The value remains false until KASAN is initialized by kasan_init_hw_tags(). - */ -DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); -EXPORT_SYMBOL(kasan_flag_enabled); - /* * Whether the selected mode is synchronous, asynchronous, or asymmetric. * Defaults to KASAN_MODE_SYNC. @@ -260,7 +253,7 @@ void __init kasan_init_hw_tags(void) kasan_init_tags(); /* KASAN is now initialized, enable it. */ - static_branch_enable(&kasan_flag_enabled); + kasan_enable(); pr_info("KernelAddressSanitizer initialized (hw-tags, mode=%s, vmalloc=%s, stacktrace=%s)\n", kasan_mode_info(), diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index 129178be5e6..8a9d8a6ea71 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -398,7 +398,13 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags, depot_flags_t depot_flags); void kasan_set_track(struct kasan_track *track, depot_stack_handle_t stack); void kasan_save_track(struct kasan_track *track, gfp_t flags); void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags); -void kasan_save_free_info(struct kmem_cache *cache, void *object); + +void __kasan_save_free_info(struct kmem_cache *cache, void *object); +static inline void kasan_save_free_info(struct kmem_cache *cache, void *object) +{ + if (kasan_enabled()) + __kasan_save_free_info(cache, object); +} #ifdef CONFIG_KASAN_GENERIC bool kasan_quarantine_put(struct kmem_cache *cache, void *object); diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c index d2c70cd2afb..2e126cb21b6 100644 --- a/mm/kasan/shadow.c +++ b/mm/kasan/shadow.c @@ -125,7 +125,7 @@ void kasan_poison(const void *addr, size_t size, u8 value, bool init) { void *shadow_start, *shadow_end; - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return; /* @@ -150,7 +150,7 @@ EXPORT_SYMBOL_GPL(kasan_poison); #ifdef CONFIG_KASAN_GENERIC void kasan_poison_last_granule(const void *addr, size_t size) { - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return; if (size & KASAN_GRANULE_MASK) { @@ -390,7 +390,7 @@ int kasan_populate_vmalloc(unsigned long addr, unsigned long size) unsigned long shadow_start, shadow_end; int ret; - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return 0; if (!is_vmalloc_or_module_addr((void *)addr)) @@ -560,7 +560,7 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end, unsigned long region_start, region_end; unsigned long size; - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return; region_start = ALIGN(start, KASAN_MEMORY_PER_SHADOW_PAGE); @@ -611,7 +611,7 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size, * with setting memory tags, so the KASAN_VMALLOC_INIT flag is ignored. */ - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return (void *)start; if (!is_vmalloc_or_module_addr(start)) @@ -636,7 +636,7 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size, */ void __kasan_poison_vmalloc(const void *start, unsigned long size) { - if (!kasan_arch_is_ready()) + if (!kasan_enabled()) return; if (!is_vmalloc_or_module_addr(start)) diff --git a/mm/kasan/sw_tags.c b/mm/kasan/sw_tags.c index b9382b5b6a3..c75741a7460 100644 --- a/mm/kasan/sw_tags.c +++ b/mm/kasan/sw_tags.c @@ -44,6 +44,7 @@ void __init kasan_init_sw_tags(void) per_cpu(prng_state, cpu) = (u32)get_cycles(); kasan_init_tags(); + kasan_enable(); pr_info("KernelAddressSanitizer initialized (sw-tags, stacktrace=%s)\n", str_on_off(kasan_stack_collection_enabled())); diff --git a/mm/kasan/tags.c b/mm/kasan/tags.c index d65d48b85f9..b9f31293622 100644 --- a/mm/kasan/tags.c +++ b/mm/kasan/tags.c @@ -142,7 +142,7 @@ void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags) save_stack_info(cache, object, flags, false); } -void kasan_save_free_info(struct kmem_cache *cache, void *object) +void __kasan_save_free_info(struct kmem_cache *cache, void *object) { save_stack_info(cache, object, 0, true); } -- 2.34.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes 2025-08-07 19:40 ` [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes Sabyrzhan Tasbolatov @ 2025-08-08 5:03 ` Christophe Leroy 2025-08-08 7:26 ` Sabyrzhan Tasbolatov 2025-08-08 15:33 ` Sabyrzhan Tasbolatov 0 siblings, 2 replies; 13+ messages in thread From: Christophe Leroy @ 2025-08-08 5:03 UTC (permalink / raw) To: Sabyrzhan Tasbolatov, ryabinin.a.a, bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov Cc: alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm Le 07/08/2025 à 21:40, Sabyrzhan Tasbolatov a écrit : > Introduce CONFIG_ARCH_DEFER_KASAN to identify architectures [1] that need > to defer KASAN initialization until shadow memory is properly set up, > and unify the static key infrastructure across all KASAN modes. That probably desserves more details, maybe copy in informations from the top of cover letter. I think there should also be some exeplanations about kasan_arch_is_ready() becoming kasan_enabled(), and also why kasan_arch_is_ready() completely disappear from mm/kasan/common.c without being replaced by kasan_enabled(). > > [1] PowerPC, UML, LoongArch selects ARCH_DEFER_KASAN. > > Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049 > Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> > --- > Changes in v5: > - Unified patches where arch (powerpc, UML, loongarch) selects > ARCH_DEFER_KASAN in the first patch not to break > bisectability > - Removed kasan_arch_is_ready completely as there is no user > - Removed __wrappers in v4, left only those where it's necessary > due to different implementations > > Changes in v4: > - Fixed HW_TAGS static key functionality (was broken in v3) > - Merged configuration and implementation for atomicity > --- > arch/loongarch/Kconfig | 1 + > arch/loongarch/include/asm/kasan.h | 7 ------ > arch/loongarch/mm/kasan_init.c | 8 +++---- > arch/powerpc/Kconfig | 1 + > arch/powerpc/include/asm/kasan.h | 12 ---------- > arch/powerpc/mm/kasan/init_32.c | 2 +- > arch/powerpc/mm/kasan/init_book3e_64.c | 2 +- > arch/powerpc/mm/kasan/init_book3s_64.c | 6 +---- > arch/um/Kconfig | 1 + > arch/um/include/asm/kasan.h | 5 ++-- > arch/um/kernel/mem.c | 10 ++++++-- > include/linux/kasan-enabled.h | 32 ++++++++++++++++++-------- > include/linux/kasan.h | 6 +++++ > lib/Kconfig.kasan | 8 +++++++ > mm/kasan/common.c | 17 ++++++++++---- > mm/kasan/generic.c | 19 +++++++++++---- > mm/kasan/hw_tags.c | 9 +------- > mm/kasan/kasan.h | 8 ++++++- > mm/kasan/shadow.c | 12 +++++----- > mm/kasan/sw_tags.c | 1 + > mm/kasan/tags.c | 2 +- > 21 files changed, 100 insertions(+), 69 deletions(-) > > diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig > index f0abc38c40a..cd64b2bc12d 100644 > --- a/arch/loongarch/Kconfig > +++ b/arch/loongarch/Kconfig > @@ -9,6 +9,7 @@ config LOONGARCH > select ACPI_PPTT if ACPI > select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI > select ARCH_BINFMT_ELF_STATE > + select ARCH_DEFER_KASAN if KASAN Instead of adding 'if KASAN' in all users, you could do in two steps: Add a symbol ARCH_NEEDS_DEFER_KASAN. +config ARCH_NEEDS_DEFER_KASAN + bool And then: +config ARCH_DEFER_KASAN + def_bool + depends on KASAN + depends on ARCH_DEFER_KASAN + help + Architectures should select this if they need to defer KASAN + initialization until shadow memory is properly set up. This + enables runtime control via static keys. Otherwise, KASAN uses + compile-time constants for better performance. > select ARCH_DISABLE_KASAN_INLINE > select ARCH_ENABLE_MEMORY_HOTPLUG > select ARCH_ENABLE_MEMORY_HOTREMOVE > diff --git a/arch/loongarch/include/asm/kasan.h b/arch/loongarch/include/asm/kasan.h > index 62f139a9c87..0e50e5b5e05 100644 > --- a/arch/loongarch/include/asm/kasan.h > +++ b/arch/loongarch/include/asm/kasan.h > @@ -66,7 +66,6 @@ > #define XKPRANGE_WC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_WC_KASAN_OFFSET) > #define XKVRANGE_VC_SHADOW_OFFSET (KASAN_SHADOW_START + XKVRANGE_VC_KASAN_OFFSET) > > -extern bool kasan_early_stage; > extern unsigned char kasan_early_shadow_page[PAGE_SIZE]; > > #define kasan_mem_to_shadow kasan_mem_to_shadow > @@ -75,12 +74,6 @@ void *kasan_mem_to_shadow(const void *addr); > #define kasan_shadow_to_mem kasan_shadow_to_mem > const void *kasan_shadow_to_mem(const void *shadow_addr); > > -#define kasan_arch_is_ready kasan_arch_is_ready > -static __always_inline bool kasan_arch_is_ready(void) > -{ > - return !kasan_early_stage; > -} > - > #define addr_has_metadata addr_has_metadata > static __always_inline bool addr_has_metadata(const void *addr) > { > diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c > index d2681272d8f..170da98ad4f 100644 > --- a/arch/loongarch/mm/kasan_init.c > +++ b/arch/loongarch/mm/kasan_init.c > @@ -40,11 +40,9 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); > #define __pte_none(early, pte) (early ? pte_none(pte) : \ > ((pte_val(pte) & _PFN_MASK) == (unsigned long)__pa(kasan_early_shadow_page))) > > -bool kasan_early_stage = true; > - > void *kasan_mem_to_shadow(const void *addr) > { > - if (!kasan_arch_is_ready()) { > + if (!kasan_enabled()) { > return (void *)(kasan_early_shadow_page); > } else { > unsigned long maddr = (unsigned long)addr; > @@ -298,7 +296,8 @@ void __init kasan_init(void) > kasan_populate_early_shadow(kasan_mem_to_shadow((void *)VMALLOC_START), > kasan_mem_to_shadow((void *)KFENCE_AREA_END)); > > - kasan_early_stage = false; > + /* Enable KASAN here before kasan_mem_to_shadow(). */ > + kasan_init_generic(); > > /* Populate the linear mapping */ > for_each_mem_range(i, &pa_start, &pa_end) { > @@ -329,5 +328,4 @@ void __init kasan_init(void) > > /* At this point kasan is fully initialized. Enable error messages */ > init_task.kasan_depth = 0; > - pr_info("KernelAddressSanitizer initialized.\n"); > } > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > index 93402a1d9c9..a324dcdb8eb 100644 > --- a/arch/powerpc/Kconfig > +++ b/arch/powerpc/Kconfig > @@ -122,6 +122,7 @@ config PPC > # Please keep this list sorted alphabetically. > # > select ARCH_32BIT_OFF_T if PPC32 > + select ARCH_DEFER_KASAN if KASAN && PPC_RADIX_MMU > select ARCH_DISABLE_KASAN_INLINE if PPC_RADIX_MMU > select ARCH_DMA_DEFAULT_COHERENT if !NOT_COHERENT_CACHE > select ARCH_ENABLE_MEMORY_HOTPLUG > diff --git a/arch/powerpc/include/asm/kasan.h b/arch/powerpc/include/asm/kasan.h > index b5bbb94c51f..957a57c1db5 100644 > --- a/arch/powerpc/include/asm/kasan.h > +++ b/arch/powerpc/include/asm/kasan.h > @@ -53,18 +53,6 @@ > #endif > > #ifdef CONFIG_KASAN > -#ifdef CONFIG_PPC_BOOK3S_64 > -DECLARE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); > - > -static __always_inline bool kasan_arch_is_ready(void) > -{ > - if (static_branch_likely(&powerpc_kasan_enabled_key)) > - return true; > - return false; > -} > - > -#define kasan_arch_is_ready kasan_arch_is_ready > -#endif > > void kasan_early_init(void); > void kasan_mmu_init(void); > diff --git a/arch/powerpc/mm/kasan/init_32.c b/arch/powerpc/mm/kasan/init_32.c > index 03666d790a5..1d083597464 100644 > --- a/arch/powerpc/mm/kasan/init_32.c > +++ b/arch/powerpc/mm/kasan/init_32.c > @@ -165,7 +165,7 @@ void __init kasan_init(void) > > /* At this point kasan is fully initialized. Enable error messages */ > init_task.kasan_depth = 0; > - pr_info("KASAN init done\n"); > + kasan_init_generic(); > } > > void __init kasan_late_init(void) > diff --git a/arch/powerpc/mm/kasan/init_book3e_64.c b/arch/powerpc/mm/kasan/init_book3e_64.c > index 60c78aac0f6..0d3a73d6d4b 100644 > --- a/arch/powerpc/mm/kasan/init_book3e_64.c > +++ b/arch/powerpc/mm/kasan/init_book3e_64.c > @@ -127,7 +127,7 @@ void __init kasan_init(void) > > /* Enable error messages */ > init_task.kasan_depth = 0; > - pr_info("KASAN init done\n"); > + kasan_init_generic(); > } > > void __init kasan_late_init(void) { } > diff --git a/arch/powerpc/mm/kasan/init_book3s_64.c b/arch/powerpc/mm/kasan/init_book3s_64.c > index 7d959544c07..dcafa641804 100644 > --- a/arch/powerpc/mm/kasan/init_book3s_64.c > +++ b/arch/powerpc/mm/kasan/init_book3s_64.c > @@ -19,8 +19,6 @@ > #include <linux/memblock.h> > #include <asm/pgalloc.h> > > -DEFINE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); > - > static void __init kasan_init_phys_region(void *start, void *end) > { > unsigned long k_start, k_end, k_cur; > @@ -92,11 +90,9 @@ void __init kasan_init(void) > */ > memset(kasan_early_shadow_page, 0, PAGE_SIZE); > > - static_branch_inc(&powerpc_kasan_enabled_key); > - > /* Enable error messages */ > init_task.kasan_depth = 0; > - pr_info("KASAN init done\n"); > + kasan_init_generic(); > } > > void __init kasan_early_init(void) { } > diff --git a/arch/um/Kconfig b/arch/um/Kconfig > index 9083bfdb773..a12cc072ab1 100644 > --- a/arch/um/Kconfig > +++ b/arch/um/Kconfig > @@ -5,6 +5,7 @@ menu "UML-specific options" > config UML > bool > default y > + select ARCH_DEFER_KASAN if STATIC_LINK No need to also verify KASAN here like powerpc and loongarch ? > select ARCH_WANTS_DYNAMIC_TASK_STRUCT > select ARCH_HAS_CACHE_LINE_SIZE > select ARCH_HAS_CPU_FINALIZE_INIT > diff --git a/arch/um/include/asm/kasan.h b/arch/um/include/asm/kasan.h > index f97bb1f7b85..b54a4e937fd 100644 > --- a/arch/um/include/asm/kasan.h > +++ b/arch/um/include/asm/kasan.h > @@ -24,10 +24,9 @@ > > #ifdef CONFIG_KASAN > void kasan_init(void); > -extern int kasan_um_is_ready; > > -#ifdef CONFIG_STATIC_LINK > -#define kasan_arch_is_ready() (kasan_um_is_ready) > +#if defined(CONFIG_STATIC_LINK) && defined(CONFIG_KASAN_INLINE) > +#error UML does not work in KASAN_INLINE mode with STATIC_LINK enabled! > #endif > #else > static inline void kasan_init(void) { } > diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c > index 76bec7de81b..261fdcd21be 100644 > --- a/arch/um/kernel/mem.c > +++ b/arch/um/kernel/mem.c > @@ -21,9 +21,9 @@ > #include <os.h> > #include <um_malloc.h> > #include <linux/sched/task.h> > +#include <linux/kasan.h> > > #ifdef CONFIG_KASAN > -int kasan_um_is_ready; > void kasan_init(void) > { > /* > @@ -32,7 +32,10 @@ void kasan_init(void) > */ > kasan_map_memory((void *)KASAN_SHADOW_START, KASAN_SHADOW_SIZE); > init_task.kasan_depth = 0; > - kasan_um_is_ready = true; > + /* Since kasan_init() is called before main(), > + * KASAN is initialized but the enablement is deferred after > + * jump_label_init(). See arch_mm_preinit(). > + */ Format standard is different outside network, see: https://docs.kernel.org/process/coding-style.html#commenting > } > > static void (*kasan_init_ptr)(void) > @@ -58,6 +61,9 @@ static unsigned long brk_end; > > void __init arch_mm_preinit(void) > { > + /* Safe to call after jump_label_init(). Enables KASAN. */ > + kasan_init_generic(); > + > /* clear the zero-page */ > memset(empty_zero_page, 0, PAGE_SIZE); > > diff --git a/include/linux/kasan-enabled.h b/include/linux/kasan-enabled.h > index 6f612d69ea0..9eca967d852 100644 > --- a/include/linux/kasan-enabled.h > +++ b/include/linux/kasan-enabled.h > @@ -4,32 +4,46 @@ > > #include <linux/static_key.h> > > -#ifdef CONFIG_KASAN_HW_TAGS > - > +#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS) > +/* > + * Global runtime flag for KASAN modes that need runtime control. > + * Used by ARCH_DEFER_KASAN architectures and HW_TAGS mode. > + */ > DECLARE_STATIC_KEY_FALSE(kasan_flag_enabled); > > +/* > + * Runtime control for shadow memory initialization or HW_TAGS mode. > + * Uses static key for architectures that need deferred KASAN or HW_TAGS. > + */ > static __always_inline bool kasan_enabled(void) > { > return static_branch_likely(&kasan_flag_enabled); > } > > -static inline bool kasan_hw_tags_enabled(void) > +static inline void kasan_enable(void) > { > - return kasan_enabled(); > + static_branch_enable(&kasan_flag_enabled); > } > - > -#else /* CONFIG_KASAN_HW_TAGS */ > - > -static inline bool kasan_enabled(void) > +#else > +/* For architectures that can enable KASAN early, use compile-time check. */ > +static __always_inline bool kasan_enabled(void) > { > return IS_ENABLED(CONFIG_KASAN); > } > > +static inline void kasan_enable(void) {} > +#endif /* CONFIG_ARCH_DEFER_KASAN || CONFIG_KASAN_HW_TAGS */ > + > +#ifdef CONFIG_KASAN_HW_TAGS > +static inline bool kasan_hw_tags_enabled(void) > +{ > + return kasan_enabled(); > +} > +#else > static inline bool kasan_hw_tags_enabled(void) > { > return false; > } > - > #endif /* CONFIG_KASAN_HW_TAGS */ > > #endif /* LINUX_KASAN_ENABLED_H */ > diff --git a/include/linux/kasan.h b/include/linux/kasan.h > index 890011071f2..51a8293d1af 100644 > --- a/include/linux/kasan.h > +++ b/include/linux/kasan.h > @@ -543,6 +543,12 @@ void kasan_report_async(void); > > #endif /* CONFIG_KASAN_HW_TAGS */ > > +#ifdef CONFIG_KASAN_GENERIC > +void __init kasan_init_generic(void); > +#else > +static inline void kasan_init_generic(void) { } > +#endif > + > #ifdef CONFIG_KASAN_SW_TAGS > void __init kasan_init_sw_tags(void); > #else > diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan > index f82889a830f..38456560c85 100644 > --- a/lib/Kconfig.kasan > +++ b/lib/Kconfig.kasan > @@ -19,6 +19,14 @@ config ARCH_DISABLE_KASAN_INLINE > Disables both inline and stack instrumentation. Selected by > architectures that do not support these instrumentation types. > > +config ARCH_DEFER_KASAN > + bool > + help > + Architectures should select this if they need to defer KASAN > + initialization until shadow memory is properly set up. This > + enables runtime control via static keys. Otherwise, KASAN uses > + compile-time constants for better performance. > + > config CC_HAS_KASAN_GENERIC > def_bool $(cc-option, -fsanitize=kernel-address) > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c > index 9142964ab9c..d9d389870a2 100644 > --- a/mm/kasan/common.c > +++ b/mm/kasan/common.c > @@ -32,6 +32,15 @@ > #include "kasan.h" > #include "../slab.h" > > +#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS) > +/* > + * Definition of the unified static key declared in kasan-enabled.h. > + * This provides consistent runtime enable/disable across KASAN modes. > + */ > +DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); > +EXPORT_SYMBOL(kasan_flag_enabled); Shouldn't new exports be GPL ? > +#endif > + > struct slab *kasan_addr_to_slab(const void *addr) > { > if (virt_addr_valid(addr)) > @@ -246,7 +255,7 @@ static inline void poison_slab_object(struct kmem_cache *cache, void *object, > bool __kasan_slab_pre_free(struct kmem_cache *cache, void *object, > unsigned long ip) > { > - if (!kasan_arch_is_ready() || is_kfence_address(object)) > + if (is_kfence_address(object)) Here and below, no need to replace kasan_arch_is_ready() by kasan_enabled() ? > return false; > return check_slab_allocation(cache, object, ip); > } > @@ -254,7 +263,7 @@ bool __kasan_slab_pre_free(struct kmem_cache *cache, void *object, > bool __kasan_slab_free(struct kmem_cache *cache, void *object, bool init, > bool still_accessible) > { > - if (!kasan_arch_is_ready() || is_kfence_address(object)) > + if (is_kfence_address(object)) > return false; > > /* > @@ -293,7 +302,7 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *object, bool init, > > static inline bool check_page_allocation(void *ptr, unsigned long ip) > { > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return false; > > if (ptr != page_address(virt_to_head_page(ptr))) { > @@ -522,7 +531,7 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned long ip) > return true; > } > > - if (is_kfence_address(ptr) || !kasan_arch_is_ready()) > + if (is_kfence_address(ptr)) > return true; > > slab = folio_slab(folio); > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c > index d54e89f8c3e..b413c46b3e0 100644 > --- a/mm/kasan/generic.c > +++ b/mm/kasan/generic.c > @@ -36,6 +36,17 @@ > #include "kasan.h" > #include "../slab.h" > > +/* > + * Initialize Generic KASAN and enable runtime checks. > + * This should be called from arch kasan_init() once shadow memory is ready. > + */ > +void __init kasan_init_generic(void) > +{ > + kasan_enable(); > + > + pr_info("KernelAddressSanitizer initialized (generic)\n"); > +} > + > /* > * All functions below always inlined so compiler could > * perform better optimizations in each of __asan_loadX/__assn_storeX > @@ -165,7 +176,7 @@ static __always_inline bool check_region_inline(const void *addr, > size_t size, bool write, > unsigned long ret_ip) > { > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return true; > > if (unlikely(size == 0)) > @@ -193,7 +204,7 @@ bool kasan_byte_accessible(const void *addr) > { > s8 shadow_byte; > > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return true; > > shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(addr)); > @@ -495,7 +506,7 @@ static void release_alloc_meta(struct kasan_alloc_meta *meta) > > static void release_free_meta(const void *object, struct kasan_free_meta *meta) > { > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return; > > /* Check if free meta is valid. */ > @@ -562,7 +573,7 @@ void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags) > kasan_save_track(&alloc_meta->alloc_track, flags); > } > > -void kasan_save_free_info(struct kmem_cache *cache, void *object) > +void __kasan_save_free_info(struct kmem_cache *cache, void *object) > { > struct kasan_free_meta *free_meta; > > diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c > index 9a6927394b5..c8289a3feab 100644 > --- a/mm/kasan/hw_tags.c > +++ b/mm/kasan/hw_tags.c > @@ -45,13 +45,6 @@ static enum kasan_arg kasan_arg __ro_after_init; > static enum kasan_arg_mode kasan_arg_mode __ro_after_init; > static enum kasan_arg_vmalloc kasan_arg_vmalloc __initdata; > > -/* > - * Whether KASAN is enabled at all. > - * The value remains false until KASAN is initialized by kasan_init_hw_tags(). > - */ > -DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); > -EXPORT_SYMBOL(kasan_flag_enabled); > - > /* > * Whether the selected mode is synchronous, asynchronous, or asymmetric. > * Defaults to KASAN_MODE_SYNC. > @@ -260,7 +253,7 @@ void __init kasan_init_hw_tags(void) > kasan_init_tags(); > > /* KASAN is now initialized, enable it. */ > - static_branch_enable(&kasan_flag_enabled); > + kasan_enable(); > > pr_info("KernelAddressSanitizer initialized (hw-tags, mode=%s, vmalloc=%s, stacktrace=%s)\n", > kasan_mode_info(), > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h > index 129178be5e6..8a9d8a6ea71 100644 > --- a/mm/kasan/kasan.h > +++ b/mm/kasan/kasan.h > @@ -398,7 +398,13 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags, depot_flags_t depot_flags); > void kasan_set_track(struct kasan_track *track, depot_stack_handle_t stack); > void kasan_save_track(struct kasan_track *track, gfp_t flags); > void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags); > -void kasan_save_free_info(struct kmem_cache *cache, void *object); > + > +void __kasan_save_free_info(struct kmem_cache *cache, void *object); > +static inline void kasan_save_free_info(struct kmem_cache *cache, void *object) > +{ > + if (kasan_enabled()) > + __kasan_save_free_info(cache, object); > +} > > #ifdef CONFIG_KASAN_GENERIC > bool kasan_quarantine_put(struct kmem_cache *cache, void *object); > diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c > index d2c70cd2afb..2e126cb21b6 100644 > --- a/mm/kasan/shadow.c > +++ b/mm/kasan/shadow.c > @@ -125,7 +125,7 @@ void kasan_poison(const void *addr, size_t size, u8 value, bool init) > { > void *shadow_start, *shadow_end; > > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return; > > /* > @@ -150,7 +150,7 @@ EXPORT_SYMBOL_GPL(kasan_poison); > #ifdef CONFIG_KASAN_GENERIC > void kasan_poison_last_granule(const void *addr, size_t size) > { > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return; > > if (size & KASAN_GRANULE_MASK) { > @@ -390,7 +390,7 @@ int kasan_populate_vmalloc(unsigned long addr, unsigned long size) > unsigned long shadow_start, shadow_end; > int ret; > > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return 0; > > if (!is_vmalloc_or_module_addr((void *)addr)) > @@ -560,7 +560,7 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end, > unsigned long region_start, region_end; > unsigned long size; > > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return; > > region_start = ALIGN(start, KASAN_MEMORY_PER_SHADOW_PAGE); > @@ -611,7 +611,7 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size, > * with setting memory tags, so the KASAN_VMALLOC_INIT flag is ignored. > */ > > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return (void *)start; > > if (!is_vmalloc_or_module_addr(start)) > @@ -636,7 +636,7 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size, > */ > void __kasan_poison_vmalloc(const void *start, unsigned long size) > { > - if (!kasan_arch_is_ready()) > + if (!kasan_enabled()) > return; > > if (!is_vmalloc_or_module_addr(start)) > diff --git a/mm/kasan/sw_tags.c b/mm/kasan/sw_tags.c > index b9382b5b6a3..c75741a7460 100644 > --- a/mm/kasan/sw_tags.c > +++ b/mm/kasan/sw_tags.c > @@ -44,6 +44,7 @@ void __init kasan_init_sw_tags(void) > per_cpu(prng_state, cpu) = (u32)get_cycles(); > > kasan_init_tags(); > + kasan_enable(); > > pr_info("KernelAddressSanitizer initialized (sw-tags, stacktrace=%s)\n", > str_on_off(kasan_stack_collection_enabled())); > diff --git a/mm/kasan/tags.c b/mm/kasan/tags.c > index d65d48b85f9..b9f31293622 100644 > --- a/mm/kasan/tags.c > +++ b/mm/kasan/tags.c > @@ -142,7 +142,7 @@ void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags) > save_stack_info(cache, object, flags, false); > } > > -void kasan_save_free_info(struct kmem_cache *cache, void *object) > +void __kasan_save_free_info(struct kmem_cache *cache, void *object) > { > save_stack_info(cache, object, 0, true); > } ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes 2025-08-08 5:03 ` Christophe Leroy @ 2025-08-08 7:26 ` Sabyrzhan Tasbolatov 2025-08-08 7:33 ` Christophe Leroy 2025-08-08 15:33 ` Sabyrzhan Tasbolatov 1 sibling, 1 reply; 13+ messages in thread From: Sabyrzhan Tasbolatov @ 2025-08-08 7:26 UTC (permalink / raw) To: Christophe Leroy, ryabinin.a.a Cc: bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov, alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm On Fri, Aug 8, 2025 at 10:03 AM Christophe Leroy <christophe.leroy@csgroup.eu> wrote: > > > > Le 07/08/2025 à 21:40, Sabyrzhan Tasbolatov a écrit : > > Introduce CONFIG_ARCH_DEFER_KASAN to identify architectures [1] that need > > to defer KASAN initialization until shadow memory is properly set up, > > and unify the static key infrastructure across all KASAN modes. > > That probably desserves more details, maybe copy in informations from > the top of cover letter. > > I think there should also be some exeplanations about > kasan_arch_is_ready() becoming kasan_enabled(), and also why > kasan_arch_is_ready() completely disappear from mm/kasan/common.c > without being replaced by kasan_enabled(). I will try to explain in details in this git commit message. Will copy this part from my cover letter as well. Hopefully, this below is concise yet informative description: The core issue is that different architectures have inconsistent approaches to KASAN readiness tracking: - PowerPC, LoongArch, and UML arch, each implement own kasan_arch_is_ready() - Only HW_TAGS mode had a unified static key (kasan_flag_enabled) - Generic and SW_TAGS modes relied on arch-specific solutions or always-on behavior This patch addresses the fragmentation in KASAN initialization across architectures by introducing a unified approach that eliminates duplicate static keys and arch-specific kasan_arch_is_ready() implementations. Let's replace kasan_arch_is_ready() with existing kasan_enabled() check, which examines the static key being enabled if arch selects ARCH_DEFER_KASAN or has HW_TAGS mode support. For other arch, kasan_enabled() checks the enablement during compile time. Now KASAN users can use a single kasan_enabled() check everywhere. > > > > > [1] PowerPC, UML, LoongArch selects ARCH_DEFER_KASAN. > > > > Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049 > > Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> > > --- > > Changes in v5: > > - Unified patches where arch (powerpc, UML, loongarch) selects > > ARCH_DEFER_KASAN in the first patch not to break > > bisectability > > - Removed kasan_arch_is_ready completely as there is no user > > - Removed __wrappers in v4, left only those where it's necessary > > due to different implementations > > > > Changes in v4: > > - Fixed HW_TAGS static key functionality (was broken in v3) > > - Merged configuration and implementation for atomicity > > --- > > arch/loongarch/Kconfig | 1 + > > arch/loongarch/include/asm/kasan.h | 7 ------ > > arch/loongarch/mm/kasan_init.c | 8 +++---- > > arch/powerpc/Kconfig | 1 + > > arch/powerpc/include/asm/kasan.h | 12 ---------- > > arch/powerpc/mm/kasan/init_32.c | 2 +- > > arch/powerpc/mm/kasan/init_book3e_64.c | 2 +- > > arch/powerpc/mm/kasan/init_book3s_64.c | 6 +---- > > arch/um/Kconfig | 1 + > > arch/um/include/asm/kasan.h | 5 ++-- > > arch/um/kernel/mem.c | 10 ++++++-- > > include/linux/kasan-enabled.h | 32 ++++++++++++++++++-------- > > include/linux/kasan.h | 6 +++++ > > lib/Kconfig.kasan | 8 +++++++ > > mm/kasan/common.c | 17 ++++++++++---- > > mm/kasan/generic.c | 19 +++++++++++---- > > mm/kasan/hw_tags.c | 9 +------- > > mm/kasan/kasan.h | 8 ++++++- > > mm/kasan/shadow.c | 12 +++++----- > > mm/kasan/sw_tags.c | 1 + > > mm/kasan/tags.c | 2 +- > > 21 files changed, 100 insertions(+), 69 deletions(-) > > > > diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig > > index f0abc38c40a..cd64b2bc12d 100644 > > --- a/arch/loongarch/Kconfig > > +++ b/arch/loongarch/Kconfig > > @@ -9,6 +9,7 @@ config LOONGARCH > > select ACPI_PPTT if ACPI > > select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI > > select ARCH_BINFMT_ELF_STATE > > + select ARCH_DEFER_KASAN if KASAN > > Instead of adding 'if KASAN' in all users, you could do in two steps: > > Add a symbol ARCH_NEEDS_DEFER_KASAN. > > +config ARCH_NEEDS_DEFER_KASAN > + bool > > And then: > > +config ARCH_DEFER_KASAN > + def_bool > + depends on KASAN > + depends on ARCH_DEFER_KASAN > + help > + Architectures should select this if they need to defer KASAN > + initialization until shadow memory is properly set up. This > + enables runtime control via static keys. Otherwise, KASAN uses > + compile-time constants for better performance. > Thanks, will do it in v6 (during weekends though as I'm away from my PC) unless anyone has objections to it. FYI, I see that Andrew added yesterday v5 to mm-new: https://lore.kernel.org/all/20250807222945.61E0AC4CEEB@smtp.kernel.org/ https://lore.kernel.org/all/20250807222941.88655C4CEEB@smtp.kernel.org/ Andrey Ryabinin, could you please also review if all comments are addressed in v5? So I could work on anything new in v6 during these weekends. > > > > select ARCH_DISABLE_KASAN_INLINE > > select ARCH_ENABLE_MEMORY_HOTPLUG > > select ARCH_ENABLE_MEMORY_HOTREMOVE > > diff --git a/arch/loongarch/include/asm/kasan.h b/arch/loongarch/include/asm/kasan.h > > index 62f139a9c87..0e50e5b5e05 100644 > > --- a/arch/loongarch/include/asm/kasan.h > > +++ b/arch/loongarch/include/asm/kasan.h > > @@ -66,7 +66,6 @@ > > #define XKPRANGE_WC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_WC_KASAN_OFFSET) > > #define XKVRANGE_VC_SHADOW_OFFSET (KASAN_SHADOW_START + XKVRANGE_VC_KASAN_OFFSET) > > > > -extern bool kasan_early_stage; > > extern unsigned char kasan_early_shadow_page[PAGE_SIZE]; > > > > #define kasan_mem_to_shadow kasan_mem_to_shadow > > @@ -75,12 +74,6 @@ void *kasan_mem_to_shadow(const void *addr); > > #define kasan_shadow_to_mem kasan_shadow_to_mem > > const void *kasan_shadow_to_mem(const void *shadow_addr); > > > > -#define kasan_arch_is_ready kasan_arch_is_ready > > -static __always_inline bool kasan_arch_is_ready(void) > > -{ > > - return !kasan_early_stage; > > -} > > - > > #define addr_has_metadata addr_has_metadata > > static __always_inline bool addr_has_metadata(const void *addr) > > { > > diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c > > index d2681272d8f..170da98ad4f 100644 > > --- a/arch/loongarch/mm/kasan_init.c > > +++ b/arch/loongarch/mm/kasan_init.c > > @@ -40,11 +40,9 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); > > #define __pte_none(early, pte) (early ? pte_none(pte) : \ > > ((pte_val(pte) & _PFN_MASK) == (unsigned long)__pa(kasan_early_shadow_page))) > > > > -bool kasan_early_stage = true; > > - > > void *kasan_mem_to_shadow(const void *addr) > > { > > - if (!kasan_arch_is_ready()) { > > + if (!kasan_enabled()) { > > return (void *)(kasan_early_shadow_page); > > } else { > > unsigned long maddr = (unsigned long)addr; > > @@ -298,7 +296,8 @@ void __init kasan_init(void) > > kasan_populate_early_shadow(kasan_mem_to_shadow((void *)VMALLOC_START), > > kasan_mem_to_shadow((void *)KFENCE_AREA_END)); > > > > - kasan_early_stage = false; > > + /* Enable KASAN here before kasan_mem_to_shadow(). */ > > + kasan_init_generic(); > > > > /* Populate the linear mapping */ > > for_each_mem_range(i, &pa_start, &pa_end) { > > @@ -329,5 +328,4 @@ void __init kasan_init(void) > > > > /* At this point kasan is fully initialized. Enable error messages */ > > init_task.kasan_depth = 0; > > - pr_info("KernelAddressSanitizer initialized.\n"); > > } > > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > > index 93402a1d9c9..a324dcdb8eb 100644 > > --- a/arch/powerpc/Kconfig > > +++ b/arch/powerpc/Kconfig > > @@ -122,6 +122,7 @@ config PPC > > # Please keep this list sorted alphabetically. > > # > > select ARCH_32BIT_OFF_T if PPC32 > > + select ARCH_DEFER_KASAN if KASAN && PPC_RADIX_MMU > > select ARCH_DISABLE_KASAN_INLINE if PPC_RADIX_MMU > > select ARCH_DMA_DEFAULT_COHERENT if !NOT_COHERENT_CACHE > > select ARCH_ENABLE_MEMORY_HOTPLUG > > diff --git a/arch/powerpc/include/asm/kasan.h b/arch/powerpc/include/asm/kasan.h > > index b5bbb94c51f..957a57c1db5 100644 > > --- a/arch/powerpc/include/asm/kasan.h > > +++ b/arch/powerpc/include/asm/kasan.h > > @@ -53,18 +53,6 @@ > > #endif > > > > #ifdef CONFIG_KASAN > > -#ifdef CONFIG_PPC_BOOK3S_64 > > -DECLARE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); > > - > > -static __always_inline bool kasan_arch_is_ready(void) > > -{ > > - if (static_branch_likely(&powerpc_kasan_enabled_key)) > > - return true; > > - return false; > > -} > > - > > -#define kasan_arch_is_ready kasan_arch_is_ready > > -#endif > > > > void kasan_early_init(void); > > void kasan_mmu_init(void); > > diff --git a/arch/powerpc/mm/kasan/init_32.c b/arch/powerpc/mm/kasan/init_32.c > > index 03666d790a5..1d083597464 100644 > > --- a/arch/powerpc/mm/kasan/init_32.c > > +++ b/arch/powerpc/mm/kasan/init_32.c > > @@ -165,7 +165,7 @@ void __init kasan_init(void) > > > > /* At this point kasan is fully initialized. Enable error messages */ > > init_task.kasan_depth = 0; > > - pr_info("KASAN init done\n"); > > + kasan_init_generic(); > > } > > > > void __init kasan_late_init(void) > > diff --git a/arch/powerpc/mm/kasan/init_book3e_64.c b/arch/powerpc/mm/kasan/init_book3e_64.c > > index 60c78aac0f6..0d3a73d6d4b 100644 > > --- a/arch/powerpc/mm/kasan/init_book3e_64.c > > +++ b/arch/powerpc/mm/kasan/init_book3e_64.c > > @@ -127,7 +127,7 @@ void __init kasan_init(void) > > > > /* Enable error messages */ > > init_task.kasan_depth = 0; > > - pr_info("KASAN init done\n"); > > + kasan_init_generic(); > > } > > > > void __init kasan_late_init(void) { } > > diff --git a/arch/powerpc/mm/kasan/init_book3s_64.c b/arch/powerpc/mm/kasan/init_book3s_64.c > > index 7d959544c07..dcafa641804 100644 > > --- a/arch/powerpc/mm/kasan/init_book3s_64.c > > +++ b/arch/powerpc/mm/kasan/init_book3s_64.c > > @@ -19,8 +19,6 @@ > > #include <linux/memblock.h> > > #include <asm/pgalloc.h> > > > > -DEFINE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); > > - > > static void __init kasan_init_phys_region(void *start, void *end) > > { > > unsigned long k_start, k_end, k_cur; > > @@ -92,11 +90,9 @@ void __init kasan_init(void) > > */ > > memset(kasan_early_shadow_page, 0, PAGE_SIZE); > > > > - static_branch_inc(&powerpc_kasan_enabled_key); > > - > > /* Enable error messages */ > > init_task.kasan_depth = 0; > > - pr_info("KASAN init done\n"); > > + kasan_init_generic(); > > } > > > > void __init kasan_early_init(void) { } > > diff --git a/arch/um/Kconfig b/arch/um/Kconfig > > index 9083bfdb773..a12cc072ab1 100644 > > --- a/arch/um/Kconfig > > +++ b/arch/um/Kconfig > > @@ -5,6 +5,7 @@ menu "UML-specific options" > > config UML > > bool > > default y > > + select ARCH_DEFER_KASAN if STATIC_LINK > > No need to also verify KASAN here like powerpc and loongarch ? Sorry, I didn't quite understand the question. I've verified powerpc with KASAN enabled which selects KASAN_OUTLINE, as far as I remember, and GENERIC mode. I haven't tested LoongArch booting via QEMU, only tested compilation. I guess, I need to test the boot, will try to learn how to do it for qemu-system-loongarch64. Would be helpful LoongArch devs in CC can assist as well. STATIC_LINK is defined for UML only. > > > select ARCH_WANTS_DYNAMIC_TASK_STRUCT > > select ARCH_HAS_CACHE_LINE_SIZE > > select ARCH_HAS_CPU_FINALIZE_INIT > > diff --git a/arch/um/include/asm/kasan.h b/arch/um/include/asm/kasan.h > > index f97bb1f7b85..b54a4e937fd 100644 > > --- a/arch/um/include/asm/kasan.h > > +++ b/arch/um/include/asm/kasan.h > > @@ -24,10 +24,9 @@ > > > > #ifdef CONFIG_KASAN > > void kasan_init(void); > > -extern int kasan_um_is_ready; > > > > -#ifdef CONFIG_STATIC_LINK > > -#define kasan_arch_is_ready() (kasan_um_is_ready) > > +#if defined(CONFIG_STATIC_LINK) && defined(CONFIG_KASAN_INLINE) > > +#error UML does not work in KASAN_INLINE mode with STATIC_LINK enabled! > > #endif > > #else > > static inline void kasan_init(void) { } > > diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c > > index 76bec7de81b..261fdcd21be 100644 > > --- a/arch/um/kernel/mem.c > > +++ b/arch/um/kernel/mem.c > > @@ -21,9 +21,9 @@ > > #include <os.h> > > #include <um_malloc.h> > > #include <linux/sched/task.h> > > +#include <linux/kasan.h> > > > > #ifdef CONFIG_KASAN > > -int kasan_um_is_ready; > > void kasan_init(void) > > { > > /* > > @@ -32,7 +32,10 @@ void kasan_init(void) > > */ > > kasan_map_memory((void *)KASAN_SHADOW_START, KASAN_SHADOW_SIZE); > > init_task.kasan_depth = 0; > > - kasan_um_is_ready = true; > > + /* Since kasan_init() is called before main(), > > + * KASAN is initialized but the enablement is deferred after > > + * jump_label_init(). See arch_mm_preinit(). > > + */ > > Format standard is different outside network, see: > https://docs.kernel.org/process/coding-style.html#commenting Thanks! Will do in v6. > > > } > > > > static void (*kasan_init_ptr)(void) > > @@ -58,6 +61,9 @@ static unsigned long brk_end; > > > > void __init arch_mm_preinit(void) > > { > > + /* Safe to call after jump_label_init(). Enables KASAN. */ > > + kasan_init_generic(); > > + > > /* clear the zero-page */ > > memset(empty_zero_page, 0, PAGE_SIZE); > > > > diff --git a/include/linux/kasan-enabled.h b/include/linux/kasan-enabled.h > > index 6f612d69ea0..9eca967d852 100644 > > --- a/include/linux/kasan-enabled.h > > +++ b/include/linux/kasan-enabled.h > > @@ -4,32 +4,46 @@ > > > > #include <linux/static_key.h> > > > > -#ifdef CONFIG_KASAN_HW_TAGS > > - > > +#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS) > > +/* > > + * Global runtime flag for KASAN modes that need runtime control. > > + * Used by ARCH_DEFER_KASAN architectures and HW_TAGS mode. > > + */ > > DECLARE_STATIC_KEY_FALSE(kasan_flag_enabled); > > > > +/* > > + * Runtime control for shadow memory initialization or HW_TAGS mode. > > + * Uses static key for architectures that need deferred KASAN or HW_TAGS. > > + */ > > static __always_inline bool kasan_enabled(void) > > { > > return static_branch_likely(&kasan_flag_enabled); > > } > > > > -static inline bool kasan_hw_tags_enabled(void) > > +static inline void kasan_enable(void) > > { > > - return kasan_enabled(); > > + static_branch_enable(&kasan_flag_enabled); > > } > > - > > -#else /* CONFIG_KASAN_HW_TAGS */ > > - > > -static inline bool kasan_enabled(void) > > +#else > > +/* For architectures that can enable KASAN early, use compile-time check. */ > > +static __always_inline bool kasan_enabled(void) > > { > > return IS_ENABLED(CONFIG_KASAN); > > } > > > > +static inline void kasan_enable(void) {} > > +#endif /* CONFIG_ARCH_DEFER_KASAN || CONFIG_KASAN_HW_TAGS */ > > + > > +#ifdef CONFIG_KASAN_HW_TAGS > > +static inline bool kasan_hw_tags_enabled(void) > > +{ > > + return kasan_enabled(); > > +} > > +#else > > static inline bool kasan_hw_tags_enabled(void) > > { > > return false; > > } > > - > > #endif /* CONFIG_KASAN_HW_TAGS */ > > > > #endif /* LINUX_KASAN_ENABLED_H */ > > diff --git a/include/linux/kasan.h b/include/linux/kasan.h > > index 890011071f2..51a8293d1af 100644 > > --- a/include/linux/kasan.h > > +++ b/include/linux/kasan.h > > @@ -543,6 +543,12 @@ void kasan_report_async(void); > > > > #endif /* CONFIG_KASAN_HW_TAGS */ > > > > +#ifdef CONFIG_KASAN_GENERIC > > +void __init kasan_init_generic(void); > > +#else > > +static inline void kasan_init_generic(void) { } > > +#endif > > + > > #ifdef CONFIG_KASAN_SW_TAGS > > void __init kasan_init_sw_tags(void); > > #else > > diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan > > index f82889a830f..38456560c85 100644 > > --- a/lib/Kconfig.kasan > > +++ b/lib/Kconfig.kasan > > @@ -19,6 +19,14 @@ config ARCH_DISABLE_KASAN_INLINE > > Disables both inline and stack instrumentation. Selected by > > architectures that do not support these instrumentation types. > > > > +config ARCH_DEFER_KASAN > > + bool > > + help > > + Architectures should select this if they need to defer KASAN > > + initialization until shadow memory is properly set up. This > > + enables runtime control via static keys. Otherwise, KASAN uses > > + compile-time constants for better performance. > > + > > config CC_HAS_KASAN_GENERIC > > def_bool $(cc-option, -fsanitize=kernel-address) > > > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c > > index 9142964ab9c..d9d389870a2 100644 > > --- a/mm/kasan/common.c > > +++ b/mm/kasan/common.c > > @@ -32,6 +32,15 @@ > > #include "kasan.h" > > #include "../slab.h" > > > > +#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS) > > +/* > > + * Definition of the unified static key declared in kasan-enabled.h. > > + * This provides consistent runtime enable/disable across KASAN modes. > > + */ > > +DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); > > +EXPORT_SYMBOL(kasan_flag_enabled); > > Shouldn't new exports be GPL ? Hmm, I did it as it's currently EXPORT_SYMBOL for HW_TAGS https://elixir.bootlin.com/linux/v6.16/source/mm/kasan/hw_tags.c#L53 but I see that in the same HW_TAGS file we have EXPORT_SYMBOL_GPL(kasan_flag_vmalloc); So I guess, we should also export kasan_flag_enabled as EXPORT_SYMBOL_GPL. Will do in v6. > > > +#endif > > + > > struct slab *kasan_addr_to_slab(const void *addr) > > { > > if (virt_addr_valid(addr)) > > @@ -246,7 +255,7 @@ static inline void poison_slab_object(struct kmem_cache *cache, void *object, > > bool __kasan_slab_pre_free(struct kmem_cache *cache, void *object, > > unsigned long ip) > > { > > - if (!kasan_arch_is_ready() || is_kfence_address(object)) > > + if (is_kfence_address(object)) > > Here and below, no need to replace kasan_arch_is_ready() by > kasan_enabled() ? Both functions have __wrappers in include/linux/kasan.h [1], where there's already kasan_enabled() check. Since we've replaced kasan_arch_is_ready() with kasan_enabled(), these checks are not needed here. [1] https://elixir.bootlin.com/linux/v6.16/source/include/linux/kasan.h#L197 > > > return false; > > return check_slab_allocation(cache, object, ip); > > } > > @@ -254,7 +263,7 @@ bool __kasan_slab_pre_free(struct kmem_cache *cache, void *object, > > bool __kasan_slab_free(struct kmem_cache *cache, void *object, bool init, > > bool still_accessible) > > { > > - if (!kasan_arch_is_ready() || is_kfence_address(object)) > > + if (is_kfence_address(object)) > > return false; > > > > /* > > @@ -293,7 +302,7 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *object, bool init, > > > > static inline bool check_page_allocation(void *ptr, unsigned long ip) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return false; > > > > if (ptr != page_address(virt_to_head_page(ptr))) { > > @@ -522,7 +531,7 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned long ip) > > return true; > > } > > > > - if (is_kfence_address(ptr) || !kasan_arch_is_ready()) > > + if (is_kfence_address(ptr)) > > return true; > > > > slab = folio_slab(folio); > > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c > > index d54e89f8c3e..b413c46b3e0 100644 > > --- a/mm/kasan/generic.c > > +++ b/mm/kasan/generic.c > > @@ -36,6 +36,17 @@ > > #include "kasan.h" > > #include "../slab.h" > > > > +/* > > + * Initialize Generic KASAN and enable runtime checks. > > + * This should be called from arch kasan_init() once shadow memory is ready. > > + */ > > +void __init kasan_init_generic(void) > > +{ > > + kasan_enable(); > > + > > + pr_info("KernelAddressSanitizer initialized (generic)\n"); > > +} > > + > > /* > > * All functions below always inlined so compiler could > > * perform better optimizations in each of __asan_loadX/__assn_storeX > > @@ -165,7 +176,7 @@ static __always_inline bool check_region_inline(const void *addr, > > size_t size, bool write, > > unsigned long ret_ip) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return true; > > > > if (unlikely(size == 0)) > > @@ -193,7 +204,7 @@ bool kasan_byte_accessible(const void *addr) > > { > > s8 shadow_byte; > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return true; > > > > shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(addr)); > > @@ -495,7 +506,7 @@ static void release_alloc_meta(struct kasan_alloc_meta *meta) > > > > static void release_free_meta(const void *object, struct kasan_free_meta *meta) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > /* Check if free meta is valid. */ > > @@ -562,7 +573,7 @@ void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags) > > kasan_save_track(&alloc_meta->alloc_track, flags); > > } > > > > -void kasan_save_free_info(struct kmem_cache *cache, void *object) > > +void __kasan_save_free_info(struct kmem_cache *cache, void *object) > > { > > struct kasan_free_meta *free_meta; > > > > diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c > > index 9a6927394b5..c8289a3feab 100644 > > --- a/mm/kasan/hw_tags.c > > +++ b/mm/kasan/hw_tags.c > > @@ -45,13 +45,6 @@ static enum kasan_arg kasan_arg __ro_after_init; > > static enum kasan_arg_mode kasan_arg_mode __ro_after_init; > > static enum kasan_arg_vmalloc kasan_arg_vmalloc __initdata; > > > > -/* > > - * Whether KASAN is enabled at all. > > - * The value remains false until KASAN is initialized by kasan_init_hw_tags(). > > - */ > > -DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); > > -EXPORT_SYMBOL(kasan_flag_enabled); > > - > > /* > > * Whether the selected mode is synchronous, asynchronous, or asymmetric. > > * Defaults to KASAN_MODE_SYNC. > > @@ -260,7 +253,7 @@ void __init kasan_init_hw_tags(void) > > kasan_init_tags(); > > > > /* KASAN is now initialized, enable it. */ > > - static_branch_enable(&kasan_flag_enabled); > > + kasan_enable(); > > > > pr_info("KernelAddressSanitizer initialized (hw-tags, mode=%s, vmalloc=%s, stacktrace=%s)\n", > > kasan_mode_info(), > > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h > > index 129178be5e6..8a9d8a6ea71 100644 > > --- a/mm/kasan/kasan.h > > +++ b/mm/kasan/kasan.h > > @@ -398,7 +398,13 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags, depot_flags_t depot_flags); > > void kasan_set_track(struct kasan_track *track, depot_stack_handle_t stack); > > void kasan_save_track(struct kasan_track *track, gfp_t flags); > > void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags); > > -void kasan_save_free_info(struct kmem_cache *cache, void *object); > > + > > +void __kasan_save_free_info(struct kmem_cache *cache, void *object); > > +static inline void kasan_save_free_info(struct kmem_cache *cache, void *object) > > +{ > > + if (kasan_enabled()) > > + __kasan_save_free_info(cache, object); > > +} > > > > #ifdef CONFIG_KASAN_GENERIC > > bool kasan_quarantine_put(struct kmem_cache *cache, void *object); > > diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c > > index d2c70cd2afb..2e126cb21b6 100644 > > --- a/mm/kasan/shadow.c > > +++ b/mm/kasan/shadow.c > > @@ -125,7 +125,7 @@ void kasan_poison(const void *addr, size_t size, u8 value, bool init) > > { > > void *shadow_start, *shadow_end; > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > /* > > @@ -150,7 +150,7 @@ EXPORT_SYMBOL_GPL(kasan_poison); > > #ifdef CONFIG_KASAN_GENERIC > > void kasan_poison_last_granule(const void *addr, size_t size) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > if (size & KASAN_GRANULE_MASK) { > > @@ -390,7 +390,7 @@ int kasan_populate_vmalloc(unsigned long addr, unsigned long size) > > unsigned long shadow_start, shadow_end; > > int ret; > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return 0; > > > > if (!is_vmalloc_or_module_addr((void *)addr)) > > @@ -560,7 +560,7 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end, > > unsigned long region_start, region_end; > > unsigned long size; > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > region_start = ALIGN(start, KASAN_MEMORY_PER_SHADOW_PAGE); > > @@ -611,7 +611,7 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size, > > * with setting memory tags, so the KASAN_VMALLOC_INIT flag is ignored. > > */ > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return (void *)start; > > > > if (!is_vmalloc_or_module_addr(start)) > > @@ -636,7 +636,7 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size, > > */ > > void __kasan_poison_vmalloc(const void *start, unsigned long size) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > if (!is_vmalloc_or_module_addr(start)) > > diff --git a/mm/kasan/sw_tags.c b/mm/kasan/sw_tags.c > > index b9382b5b6a3..c75741a7460 100644 > > --- a/mm/kasan/sw_tags.c > > +++ b/mm/kasan/sw_tags.c > > @@ -44,6 +44,7 @@ void __init kasan_init_sw_tags(void) > > per_cpu(prng_state, cpu) = (u32)get_cycles(); > > > > kasan_init_tags(); > > + kasan_enable(); > > > > pr_info("KernelAddressSanitizer initialized (sw-tags, stacktrace=%s)\n", > > str_on_off(kasan_stack_collection_enabled())); > > diff --git a/mm/kasan/tags.c b/mm/kasan/tags.c > > index d65d48b85f9..b9f31293622 100644 > > --- a/mm/kasan/tags.c > > +++ b/mm/kasan/tags.c > > @@ -142,7 +142,7 @@ void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags) > > save_stack_info(cache, object, flags, false); > > } > > > > -void kasan_save_free_info(struct kmem_cache *cache, void *object) > > +void __kasan_save_free_info(struct kmem_cache *cache, void *object) > > { > > save_stack_info(cache, object, 0, true); > > } > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes 2025-08-08 7:26 ` Sabyrzhan Tasbolatov @ 2025-08-08 7:33 ` Christophe Leroy 0 siblings, 0 replies; 13+ messages in thread From: Christophe Leroy @ 2025-08-08 7:33 UTC (permalink / raw) To: Sabyrzhan Tasbolatov, ryabinin.a.a Cc: bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov, alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm Le 08/08/2025 à 09:26, Sabyrzhan Tasbolatov a écrit : > On Fri, Aug 8, 2025 at 10:03 AM Christophe Leroy > <christophe.leroy@csgroup.eu> wrote: >>> diff --git a/arch/um/Kconfig b/arch/um/Kconfig >>> index 9083bfdb773..a12cc072ab1 100644 >>> --- a/arch/um/Kconfig >>> +++ b/arch/um/Kconfig >>> @@ -5,6 +5,7 @@ menu "UML-specific options" >>> config UML >>> bool >>> default y >>> + select ARCH_DEFER_KASAN if STATIC_LINK >> >> No need to also verify KASAN here like powerpc and loongarch ? > > Sorry, I didn't quite understand the question. > I've verified powerpc with KASAN enabled which selects KASAN_OUTLINE, > as far as I remember, and GENERIC mode. The question is whether: select ARCH_DEFER_KASAN if STATIC_LINK is enough ? Shouldn't it be: select ARCH_DEFER_KASAN if KASAN && STATIC_LINK Like for powerpc and loongarch ? > > I haven't tested LoongArch booting via QEMU, only tested compilation. > I guess, I need to test the boot, will try to learn how to do it for > qemu-system-loongarch64. Would be helpful LoongArch devs in CC can > assist as well. > > STATIC_LINK is defined for UML only. > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes 2025-08-08 5:03 ` Christophe Leroy 2025-08-08 7:26 ` Sabyrzhan Tasbolatov @ 2025-08-08 15:33 ` Sabyrzhan Tasbolatov 2025-08-08 17:03 ` Christophe Leroy 1 sibling, 1 reply; 13+ messages in thread From: Sabyrzhan Tasbolatov @ 2025-08-08 15:33 UTC (permalink / raw) To: Christophe Leroy Cc: ryabinin.a.a, bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov, alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm On Fri, Aug 8, 2025 at 10:03 AM Christophe Leroy <christophe.leroy@csgroup.eu> wrote: > > > > Le 07/08/2025 à 21:40, Sabyrzhan Tasbolatov a écrit : > > Introduce CONFIG_ARCH_DEFER_KASAN to identify architectures [1] that need > > to defer KASAN initialization until shadow memory is properly set up, > > and unify the static key infrastructure across all KASAN modes. > > That probably desserves more details, maybe copy in informations from > the top of cover letter. > > I think there should also be some exeplanations about > kasan_arch_is_ready() becoming kasan_enabled(), and also why > kasan_arch_is_ready() completely disappear from mm/kasan/common.c > without being replaced by kasan_enabled(). > > > > > [1] PowerPC, UML, LoongArch selects ARCH_DEFER_KASAN. > > > > Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049 > > Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> > > --- > > Changes in v5: > > - Unified patches where arch (powerpc, UML, loongarch) selects > > ARCH_DEFER_KASAN in the first patch not to break > > bisectability > > - Removed kasan_arch_is_ready completely as there is no user > > - Removed __wrappers in v4, left only those where it's necessary > > due to different implementations > > > > Changes in v4: > > - Fixed HW_TAGS static key functionality (was broken in v3) > > - Merged configuration and implementation for atomicity > > --- > > arch/loongarch/Kconfig | 1 + > > arch/loongarch/include/asm/kasan.h | 7 ------ > > arch/loongarch/mm/kasan_init.c | 8 +++---- > > arch/powerpc/Kconfig | 1 + > > arch/powerpc/include/asm/kasan.h | 12 ---------- > > arch/powerpc/mm/kasan/init_32.c | 2 +- > > arch/powerpc/mm/kasan/init_book3e_64.c | 2 +- > > arch/powerpc/mm/kasan/init_book3s_64.c | 6 +---- > > arch/um/Kconfig | 1 + > > arch/um/include/asm/kasan.h | 5 ++-- > > arch/um/kernel/mem.c | 10 ++++++-- > > include/linux/kasan-enabled.h | 32 ++++++++++++++++++-------- > > include/linux/kasan.h | 6 +++++ > > lib/Kconfig.kasan | 8 +++++++ > > mm/kasan/common.c | 17 ++++++++++---- > > mm/kasan/generic.c | 19 +++++++++++---- > > mm/kasan/hw_tags.c | 9 +------- > > mm/kasan/kasan.h | 8 ++++++- > > mm/kasan/shadow.c | 12 +++++----- > > mm/kasan/sw_tags.c | 1 + > > mm/kasan/tags.c | 2 +- > > 21 files changed, 100 insertions(+), 69 deletions(-) > > > > diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig > > index f0abc38c40a..cd64b2bc12d 100644 > > --- a/arch/loongarch/Kconfig > > +++ b/arch/loongarch/Kconfig > > @@ -9,6 +9,7 @@ config LOONGARCH > > select ACPI_PPTT if ACPI > > select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI > > select ARCH_BINFMT_ELF_STATE > > + select ARCH_DEFER_KASAN if KASAN > > Instead of adding 'if KASAN' in all users, you could do in two steps: > > Add a symbol ARCH_NEEDS_DEFER_KASAN. > > +config ARCH_NEEDS_DEFER_KASAN > + bool > > And then: > > +config ARCH_DEFER_KASAN > + def_bool > + depends on KASAN > + depends on ARCH_DEFER_KASAN > + help > + Architectures should select this if they need to defer KASAN > + initialization until shadow memory is properly set up. This > + enables runtime control via static keys. Otherwise, KASAN uses > + compile-time constants for better performance. > Actually, I don't see the benefits from this option. Sorry, have just revisited this again. With the new symbol, arch (PowerPC, UML, LoongArch) still needs select 2 options: select ARCH_NEEDS_DEFER_KASAN select ARCH_DEFER_KASAN and the oneline with `if` condition is cleaner. select ARCH_DEFER_KASAN if KASAN > > > > select ARCH_DISABLE_KASAN_INLINE > > select ARCH_ENABLE_MEMORY_HOTPLUG > > select ARCH_ENABLE_MEMORY_HOTREMOVE > > diff --git a/arch/loongarch/include/asm/kasan.h b/arch/loongarch/include/asm/kasan.h > > index 62f139a9c87..0e50e5b5e05 100644 > > --- a/arch/loongarch/include/asm/kasan.h > > +++ b/arch/loongarch/include/asm/kasan.h > > @@ -66,7 +66,6 @@ > > #define XKPRANGE_WC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_WC_KASAN_OFFSET) > > #define XKVRANGE_VC_SHADOW_OFFSET (KASAN_SHADOW_START + XKVRANGE_VC_KASAN_OFFSET) > > > > -extern bool kasan_early_stage; > > extern unsigned char kasan_early_shadow_page[PAGE_SIZE]; > > > > #define kasan_mem_to_shadow kasan_mem_to_shadow > > @@ -75,12 +74,6 @@ void *kasan_mem_to_shadow(const void *addr); > > #define kasan_shadow_to_mem kasan_shadow_to_mem > > const void *kasan_shadow_to_mem(const void *shadow_addr); > > > > -#define kasan_arch_is_ready kasan_arch_is_ready > > -static __always_inline bool kasan_arch_is_ready(void) > > -{ > > - return !kasan_early_stage; > > -} > > - > > #define addr_has_metadata addr_has_metadata > > static __always_inline bool addr_has_metadata(const void *addr) > > { > > diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c > > index d2681272d8f..170da98ad4f 100644 > > --- a/arch/loongarch/mm/kasan_init.c > > +++ b/arch/loongarch/mm/kasan_init.c > > @@ -40,11 +40,9 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); > > #define __pte_none(early, pte) (early ? pte_none(pte) : \ > > ((pte_val(pte) & _PFN_MASK) == (unsigned long)__pa(kasan_early_shadow_page))) > > > > -bool kasan_early_stage = true; > > - > > void *kasan_mem_to_shadow(const void *addr) > > { > > - if (!kasan_arch_is_ready()) { > > + if (!kasan_enabled()) { > > return (void *)(kasan_early_shadow_page); > > } else { > > unsigned long maddr = (unsigned long)addr; > > @@ -298,7 +296,8 @@ void __init kasan_init(void) > > kasan_populate_early_shadow(kasan_mem_to_shadow((void *)VMALLOC_START), > > kasan_mem_to_shadow((void *)KFENCE_AREA_END)); > > > > - kasan_early_stage = false; > > + /* Enable KASAN here before kasan_mem_to_shadow(). */ > > + kasan_init_generic(); > > > > /* Populate the linear mapping */ > > for_each_mem_range(i, &pa_start, &pa_end) { > > @@ -329,5 +328,4 @@ void __init kasan_init(void) > > > > /* At this point kasan is fully initialized. Enable error messages */ > > init_task.kasan_depth = 0; > > - pr_info("KernelAddressSanitizer initialized.\n"); > > } > > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > > index 93402a1d9c9..a324dcdb8eb 100644 > > --- a/arch/powerpc/Kconfig > > +++ b/arch/powerpc/Kconfig > > @@ -122,6 +122,7 @@ config PPC > > # Please keep this list sorted alphabetically. > > # > > select ARCH_32BIT_OFF_T if PPC32 > > + select ARCH_DEFER_KASAN if KASAN && PPC_RADIX_MMU > > select ARCH_DISABLE_KASAN_INLINE if PPC_RADIX_MMU > > select ARCH_DMA_DEFAULT_COHERENT if !NOT_COHERENT_CACHE > > select ARCH_ENABLE_MEMORY_HOTPLUG > > diff --git a/arch/powerpc/include/asm/kasan.h b/arch/powerpc/include/asm/kasan.h > > index b5bbb94c51f..957a57c1db5 100644 > > --- a/arch/powerpc/include/asm/kasan.h > > +++ b/arch/powerpc/include/asm/kasan.h > > @@ -53,18 +53,6 @@ > > #endif > > > > #ifdef CONFIG_KASAN > > -#ifdef CONFIG_PPC_BOOK3S_64 > > -DECLARE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); > > - > > -static __always_inline bool kasan_arch_is_ready(void) > > -{ > > - if (static_branch_likely(&powerpc_kasan_enabled_key)) > > - return true; > > - return false; > > -} > > - > > -#define kasan_arch_is_ready kasan_arch_is_ready > > -#endif > > > > void kasan_early_init(void); > > void kasan_mmu_init(void); > > diff --git a/arch/powerpc/mm/kasan/init_32.c b/arch/powerpc/mm/kasan/init_32.c > > index 03666d790a5..1d083597464 100644 > > --- a/arch/powerpc/mm/kasan/init_32.c > > +++ b/arch/powerpc/mm/kasan/init_32.c > > @@ -165,7 +165,7 @@ void __init kasan_init(void) > > > > /* At this point kasan is fully initialized. Enable error messages */ > > init_task.kasan_depth = 0; > > - pr_info("KASAN init done\n"); > > + kasan_init_generic(); > > } > > > > void __init kasan_late_init(void) > > diff --git a/arch/powerpc/mm/kasan/init_book3e_64.c b/arch/powerpc/mm/kasan/init_book3e_64.c > > index 60c78aac0f6..0d3a73d6d4b 100644 > > --- a/arch/powerpc/mm/kasan/init_book3e_64.c > > +++ b/arch/powerpc/mm/kasan/init_book3e_64.c > > @@ -127,7 +127,7 @@ void __init kasan_init(void) > > > > /* Enable error messages */ > > init_task.kasan_depth = 0; > > - pr_info("KASAN init done\n"); > > + kasan_init_generic(); > > } > > > > void __init kasan_late_init(void) { } > > diff --git a/arch/powerpc/mm/kasan/init_book3s_64.c b/arch/powerpc/mm/kasan/init_book3s_64.c > > index 7d959544c07..dcafa641804 100644 > > --- a/arch/powerpc/mm/kasan/init_book3s_64.c > > +++ b/arch/powerpc/mm/kasan/init_book3s_64.c > > @@ -19,8 +19,6 @@ > > #include <linux/memblock.h> > > #include <asm/pgalloc.h> > > > > -DEFINE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); > > - > > static void __init kasan_init_phys_region(void *start, void *end) > > { > > unsigned long k_start, k_end, k_cur; > > @@ -92,11 +90,9 @@ void __init kasan_init(void) > > */ > > memset(kasan_early_shadow_page, 0, PAGE_SIZE); > > > > - static_branch_inc(&powerpc_kasan_enabled_key); > > - > > /* Enable error messages */ > > init_task.kasan_depth = 0; > > - pr_info("KASAN init done\n"); > > + kasan_init_generic(); > > } > > > > void __init kasan_early_init(void) { } > > diff --git a/arch/um/Kconfig b/arch/um/Kconfig > > index 9083bfdb773..a12cc072ab1 100644 > > --- a/arch/um/Kconfig > > +++ b/arch/um/Kconfig > > @@ -5,6 +5,7 @@ menu "UML-specific options" > > config UML > > bool > > default y > > + select ARCH_DEFER_KASAN if STATIC_LINK > > No need to also verify KASAN here like powerpc and loongarch ? > > > select ARCH_WANTS_DYNAMIC_TASK_STRUCT > > select ARCH_HAS_CACHE_LINE_SIZE > > select ARCH_HAS_CPU_FINALIZE_INIT > > diff --git a/arch/um/include/asm/kasan.h b/arch/um/include/asm/kasan.h > > index f97bb1f7b85..b54a4e937fd 100644 > > --- a/arch/um/include/asm/kasan.h > > +++ b/arch/um/include/asm/kasan.h > > @@ -24,10 +24,9 @@ > > > > #ifdef CONFIG_KASAN > > void kasan_init(void); > > -extern int kasan_um_is_ready; > > > > -#ifdef CONFIG_STATIC_LINK > > -#define kasan_arch_is_ready() (kasan_um_is_ready) > > +#if defined(CONFIG_STATIC_LINK) && defined(CONFIG_KASAN_INLINE) > > +#error UML does not work in KASAN_INLINE mode with STATIC_LINK enabled! > > #endif > > #else > > static inline void kasan_init(void) { } > > diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c > > index 76bec7de81b..261fdcd21be 100644 > > --- a/arch/um/kernel/mem.c > > +++ b/arch/um/kernel/mem.c > > @@ -21,9 +21,9 @@ > > #include <os.h> > > #include <um_malloc.h> > > #include <linux/sched/task.h> > > +#include <linux/kasan.h> > > > > #ifdef CONFIG_KASAN > > -int kasan_um_is_ready; > > void kasan_init(void) > > { > > /* > > @@ -32,7 +32,10 @@ void kasan_init(void) > > */ > > kasan_map_memory((void *)KASAN_SHADOW_START, KASAN_SHADOW_SIZE); > > init_task.kasan_depth = 0; > > - kasan_um_is_ready = true; > > + /* Since kasan_init() is called before main(), > > + * KASAN is initialized but the enablement is deferred after > > + * jump_label_init(). See arch_mm_preinit(). > > + */ > > Format standard is different outside network, see: > https://docs.kernel.org/process/coding-style.html#commenting > > > } > > > > static void (*kasan_init_ptr)(void) > > @@ -58,6 +61,9 @@ static unsigned long brk_end; > > > > void __init arch_mm_preinit(void) > > { > > + /* Safe to call after jump_label_init(). Enables KASAN. */ > > + kasan_init_generic(); > > + > > /* clear the zero-page */ > > memset(empty_zero_page, 0, PAGE_SIZE); > > > > diff --git a/include/linux/kasan-enabled.h b/include/linux/kasan-enabled.h > > index 6f612d69ea0..9eca967d852 100644 > > --- a/include/linux/kasan-enabled.h > > +++ b/include/linux/kasan-enabled.h > > @@ -4,32 +4,46 @@ > > > > #include <linux/static_key.h> > > > > -#ifdef CONFIG_KASAN_HW_TAGS > > - > > +#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS) > > +/* > > + * Global runtime flag for KASAN modes that need runtime control. > > + * Used by ARCH_DEFER_KASAN architectures and HW_TAGS mode. > > + */ > > DECLARE_STATIC_KEY_FALSE(kasan_flag_enabled); > > > > +/* > > + * Runtime control for shadow memory initialization or HW_TAGS mode. > > + * Uses static key for architectures that need deferred KASAN or HW_TAGS. > > + */ > > static __always_inline bool kasan_enabled(void) > > { > > return static_branch_likely(&kasan_flag_enabled); > > } > > > > -static inline bool kasan_hw_tags_enabled(void) > > +static inline void kasan_enable(void) > > { > > - return kasan_enabled(); > > + static_branch_enable(&kasan_flag_enabled); > > } > > - > > -#else /* CONFIG_KASAN_HW_TAGS */ > > - > > -static inline bool kasan_enabled(void) > > +#else > > +/* For architectures that can enable KASAN early, use compile-time check. */ > > +static __always_inline bool kasan_enabled(void) > > { > > return IS_ENABLED(CONFIG_KASAN); > > } > > > > +static inline void kasan_enable(void) {} > > +#endif /* CONFIG_ARCH_DEFER_KASAN || CONFIG_KASAN_HW_TAGS */ > > + > > +#ifdef CONFIG_KASAN_HW_TAGS > > +static inline bool kasan_hw_tags_enabled(void) > > +{ > > + return kasan_enabled(); > > +} > > +#else > > static inline bool kasan_hw_tags_enabled(void) > > { > > return false; > > } > > - > > #endif /* CONFIG_KASAN_HW_TAGS */ > > > > #endif /* LINUX_KASAN_ENABLED_H */ > > diff --git a/include/linux/kasan.h b/include/linux/kasan.h > > index 890011071f2..51a8293d1af 100644 > > --- a/include/linux/kasan.h > > +++ b/include/linux/kasan.h > > @@ -543,6 +543,12 @@ void kasan_report_async(void); > > > > #endif /* CONFIG_KASAN_HW_TAGS */ > > > > +#ifdef CONFIG_KASAN_GENERIC > > +void __init kasan_init_generic(void); > > +#else > > +static inline void kasan_init_generic(void) { } > > +#endif > > + > > #ifdef CONFIG_KASAN_SW_TAGS > > void __init kasan_init_sw_tags(void); > > #else > > diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan > > index f82889a830f..38456560c85 100644 > > --- a/lib/Kconfig.kasan > > +++ b/lib/Kconfig.kasan > > @@ -19,6 +19,14 @@ config ARCH_DISABLE_KASAN_INLINE > > Disables both inline and stack instrumentation. Selected by > > architectures that do not support these instrumentation types. > > > > +config ARCH_DEFER_KASAN > > + bool > > + help > > + Architectures should select this if they need to defer KASAN > > + initialization until shadow memory is properly set up. This > > + enables runtime control via static keys. Otherwise, KASAN uses > > + compile-time constants for better performance. > > + > > config CC_HAS_KASAN_GENERIC > > def_bool $(cc-option, -fsanitize=kernel-address) > > > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c > > index 9142964ab9c..d9d389870a2 100644 > > --- a/mm/kasan/common.c > > +++ b/mm/kasan/common.c > > @@ -32,6 +32,15 @@ > > #include "kasan.h" > > #include "../slab.h" > > > > +#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS) > > +/* > > + * Definition of the unified static key declared in kasan-enabled.h. > > + * This provides consistent runtime enable/disable across KASAN modes. > > + */ > > +DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); > > +EXPORT_SYMBOL(kasan_flag_enabled); > > Shouldn't new exports be GPL ? > > > +#endif > > + > > struct slab *kasan_addr_to_slab(const void *addr) > > { > > if (virt_addr_valid(addr)) > > @@ -246,7 +255,7 @@ static inline void poison_slab_object(struct kmem_cache *cache, void *object, > > bool __kasan_slab_pre_free(struct kmem_cache *cache, void *object, > > unsigned long ip) > > { > > - if (!kasan_arch_is_ready() || is_kfence_address(object)) > > + if (is_kfence_address(object)) > > Here and below, no need to replace kasan_arch_is_ready() by > kasan_enabled() ? > > > return false; > > return check_slab_allocation(cache, object, ip); > > } > > @@ -254,7 +263,7 @@ bool __kasan_slab_pre_free(struct kmem_cache *cache, void *object, > > bool __kasan_slab_free(struct kmem_cache *cache, void *object, bool init, > > bool still_accessible) > > { > > - if (!kasan_arch_is_ready() || is_kfence_address(object)) > > + if (is_kfence_address(object)) > > return false; > > > > /* > > @@ -293,7 +302,7 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *object, bool init, > > > > static inline bool check_page_allocation(void *ptr, unsigned long ip) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return false; > > > > if (ptr != page_address(virt_to_head_page(ptr))) { > > @@ -522,7 +531,7 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned long ip) > > return true; > > } > > > > - if (is_kfence_address(ptr) || !kasan_arch_is_ready()) > > + if (is_kfence_address(ptr)) > > return true; > > > > slab = folio_slab(folio); > > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c > > index d54e89f8c3e..b413c46b3e0 100644 > > --- a/mm/kasan/generic.c > > +++ b/mm/kasan/generic.c > > @@ -36,6 +36,17 @@ > > #include "kasan.h" > > #include "../slab.h" > > > > +/* > > + * Initialize Generic KASAN and enable runtime checks. > > + * This should be called from arch kasan_init() once shadow memory is ready. > > + */ > > +void __init kasan_init_generic(void) > > +{ > > + kasan_enable(); > > + > > + pr_info("KernelAddressSanitizer initialized (generic)\n"); > > +} > > + > > /* > > * All functions below always inlined so compiler could > > * perform better optimizations in each of __asan_loadX/__assn_storeX > > @@ -165,7 +176,7 @@ static __always_inline bool check_region_inline(const void *addr, > > size_t size, bool write, > > unsigned long ret_ip) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return true; > > > > if (unlikely(size == 0)) > > @@ -193,7 +204,7 @@ bool kasan_byte_accessible(const void *addr) > > { > > s8 shadow_byte; > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return true; > > > > shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(addr)); > > @@ -495,7 +506,7 @@ static void release_alloc_meta(struct kasan_alloc_meta *meta) > > > > static void release_free_meta(const void *object, struct kasan_free_meta *meta) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > /* Check if free meta is valid. */ > > @@ -562,7 +573,7 @@ void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags) > > kasan_save_track(&alloc_meta->alloc_track, flags); > > } > > > > -void kasan_save_free_info(struct kmem_cache *cache, void *object) > > +void __kasan_save_free_info(struct kmem_cache *cache, void *object) > > { > > struct kasan_free_meta *free_meta; > > > > diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c > > index 9a6927394b5..c8289a3feab 100644 > > --- a/mm/kasan/hw_tags.c > > +++ b/mm/kasan/hw_tags.c > > @@ -45,13 +45,6 @@ static enum kasan_arg kasan_arg __ro_after_init; > > static enum kasan_arg_mode kasan_arg_mode __ro_after_init; > > static enum kasan_arg_vmalloc kasan_arg_vmalloc __initdata; > > > > -/* > > - * Whether KASAN is enabled at all. > > - * The value remains false until KASAN is initialized by kasan_init_hw_tags(). > > - */ > > -DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled); > > -EXPORT_SYMBOL(kasan_flag_enabled); > > - > > /* > > * Whether the selected mode is synchronous, asynchronous, or asymmetric. > > * Defaults to KASAN_MODE_SYNC. > > @@ -260,7 +253,7 @@ void __init kasan_init_hw_tags(void) > > kasan_init_tags(); > > > > /* KASAN is now initialized, enable it. */ > > - static_branch_enable(&kasan_flag_enabled); > > + kasan_enable(); > > > > pr_info("KernelAddressSanitizer initialized (hw-tags, mode=%s, vmalloc=%s, stacktrace=%s)\n", > > kasan_mode_info(), > > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h > > index 129178be5e6..8a9d8a6ea71 100644 > > --- a/mm/kasan/kasan.h > > +++ b/mm/kasan/kasan.h > > @@ -398,7 +398,13 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags, depot_flags_t depot_flags); > > void kasan_set_track(struct kasan_track *track, depot_stack_handle_t stack); > > void kasan_save_track(struct kasan_track *track, gfp_t flags); > > void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags); > > -void kasan_save_free_info(struct kmem_cache *cache, void *object); > > + > > +void __kasan_save_free_info(struct kmem_cache *cache, void *object); > > +static inline void kasan_save_free_info(struct kmem_cache *cache, void *object) > > +{ > > + if (kasan_enabled()) > > + __kasan_save_free_info(cache, object); > > +} > > > > #ifdef CONFIG_KASAN_GENERIC > > bool kasan_quarantine_put(struct kmem_cache *cache, void *object); > > diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c > > index d2c70cd2afb..2e126cb21b6 100644 > > --- a/mm/kasan/shadow.c > > +++ b/mm/kasan/shadow.c > > @@ -125,7 +125,7 @@ void kasan_poison(const void *addr, size_t size, u8 value, bool init) > > { > > void *shadow_start, *shadow_end; > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > /* > > @@ -150,7 +150,7 @@ EXPORT_SYMBOL_GPL(kasan_poison); > > #ifdef CONFIG_KASAN_GENERIC > > void kasan_poison_last_granule(const void *addr, size_t size) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > if (size & KASAN_GRANULE_MASK) { > > @@ -390,7 +390,7 @@ int kasan_populate_vmalloc(unsigned long addr, unsigned long size) > > unsigned long shadow_start, shadow_end; > > int ret; > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return 0; > > > > if (!is_vmalloc_or_module_addr((void *)addr)) > > @@ -560,7 +560,7 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end, > > unsigned long region_start, region_end; > > unsigned long size; > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > region_start = ALIGN(start, KASAN_MEMORY_PER_SHADOW_PAGE); > > @@ -611,7 +611,7 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size, > > * with setting memory tags, so the KASAN_VMALLOC_INIT flag is ignored. > > */ > > > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return (void *)start; > > > > if (!is_vmalloc_or_module_addr(start)) > > @@ -636,7 +636,7 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size, > > */ > > void __kasan_poison_vmalloc(const void *start, unsigned long size) > > { > > - if (!kasan_arch_is_ready()) > > + if (!kasan_enabled()) > > return; > > > > if (!is_vmalloc_or_module_addr(start)) > > diff --git a/mm/kasan/sw_tags.c b/mm/kasan/sw_tags.c > > index b9382b5b6a3..c75741a7460 100644 > > --- a/mm/kasan/sw_tags.c > > +++ b/mm/kasan/sw_tags.c > > @@ -44,6 +44,7 @@ void __init kasan_init_sw_tags(void) > > per_cpu(prng_state, cpu) = (u32)get_cycles(); > > > > kasan_init_tags(); > > + kasan_enable(); > > > > pr_info("KernelAddressSanitizer initialized (sw-tags, stacktrace=%s)\n", > > str_on_off(kasan_stack_collection_enabled())); > > diff --git a/mm/kasan/tags.c b/mm/kasan/tags.c > > index d65d48b85f9..b9f31293622 100644 > > --- a/mm/kasan/tags.c > > +++ b/mm/kasan/tags.c > > @@ -142,7 +142,7 @@ void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags) > > save_stack_info(cache, object, flags, false); > > } > > > > -void kasan_save_free_info(struct kmem_cache *cache, void *object) > > +void __kasan_save_free_info(struct kmem_cache *cache, void *object) > > { > > save_stack_info(cache, object, 0, true); > > } > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes 2025-08-08 15:33 ` Sabyrzhan Tasbolatov @ 2025-08-08 17:03 ` Christophe Leroy 2025-08-10 7:20 ` Sabyrzhan Tasbolatov 0 siblings, 1 reply; 13+ messages in thread From: Christophe Leroy @ 2025-08-08 17:03 UTC (permalink / raw) To: Sabyrzhan Tasbolatov Cc: ryabinin.a.a, bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov, alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm Le 08/08/2025 à 17:33, Sabyrzhan Tasbolatov a écrit : > On Fri, Aug 8, 2025 at 10:03 AM Christophe Leroy > <christophe.leroy@csgroup.eu> wrote: >> >> >> >> Le 07/08/2025 à 21:40, Sabyrzhan Tasbolatov a écrit : >>> Introduce CONFIG_ARCH_DEFER_KASAN to identify architectures [1] that need >>> to defer KASAN initialization until shadow memory is properly set up, >>> and unify the static key infrastructure across all KASAN modes. >> >> That probably desserves more details, maybe copy in informations from >> the top of cover letter. >> >> I think there should also be some exeplanations about >> kasan_arch_is_ready() becoming kasan_enabled(), and also why >> kasan_arch_is_ready() completely disappear from mm/kasan/common.c >> without being replaced by kasan_enabled(). >> >>> >>> [1] PowerPC, UML, LoongArch selects ARCH_DEFER_KASAN. >>> >>> Closes: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.kernel.org%2Fshow_bug.cgi%3Fid%3D217049&data=05%7C02%7Cchristophe.leroy%40csgroup.eu%7Cfe4f5a759ad6452b047408ddd691024a%7C8b87af7d86474dc78df45f69a2011bb5%7C0%7C0%7C638902640503259176%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=UM4uvQihJdeWwcC6DIiJXbn4wGsrijjRcHc55uCMErI%3D&reserved=0 >>> Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> >>> --- >>> Changes in v5: >>> - Unified patches where arch (powerpc, UML, loongarch) selects >>> ARCH_DEFER_KASAN in the first patch not to break >>> bisectability >>> - Removed kasan_arch_is_ready completely as there is no user >>> - Removed __wrappers in v4, left only those where it's necessary >>> due to different implementations >>> >>> Changes in v4: >>> - Fixed HW_TAGS static key functionality (was broken in v3) >>> - Merged configuration and implementation for atomicity >>> --- >>> arch/loongarch/Kconfig | 1 + >>> arch/loongarch/include/asm/kasan.h | 7 ------ >>> arch/loongarch/mm/kasan_init.c | 8 +++---- >>> arch/powerpc/Kconfig | 1 + >>> arch/powerpc/include/asm/kasan.h | 12 ---------- >>> arch/powerpc/mm/kasan/init_32.c | 2 +- >>> arch/powerpc/mm/kasan/init_book3e_64.c | 2 +- >>> arch/powerpc/mm/kasan/init_book3s_64.c | 6 +---- >>> arch/um/Kconfig | 1 + >>> arch/um/include/asm/kasan.h | 5 ++-- >>> arch/um/kernel/mem.c | 10 ++++++-- >>> include/linux/kasan-enabled.h | 32 ++++++++++++++++++-------- >>> include/linux/kasan.h | 6 +++++ >>> lib/Kconfig.kasan | 8 +++++++ >>> mm/kasan/common.c | 17 ++++++++++---- >>> mm/kasan/generic.c | 19 +++++++++++---- >>> mm/kasan/hw_tags.c | 9 +------- >>> mm/kasan/kasan.h | 8 ++++++- >>> mm/kasan/shadow.c | 12 +++++----- >>> mm/kasan/sw_tags.c | 1 + >>> mm/kasan/tags.c | 2 +- >>> 21 files changed, 100 insertions(+), 69 deletions(-) >>> >>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig >>> index f0abc38c40a..cd64b2bc12d 100644 >>> --- a/arch/loongarch/Kconfig >>> +++ b/arch/loongarch/Kconfig >>> @@ -9,6 +9,7 @@ config LOONGARCH >>> select ACPI_PPTT if ACPI >>> select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI >>> select ARCH_BINFMT_ELF_STATE >>> + select ARCH_DEFER_KASAN if KASAN >> >> Instead of adding 'if KASAN' in all users, you could do in two steps: >> >> Add a symbol ARCH_NEEDS_DEFER_KASAN. >> >> +config ARCH_NEEDS_DEFER_KASAN >> + bool >> >> And then: >> >> +config ARCH_DEFER_KASAN >> + def_bool >> + depends on KASAN >> + depends on ARCH_DEFER_KASAN >> + help >> + Architectures should select this if they need to defer KASAN >> + initialization until shadow memory is properly set up. This >> + enables runtime control via static keys. Otherwise, KASAN uses >> + compile-time constants for better performance. >> > > Actually, I don't see the benefits from this option. Sorry, have just > revisited this again. > With the new symbol, arch (PowerPC, UML, LoongArch) still needs select > 2 options: > > select ARCH_NEEDS_DEFER_KASAN > select ARCH_DEFER_KASAN Sorry, my mistake, ARCH_DEFER_KASAN has to be 'def_bool y'. Missing the 'y'. That way it is automatically set to 'y' as long as KASAN and ARCH_NEEDS_DEFER_KASAN are selected. Should be: config ARCH_DEFER_KASAN def_bool y depends on KASAN depends on ARCH_NEEDS_DEFER_KASAN > > and the oneline with `if` condition is cleaner. > select ARCH_DEFER_KASAN if KASAN > I don't think so because it requires all architectures to add 'if KASAN' which is not convenient. Christophe ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes 2025-08-08 17:03 ` Christophe Leroy @ 2025-08-10 7:20 ` Sabyrzhan Tasbolatov 2025-08-10 7:32 ` Sabyrzhan Tasbolatov 0 siblings, 1 reply; 13+ messages in thread From: Sabyrzhan Tasbolatov @ 2025-08-10 7:20 UTC (permalink / raw) To: Christophe Leroy Cc: ryabinin.a.a, bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov, alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm On Fri, Aug 8, 2025 at 10:03 PM Christophe Leroy <christophe.leroy@csgroup.eu> wrote: > > > > Le 08/08/2025 à 17:33, Sabyrzhan Tasbolatov a écrit : > > On Fri, Aug 8, 2025 at 10:03 AM Christophe Leroy > > <christophe.leroy@csgroup.eu> wrote: > >> > >> > >> > >> Le 07/08/2025 à 21:40, Sabyrzhan Tasbolatov a écrit : > >>> Introduce CONFIG_ARCH_DEFER_KASAN to identify architectures [1] that need > >>> to defer KASAN initialization until shadow memory is properly set up, > >>> and unify the static key infrastructure across all KASAN modes. > >> > >> That probably desserves more details, maybe copy in informations from > >> the top of cover letter. > >> > >> I think there should also be some exeplanations about > >> kasan_arch_is_ready() becoming kasan_enabled(), and also why > >> kasan_arch_is_ready() completely disappear from mm/kasan/common.c > >> without being replaced by kasan_enabled(). > >> > >>> > >>> [1] PowerPC, UML, LoongArch selects ARCH_DEFER_KASAN. > >>> > >>> Closes: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.kernel.org%2Fshow_bug.cgi%3Fid%3D217049&data=05%7C02%7Cchristophe.leroy%40csgroup.eu%7Cfe4f5a759ad6452b047408ddd691024a%7C8b87af7d86474dc78df45f69a2011bb5%7C0%7C0%7C638902640503259176%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=UM4uvQihJdeWwcC6DIiJXbn4wGsrijjRcHc55uCMErI%3D&reserved=0 > >>> Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> > >>> --- > >>> Changes in v5: > >>> - Unified patches where arch (powerpc, UML, loongarch) selects > >>> ARCH_DEFER_KASAN in the first patch not to break > >>> bisectability > >>> - Removed kasan_arch_is_ready completely as there is no user > >>> - Removed __wrappers in v4, left only those where it's necessary > >>> due to different implementations > >>> > >>> Changes in v4: > >>> - Fixed HW_TAGS static key functionality (was broken in v3) > >>> - Merged configuration and implementation for atomicity > >>> --- > >>> arch/loongarch/Kconfig | 1 + > >>> arch/loongarch/include/asm/kasan.h | 7 ------ > >>> arch/loongarch/mm/kasan_init.c | 8 +++---- > >>> arch/powerpc/Kconfig | 1 + > >>> arch/powerpc/include/asm/kasan.h | 12 ---------- > >>> arch/powerpc/mm/kasan/init_32.c | 2 +- > >>> arch/powerpc/mm/kasan/init_book3e_64.c | 2 +- > >>> arch/powerpc/mm/kasan/init_book3s_64.c | 6 +---- > >>> arch/um/Kconfig | 1 + > >>> arch/um/include/asm/kasan.h | 5 ++-- > >>> arch/um/kernel/mem.c | 10 ++++++-- > >>> include/linux/kasan-enabled.h | 32 ++++++++++++++++++-------- > >>> include/linux/kasan.h | 6 +++++ > >>> lib/Kconfig.kasan | 8 +++++++ > >>> mm/kasan/common.c | 17 ++++++++++---- > >>> mm/kasan/generic.c | 19 +++++++++++---- > >>> mm/kasan/hw_tags.c | 9 +------- > >>> mm/kasan/kasan.h | 8 ++++++- > >>> mm/kasan/shadow.c | 12 +++++----- > >>> mm/kasan/sw_tags.c | 1 + > >>> mm/kasan/tags.c | 2 +- > >>> 21 files changed, 100 insertions(+), 69 deletions(-) > >>> > >>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig > >>> index f0abc38c40a..cd64b2bc12d 100644 > >>> --- a/arch/loongarch/Kconfig > >>> +++ b/arch/loongarch/Kconfig > >>> @@ -9,6 +9,7 @@ config LOONGARCH > >>> select ACPI_PPTT if ACPI > >>> select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI > >>> select ARCH_BINFMT_ELF_STATE > >>> + select ARCH_DEFER_KASAN if KASAN > >> > >> Instead of adding 'if KASAN' in all users, you could do in two steps: > >> > >> Add a symbol ARCH_NEEDS_DEFER_KASAN. > >> > >> +config ARCH_NEEDS_DEFER_KASAN > >> + bool > >> > >> And then: > >> > >> +config ARCH_DEFER_KASAN > >> + def_bool > >> + depends on KASAN > >> + depends on ARCH_DEFER_KASAN > >> + help > >> + Architectures should select this if they need to defer KASAN > >> + initialization until shadow memory is properly set up. This > >> + enables runtime control via static keys. Otherwise, KASAN uses > >> + compile-time constants for better performance. > >> > > > > Actually, I don't see the benefits from this option. Sorry, have just > > revisited this again. > > With the new symbol, arch (PowerPC, UML, LoongArch) still needs select > > 2 options: > > > > select ARCH_NEEDS_DEFER_KASAN > > select ARCH_DEFER_KASAN > > Sorry, my mistake, ARCH_DEFER_KASAN has to be 'def_bool y'. Missing the > 'y'. That way it is automatically set to 'y' as long as KASAN and > ARCH_NEEDS_DEFER_KASAN are selected. Should be: > > config ARCH_DEFER_KASAN > def_bool y > depends on KASAN > depends on ARCH_NEEDS_DEFER_KASAN > > > > > > and the oneline with `if` condition is cleaner. > > select ARCH_DEFER_KASAN if KASAN Hello, Have just had a chance to test this. lib/Kconfig.kasan: config ARCH_NEEDS_DEFER_KASAN bool config ARCH_DEFER_KASAN def_bool y depends on KASAN depends on ARCH_NEEDS_DEFER_KASAN It works for UML defconfig where arch/um/Kconfig is: config UML bool default y select ARCH_NEEDS_DEFER_KASAN select ARCH_DEFER_KASAN if STATIC_LINK But it prints warnings for PowerPC, LoongArch: config LOONGARCH bool ... select ARCH_NEEDS_DEFER_KASAN select ARCH_DEFER_KASAN $ make defconfig ARCH=loongarch *** Default configuration is based on 'loongson3_defconfig' WARNING: unmet direct dependencies detected for ARCH_DEFER_KASAN Depends on [n]: KASAN [=n] && ARCH_NEEDS_DEFER_KASAN [=y] Selected by [y]: - LOONGARCH [=y] config PPC bool default y select ARCH_DEFER_KASAN if PPC_RADIX_MMU select ARCH_NEEDS_DEFER_KASAN $ make ppc64_defconfig WARNING: unmet direct dependencies detected for ARCH_DEFER_KASAN Depends on [n]: KASAN [=n] && ARCH_NEEDS_DEFER_KASAN [=y] Selected by [y]: - PPC [=y] && PPC_RADIX_MMU [=y] > > > > I don't think so because it requires all architectures to add 'if KASAN' > which is not convenient. > > Christophe ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes 2025-08-10 7:20 ` Sabyrzhan Tasbolatov @ 2025-08-10 7:32 ` Sabyrzhan Tasbolatov 0 siblings, 0 replies; 13+ messages in thread From: Sabyrzhan Tasbolatov @ 2025-08-10 7:32 UTC (permalink / raw) To: Christophe Leroy Cc: ryabinin.a.a, bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, glider, dvyukov, alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm, davidgow On Sun, Aug 10, 2025 at 12:20 PM Sabyrzhan Tasbolatov <snovitoll@gmail.com> wrote: > > On Fri, Aug 8, 2025 at 10:03 PM Christophe Leroy > <christophe.leroy@csgroup.eu> wrote: > > > > > > > > Le 08/08/2025 à 17:33, Sabyrzhan Tasbolatov a écrit : > > > On Fri, Aug 8, 2025 at 10:03 AM Christophe Leroy > > > <christophe.leroy@csgroup.eu> wrote: > > >> > > >> > > >> > > >> Le 07/08/2025 à 21:40, Sabyrzhan Tasbolatov a écrit : > > >>> Introduce CONFIG_ARCH_DEFER_KASAN to identify architectures [1] that need > > >>> to defer KASAN initialization until shadow memory is properly set up, > > >>> and unify the static key infrastructure across all KASAN modes. > > >> > > >> That probably desserves more details, maybe copy in informations from > > >> the top of cover letter. > > >> > > >> I think there should also be some exeplanations about > > >> kasan_arch_is_ready() becoming kasan_enabled(), and also why > > >> kasan_arch_is_ready() completely disappear from mm/kasan/common.c > > >> without being replaced by kasan_enabled(). > > >> > > >>> > > >>> [1] PowerPC, UML, LoongArch selects ARCH_DEFER_KASAN. > > >>> > > >>> Closes: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.kernel.org%2Fshow_bug.cgi%3Fid%3D217049&data=05%7C02%7Cchristophe.leroy%40csgroup.eu%7Cfe4f5a759ad6452b047408ddd691024a%7C8b87af7d86474dc78df45f69a2011bb5%7C0%7C0%7C638902640503259176%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=UM4uvQihJdeWwcC6DIiJXbn4wGsrijjRcHc55uCMErI%3D&reserved=0 > > >>> Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> > > >>> --- > > >>> Changes in v5: > > >>> - Unified patches where arch (powerpc, UML, loongarch) selects > > >>> ARCH_DEFER_KASAN in the first patch not to break > > >>> bisectability > > >>> - Removed kasan_arch_is_ready completely as there is no user > > >>> - Removed __wrappers in v4, left only those where it's necessary > > >>> due to different implementations > > >>> > > >>> Changes in v4: > > >>> - Fixed HW_TAGS static key functionality (was broken in v3) > > >>> - Merged configuration and implementation for atomicity > > >>> --- > > >>> arch/loongarch/Kconfig | 1 + > > >>> arch/loongarch/include/asm/kasan.h | 7 ------ > > >>> arch/loongarch/mm/kasan_init.c | 8 +++---- > > >>> arch/powerpc/Kconfig | 1 + > > >>> arch/powerpc/include/asm/kasan.h | 12 ---------- > > >>> arch/powerpc/mm/kasan/init_32.c | 2 +- > > >>> arch/powerpc/mm/kasan/init_book3e_64.c | 2 +- > > >>> arch/powerpc/mm/kasan/init_book3s_64.c | 6 +---- > > >>> arch/um/Kconfig | 1 + > > >>> arch/um/include/asm/kasan.h | 5 ++-- > > >>> arch/um/kernel/mem.c | 10 ++++++-- > > >>> include/linux/kasan-enabled.h | 32 ++++++++++++++++++-------- > > >>> include/linux/kasan.h | 6 +++++ > > >>> lib/Kconfig.kasan | 8 +++++++ > > >>> mm/kasan/common.c | 17 ++++++++++---- > > >>> mm/kasan/generic.c | 19 +++++++++++---- > > >>> mm/kasan/hw_tags.c | 9 +------- > > >>> mm/kasan/kasan.h | 8 ++++++- > > >>> mm/kasan/shadow.c | 12 +++++----- > > >>> mm/kasan/sw_tags.c | 1 + > > >>> mm/kasan/tags.c | 2 +- > > >>> 21 files changed, 100 insertions(+), 69 deletions(-) > > >>> > > >>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig > > >>> index f0abc38c40a..cd64b2bc12d 100644 > > >>> --- a/arch/loongarch/Kconfig > > >>> +++ b/arch/loongarch/Kconfig > > >>> @@ -9,6 +9,7 @@ config LOONGARCH > > >>> select ACPI_PPTT if ACPI > > >>> select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI > > >>> select ARCH_BINFMT_ELF_STATE > > >>> + select ARCH_DEFER_KASAN if KASAN > > >> > > >> Instead of adding 'if KASAN' in all users, you could do in two steps: > > >> > > >> Add a symbol ARCH_NEEDS_DEFER_KASAN. > > >> > > >> +config ARCH_NEEDS_DEFER_KASAN > > >> + bool > > >> > > >> And then: > > >> > > >> +config ARCH_DEFER_KASAN > > >> + def_bool > > >> + depends on KASAN > > >> + depends on ARCH_DEFER_KASAN > > >> + help > > >> + Architectures should select this if they need to defer KASAN > > >> + initialization until shadow memory is properly set up. This > > >> + enables runtime control via static keys. Otherwise, KASAN uses > > >> + compile-time constants for better performance. > > >> > > > > > > Actually, I don't see the benefits from this option. Sorry, have just > > > revisited this again. > > > With the new symbol, arch (PowerPC, UML, LoongArch) still needs select > > > 2 options: > > > > > > select ARCH_NEEDS_DEFER_KASAN > > > select ARCH_DEFER_KASAN > > > > Sorry, my mistake, ARCH_DEFER_KASAN has to be 'def_bool y'. Missing the > > 'y'. That way it is automatically set to 'y' as long as KASAN and > > ARCH_NEEDS_DEFER_KASAN are selected. Should be: > > > > config ARCH_DEFER_KASAN > > def_bool y > > depends on KASAN > > depends on ARCH_NEEDS_DEFER_KASAN > > > > > > > > > > and the oneline with `if` condition is cleaner. > > > select ARCH_DEFER_KASAN if KASAN > > Hello, > > Have just had a chance to test this. > > lib/Kconfig.kasan: > config ARCH_NEEDS_DEFER_KASAN > bool > > config ARCH_DEFER_KASAN > def_bool y > depends on KASAN > depends on ARCH_NEEDS_DEFER_KASAN Setting Kconfig.kasan without KASAN works fine for 3 arch that selects ARCH_DEFER_KASAN: config ARCH_DEFER_KASAN def_bool y depends on ARCH_NEEDS_DEFER_KASAN Going to send v6 soon. P.S.: Fixed email of David Gow. > > It works for UML defconfig where arch/um/Kconfig is: > > config UML > bool > default y > select ARCH_NEEDS_DEFER_KASAN > select ARCH_DEFER_KASAN if STATIC_LINK > > But it prints warnings for PowerPC, LoongArch: > > config LOONGARCH > bool > ... > select ARCH_NEEDS_DEFER_KASAN > select ARCH_DEFER_KASAN > > $ make defconfig ARCH=loongarch > *** Default configuration is based on 'loongson3_defconfig' > > WARNING: unmet direct dependencies detected for ARCH_DEFER_KASAN > Depends on [n]: KASAN [=n] && ARCH_NEEDS_DEFER_KASAN [=y] > Selected by [y]: > - LOONGARCH [=y] > > > config PPC > bool > default y > select ARCH_DEFER_KASAN if PPC_RADIX_MMU > select ARCH_NEEDS_DEFER_KASAN > > $ make ppc64_defconfig > > WARNING: unmet direct dependencies detected for ARCH_DEFER_KASAN > Depends on [n]: KASAN [=n] && ARCH_NEEDS_DEFER_KASAN [=y] > Selected by [y]: > - PPC [=y] && PPC_RADIX_MMU [=y] > > > > > > > > > I don't think so because it requires all architectures to add 'if KASAN' > > which is not convenient. > > > > Christophe ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 2/2] kasan: call kasan_init_generic in kasan_init 2025-08-07 19:40 [PATCH v5 0/2] kasan: unify kasan_enabled() and remove arch-specific implementations Sabyrzhan Tasbolatov 2025-08-07 19:40 ` [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes Sabyrzhan Tasbolatov @ 2025-08-07 19:40 ` Sabyrzhan Tasbolatov 2025-08-08 5:07 ` Christophe Leroy 1 sibling, 1 reply; 13+ messages in thread From: Sabyrzhan Tasbolatov @ 2025-08-07 19:40 UTC (permalink / raw) To: ryabinin.a.a, bhe, hca, christophe.leroy, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov Cc: alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm, snovitoll, Alexandre Ghiti Call kasan_init_generic() which handles Generic KASAN initialization. For architectures that do not select ARCH_DEFER_KASAN, this will be a no-op for the runtime flag but will print the initialization banner. For SW_TAGS and HW_TAGS modes, their respective init functions will handle the flag enabling, if they are enabled/implemented. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049 Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> Tested-by: Alexandre Ghiti <alexghiti@rivosinc.com> # riscv Acked-by: Alexander Gordeev <agordeev@linux.ibm.com> # s390 --- Changes in v5: - Unified arch patches into a single one, where we just call kasan_init_generic() - Added Tested-by tag for riscv (tested the same change in v4) - Added Acked-by tag for s390 (tested the same change in v4) --- arch/arm/mm/kasan_init.c | 2 +- arch/arm64/mm/kasan_init.c | 4 +--- arch/riscv/mm/kasan_init.c | 1 + arch/s390/kernel/early.c | 3 ++- arch/x86/mm/kasan_init_64.c | 2 +- arch/xtensa/mm/kasan_init.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c index 111d4f70313..c6625e808bf 100644 --- a/arch/arm/mm/kasan_init.c +++ b/arch/arm/mm/kasan_init.c @@ -300,6 +300,6 @@ void __init kasan_init(void) local_flush_tlb_all(); memset(kasan_early_shadow_page, 0, PAGE_SIZE); - pr_info("Kernel address sanitizer initialized\n"); init_task.kasan_depth = 0; + kasan_init_generic(); } diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c index d541ce45dae..abeb81bf6eb 100644 --- a/arch/arm64/mm/kasan_init.c +++ b/arch/arm64/mm/kasan_init.c @@ -399,14 +399,12 @@ void __init kasan_init(void) { kasan_init_shadow(); kasan_init_depth(); -#if defined(CONFIG_KASAN_GENERIC) + kasan_init_generic(); /* * Generic KASAN is now fully initialized. * Software and Hardware Tag-Based modes still require * kasan_init_sw_tags() and kasan_init_hw_tags() correspondingly. */ - pr_info("KernelAddressSanitizer initialized (generic)\n"); -#endif } #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */ diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c index 41c635d6aca..ba2709b1eec 100644 --- a/arch/riscv/mm/kasan_init.c +++ b/arch/riscv/mm/kasan_init.c @@ -530,6 +530,7 @@ void __init kasan_init(void) memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE); init_task.kasan_depth = 0; + kasan_init_generic(); csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | satp_mode); local_flush_tlb_all(); diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 9adfbdd377d..544e5403dd9 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -21,6 +21,7 @@ #include <linux/kernel.h> #include <asm/asm-extable.h> #include <linux/memblock.h> +#include <linux/kasan.h> #include <asm/access-regs.h> #include <asm/asm-offsets.h> #include <asm/machine.h> @@ -65,7 +66,7 @@ static void __init kasan_early_init(void) { #ifdef CONFIG_KASAN init_task.kasan_depth = 0; - pr_info("KernelAddressSanitizer initialized\n"); + kasan_init_generic(); #endif } diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c index 0539efd0d21..998b6010d6d 100644 --- a/arch/x86/mm/kasan_init_64.c +++ b/arch/x86/mm/kasan_init_64.c @@ -451,5 +451,5 @@ void __init kasan_init(void) __flush_tlb_all(); init_task.kasan_depth = 0; - pr_info("KernelAddressSanitizer initialized\n"); + kasan_init_generic(); } diff --git a/arch/xtensa/mm/kasan_init.c b/arch/xtensa/mm/kasan_init.c index f39c4d83173..0524b9ed5e6 100644 --- a/arch/xtensa/mm/kasan_init.c +++ b/arch/xtensa/mm/kasan_init.c @@ -94,5 +94,5 @@ void __init kasan_init(void) /* At this point kasan is fully initialized. Enable error messages. */ current->kasan_depth = 0; - pr_info("KernelAddressSanitizer initialized\n"); + kasan_init_generic(); } -- 2.34.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v5 2/2] kasan: call kasan_init_generic in kasan_init 2025-08-07 19:40 ` [PATCH v5 2/2] kasan: call kasan_init_generic in kasan_init Sabyrzhan Tasbolatov @ 2025-08-08 5:07 ` Christophe Leroy 2025-08-08 6:44 ` Sabyrzhan Tasbolatov 0 siblings, 1 reply; 13+ messages in thread From: Christophe Leroy @ 2025-08-08 5:07 UTC (permalink / raw) To: Sabyrzhan Tasbolatov, ryabinin.a.a, bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov Cc: alex, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm, Alexandre Ghiti Le 07/08/2025 à 21:40, Sabyrzhan Tasbolatov a écrit : > Call kasan_init_generic() which handles Generic KASAN initialization. > For architectures that do not select ARCH_DEFER_KASAN, > this will be a no-op for the runtime flag but will > print the initialization banner. > > For SW_TAGS and HW_TAGS modes, their respective init functions will > handle the flag enabling, if they are enabled/implemented. > > Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049 > Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> > Tested-by: Alexandre Ghiti <alexghiti@rivosinc.com> # riscv > Acked-by: Alexander Gordeev <agordeev@linux.ibm.com> # s390 > --- > Changes in v5: > - Unified arch patches into a single one, where we just call > kasan_init_generic() > - Added Tested-by tag for riscv (tested the same change in v4) > - Added Acked-by tag for s390 (tested the same change in v4) > --- > arch/arm/mm/kasan_init.c | 2 +- > arch/arm64/mm/kasan_init.c | 4 +--- > arch/riscv/mm/kasan_init.c | 1 + > arch/s390/kernel/early.c | 3 ++- > arch/x86/mm/kasan_init_64.c | 2 +- > arch/xtensa/mm/kasan_init.c | 2 +- > 6 files changed, 7 insertions(+), 7 deletions(-) > > diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c > index 111d4f70313..c6625e808bf 100644 > --- a/arch/arm/mm/kasan_init.c > +++ b/arch/arm/mm/kasan_init.c > @@ -300,6 +300,6 @@ void __init kasan_init(void) > local_flush_tlb_all(); > > memset(kasan_early_shadow_page, 0, PAGE_SIZE); > - pr_info("Kernel address sanitizer initialized\n"); > init_task.kasan_depth = 0; > + kasan_init_generic(); > } > diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c > index d541ce45dae..abeb81bf6eb 100644 > --- a/arch/arm64/mm/kasan_init.c > +++ b/arch/arm64/mm/kasan_init.c > @@ -399,14 +399,12 @@ void __init kasan_init(void) > { > kasan_init_shadow(); > kasan_init_depth(); > -#if defined(CONFIG_KASAN_GENERIC) > + kasan_init_generic(); > /* > * Generic KASAN is now fully initialized. > * Software and Hardware Tag-Based modes still require > * kasan_init_sw_tags() and kasan_init_hw_tags() correspondingly. > */ > - pr_info("KernelAddressSanitizer initialized (generic)\n"); > -#endif > } > > #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */ > diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c > index 41c635d6aca..ba2709b1eec 100644 > --- a/arch/riscv/mm/kasan_init.c > +++ b/arch/riscv/mm/kasan_init.c > @@ -530,6 +530,7 @@ void __init kasan_init(void) > > memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE); > init_task.kasan_depth = 0; > + kasan_init_generic(); I understood KASAN is really ready to function only once the csr_write() and local_flush_tlb_all() below are done. Shouldn't kasan_init_generic() be called after it ? > > csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | satp_mode); > local_flush_tlb_all(); > diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c > index 9adfbdd377d..544e5403dd9 100644 > --- a/arch/s390/kernel/early.c > +++ b/arch/s390/kernel/early.c > @@ -21,6 +21,7 @@ > #include <linux/kernel.h> > #include <asm/asm-extable.h> > #include <linux/memblock.h> > +#include <linux/kasan.h> > #include <asm/access-regs.h> > #include <asm/asm-offsets.h> > #include <asm/machine.h> > @@ -65,7 +66,7 @@ static void __init kasan_early_init(void) > { > #ifdef CONFIG_KASAN > init_task.kasan_depth = 0; > - pr_info("KernelAddressSanitizer initialized\n"); > + kasan_init_generic(); > #endif > } > > diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c > index 0539efd0d21..998b6010d6d 100644 > --- a/arch/x86/mm/kasan_init_64.c > +++ b/arch/x86/mm/kasan_init_64.c > @@ -451,5 +451,5 @@ void __init kasan_init(void) > __flush_tlb_all(); > > init_task.kasan_depth = 0; > - pr_info("KernelAddressSanitizer initialized\n"); > + kasan_init_generic(); > } > diff --git a/arch/xtensa/mm/kasan_init.c b/arch/xtensa/mm/kasan_init.c > index f39c4d83173..0524b9ed5e6 100644 > --- a/arch/xtensa/mm/kasan_init.c > +++ b/arch/xtensa/mm/kasan_init.c > @@ -94,5 +94,5 @@ void __init kasan_init(void) > > /* At this point kasan is fully initialized. Enable error messages. */ > current->kasan_depth = 0; > - pr_info("KernelAddressSanitizer initialized\n"); > + kasan_init_generic(); > } ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 2/2] kasan: call kasan_init_generic in kasan_init 2025-08-08 5:07 ` Christophe Leroy @ 2025-08-08 6:44 ` Sabyrzhan Tasbolatov 2025-08-08 7:21 ` Alexandre Ghiti 0 siblings, 1 reply; 13+ messages in thread From: Sabyrzhan Tasbolatov @ 2025-08-08 6:44 UTC (permalink / raw) To: Christophe Leroy, alex Cc: ryabinin.a.a, bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm, Alexandre Ghiti On Fri, Aug 8, 2025 at 10:07 AM Christophe Leroy <christophe.leroy@csgroup.eu> wrote: > > > > Le 07/08/2025 à 21:40, Sabyrzhan Tasbolatov a écrit : > > Call kasan_init_generic() which handles Generic KASAN initialization. > > For architectures that do not select ARCH_DEFER_KASAN, > > this will be a no-op for the runtime flag but will > > print the initialization banner. > > > > For SW_TAGS and HW_TAGS modes, their respective init functions will > > handle the flag enabling, if they are enabled/implemented. > > > > Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049 > > Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> > > Tested-by: Alexandre Ghiti <alexghiti@rivosinc.com> # riscv > > Acked-by: Alexander Gordeev <agordeev@linux.ibm.com> # s390 > > --- > > Changes in v5: > > - Unified arch patches into a single one, where we just call > > kasan_init_generic() > > - Added Tested-by tag for riscv (tested the same change in v4) > > - Added Acked-by tag for s390 (tested the same change in v4) > > --- > > arch/arm/mm/kasan_init.c | 2 +- > > arch/arm64/mm/kasan_init.c | 4 +--- > > arch/riscv/mm/kasan_init.c | 1 + > > arch/s390/kernel/early.c | 3 ++- > > arch/x86/mm/kasan_init_64.c | 2 +- > > arch/xtensa/mm/kasan_init.c | 2 +- > > 6 files changed, 7 insertions(+), 7 deletions(-) > > > > diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c > > index 111d4f70313..c6625e808bf 100644 > > --- a/arch/arm/mm/kasan_init.c > > +++ b/arch/arm/mm/kasan_init.c > > @@ -300,6 +300,6 @@ void __init kasan_init(void) > > local_flush_tlb_all(); > > > > memset(kasan_early_shadow_page, 0, PAGE_SIZE); > > - pr_info("Kernel address sanitizer initialized\n"); > > init_task.kasan_depth = 0; > > + kasan_init_generic(); > > } > > diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c > > index d541ce45dae..abeb81bf6eb 100644 > > --- a/arch/arm64/mm/kasan_init.c > > +++ b/arch/arm64/mm/kasan_init.c > > @@ -399,14 +399,12 @@ void __init kasan_init(void) > > { > > kasan_init_shadow(); > > kasan_init_depth(); > > -#if defined(CONFIG_KASAN_GENERIC) > > + kasan_init_generic(); > > /* > > * Generic KASAN is now fully initialized. > > * Software and Hardware Tag-Based modes still require > > * kasan_init_sw_tags() and kasan_init_hw_tags() correspondingly. > > */ > > - pr_info("KernelAddressSanitizer initialized (generic)\n"); > > -#endif > > } > > > > #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */ > > diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c > > index 41c635d6aca..ba2709b1eec 100644 > > --- a/arch/riscv/mm/kasan_init.c > > +++ b/arch/riscv/mm/kasan_init.c > > @@ -530,6 +530,7 @@ void __init kasan_init(void) > > > > memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE); > > init_task.kasan_depth = 0; > > + kasan_init_generic(); > > I understood KASAN is really ready to function only once the csr_write() > and local_flush_tlb_all() below are done. Shouldn't kasan_init_generic() > be called after it ? I will try to test this in v6: csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | satp_mode); local_flush_tlb_all(); kasan_init_generic(); Alexandre Ghiti said [1] it was not a problem, but I will check. [1] https://lore.kernel.org/all/20c1e656-512e-4424-9d4e-176af18bb7d6@ghiti.fr/ > > > > > csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | satp_mode); > > local_flush_tlb_all(); > > diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c > > index 9adfbdd377d..544e5403dd9 100644 > > --- a/arch/s390/kernel/early.c > > +++ b/arch/s390/kernel/early.c > > @@ -21,6 +21,7 @@ > > #include <linux/kernel.h> > > #include <asm/asm-extable.h> > > #include <linux/memblock.h> > > +#include <linux/kasan.h> > > #include <asm/access-regs.h> > > #include <asm/asm-offsets.h> > > #include <asm/machine.h> > > @@ -65,7 +66,7 @@ static void __init kasan_early_init(void) > > { > > #ifdef CONFIG_KASAN > > init_task.kasan_depth = 0; > > - pr_info("KernelAddressSanitizer initialized\n"); > > + kasan_init_generic(); > > #endif > > } > > > > diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c > > index 0539efd0d21..998b6010d6d 100644 > > --- a/arch/x86/mm/kasan_init_64.c > > +++ b/arch/x86/mm/kasan_init_64.c > > @@ -451,5 +451,5 @@ void __init kasan_init(void) > > __flush_tlb_all(); > > > > init_task.kasan_depth = 0; > > - pr_info("KernelAddressSanitizer initialized\n"); > > + kasan_init_generic(); > > } > > diff --git a/arch/xtensa/mm/kasan_init.c b/arch/xtensa/mm/kasan_init.c > > index f39c4d83173..0524b9ed5e6 100644 > > --- a/arch/xtensa/mm/kasan_init.c > > +++ b/arch/xtensa/mm/kasan_init.c > > @@ -94,5 +94,5 @@ void __init kasan_init(void) > > > > /* At this point kasan is fully initialized. Enable error messages. */ > > current->kasan_depth = 0; > > - pr_info("KernelAddressSanitizer initialized\n"); > > + kasan_init_generic(); > > } > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 2/2] kasan: call kasan_init_generic in kasan_init 2025-08-08 6:44 ` Sabyrzhan Tasbolatov @ 2025-08-08 7:21 ` Alexandre Ghiti 0 siblings, 0 replies; 13+ messages in thread From: Alexandre Ghiti @ 2025-08-08 7:21 UTC (permalink / raw) To: Sabyrzhan Tasbolatov, Christophe Leroy Cc: ryabinin.a.a, bhe, hca, andreyknvl, akpm, zhangqing, chenhuacai, davidgow, glider, dvyukov, agordeev, vincenzo.frascino, elver, kasan-dev, linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390, linux-um, linux-mm, Alexandre Ghiti On 8/8/25 08:44, Sabyrzhan Tasbolatov wrote: > On Fri, Aug 8, 2025 at 10:07 AM Christophe Leroy > <christophe.leroy@csgroup.eu> wrote: >> >> >> Le 07/08/2025 à 21:40, Sabyrzhan Tasbolatov a écrit : >>> Call kasan_init_generic() which handles Generic KASAN initialization. >>> For architectures that do not select ARCH_DEFER_KASAN, >>> this will be a no-op for the runtime flag but will >>> print the initialization banner. >>> >>> For SW_TAGS and HW_TAGS modes, their respective init functions will >>> handle the flag enabling, if they are enabled/implemented. >>> >>> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049 >>> Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> >>> Tested-by: Alexandre Ghiti <alexghiti@rivosinc.com> # riscv >>> Acked-by: Alexander Gordeev <agordeev@linux.ibm.com> # s390 >>> --- >>> Changes in v5: >>> - Unified arch patches into a single one, where we just call >>> kasan_init_generic() >>> - Added Tested-by tag for riscv (tested the same change in v4) >>> - Added Acked-by tag for s390 (tested the same change in v4) >>> --- >>> arch/arm/mm/kasan_init.c | 2 +- >>> arch/arm64/mm/kasan_init.c | 4 +--- >>> arch/riscv/mm/kasan_init.c | 1 + >>> arch/s390/kernel/early.c | 3 ++- >>> arch/x86/mm/kasan_init_64.c | 2 +- >>> arch/xtensa/mm/kasan_init.c | 2 +- >>> 6 files changed, 7 insertions(+), 7 deletions(-) >>> >>> diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c >>> index 111d4f70313..c6625e808bf 100644 >>> --- a/arch/arm/mm/kasan_init.c >>> +++ b/arch/arm/mm/kasan_init.c >>> @@ -300,6 +300,6 @@ void __init kasan_init(void) >>> local_flush_tlb_all(); >>> >>> memset(kasan_early_shadow_page, 0, PAGE_SIZE); >>> - pr_info("Kernel address sanitizer initialized\n"); >>> init_task.kasan_depth = 0; >>> + kasan_init_generic(); >>> } >>> diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c >>> index d541ce45dae..abeb81bf6eb 100644 >>> --- a/arch/arm64/mm/kasan_init.c >>> +++ b/arch/arm64/mm/kasan_init.c >>> @@ -399,14 +399,12 @@ void __init kasan_init(void) >>> { >>> kasan_init_shadow(); >>> kasan_init_depth(); >>> -#if defined(CONFIG_KASAN_GENERIC) >>> + kasan_init_generic(); >>> /* >>> * Generic KASAN is now fully initialized. >>> * Software and Hardware Tag-Based modes still require >>> * kasan_init_sw_tags() and kasan_init_hw_tags() correspondingly. >>> */ >>> - pr_info("KernelAddressSanitizer initialized (generic)\n"); >>> -#endif >>> } >>> >>> #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */ >>> diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c >>> index 41c635d6aca..ba2709b1eec 100644 >>> --- a/arch/riscv/mm/kasan_init.c >>> +++ b/arch/riscv/mm/kasan_init.c >>> @@ -530,6 +530,7 @@ void __init kasan_init(void) >>> >>> memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE); >>> init_task.kasan_depth = 0; >>> + kasan_init_generic(); >> I understood KASAN is really ready to function only once the csr_write() >> and local_flush_tlb_all() below are done. Shouldn't kasan_init_generic() >> be called after it ? > I will try to test this in v6: > > csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | satp_mode); > local_flush_tlb_all(); > kasan_init_generic(); Before setting the final kasan mapping, we still have the early one so we won't trap or anything on some kasan accesses. But if there is a v6, I agree it will be cleaner to do it this ^ way. Thanks, Alex > > Alexandre Ghiti said [1] it was not a problem, but I will check. > > [1] https://lore.kernel.org/all/20c1e656-512e-4424-9d4e-176af18bb7d6@ghiti.fr/ > >>> csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | satp_mode); >>> local_flush_tlb_all(); >>> diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c >>> index 9adfbdd377d..544e5403dd9 100644 >>> --- a/arch/s390/kernel/early.c >>> +++ b/arch/s390/kernel/early.c >>> @@ -21,6 +21,7 @@ >>> #include <linux/kernel.h> >>> #include <asm/asm-extable.h> >>> #include <linux/memblock.h> >>> +#include <linux/kasan.h> >>> #include <asm/access-regs.h> >>> #include <asm/asm-offsets.h> >>> #include <asm/machine.h> >>> @@ -65,7 +66,7 @@ static void __init kasan_early_init(void) >>> { >>> #ifdef CONFIG_KASAN >>> init_task.kasan_depth = 0; >>> - pr_info("KernelAddressSanitizer initialized\n"); >>> + kasan_init_generic(); >>> #endif >>> } >>> >>> diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c >>> index 0539efd0d21..998b6010d6d 100644 >>> --- a/arch/x86/mm/kasan_init_64.c >>> +++ b/arch/x86/mm/kasan_init_64.c >>> @@ -451,5 +451,5 @@ void __init kasan_init(void) >>> __flush_tlb_all(); >>> >>> init_task.kasan_depth = 0; >>> - pr_info("KernelAddressSanitizer initialized\n"); >>> + kasan_init_generic(); >>> } >>> diff --git a/arch/xtensa/mm/kasan_init.c b/arch/xtensa/mm/kasan_init.c >>> index f39c4d83173..0524b9ed5e6 100644 >>> --- a/arch/xtensa/mm/kasan_init.c >>> +++ b/arch/xtensa/mm/kasan_init.c >>> @@ -94,5 +94,5 @@ void __init kasan_init(void) >>> >>> /* At this point kasan is fully initialized. Enable error messages. */ >>> current->kasan_depth = 0; >>> - pr_info("KernelAddressSanitizer initialized\n"); >>> + kasan_init_generic(); >>> } > _______________________________________________ > linux-riscv mailing list > linux-riscv@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-08-10 7:32 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-08-07 19:40 [PATCH v5 0/2] kasan: unify kasan_enabled() and remove arch-specific implementations Sabyrzhan Tasbolatov 2025-08-07 19:40 ` [PATCH v5 1/2] kasan: introduce ARCH_DEFER_KASAN and unify static key across modes Sabyrzhan Tasbolatov 2025-08-08 5:03 ` Christophe Leroy 2025-08-08 7:26 ` Sabyrzhan Tasbolatov 2025-08-08 7:33 ` Christophe Leroy 2025-08-08 15:33 ` Sabyrzhan Tasbolatov 2025-08-08 17:03 ` Christophe Leroy 2025-08-10 7:20 ` Sabyrzhan Tasbolatov 2025-08-10 7:32 ` Sabyrzhan Tasbolatov 2025-08-07 19:40 ` [PATCH v5 2/2] kasan: call kasan_init_generic in kasan_init Sabyrzhan Tasbolatov 2025-08-08 5:07 ` Christophe Leroy 2025-08-08 6:44 ` Sabyrzhan Tasbolatov 2025-08-08 7:21 ` Alexandre Ghiti
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).