Re: [PATCH v10 13/13] x86/kasan: Make software tag-based kasan available

Dave Hansen
2026-02-23T20:52:02Z

...
> diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
> index a6cf05d51bd8..7e2e4c5fa661 100644
> --- a/Documentation/arch/x86/x86_64/mm.rst
> +++ b/Documentation/arch/x86/x86_64/mm.rst
> @@ -60,7 +60,8 @@ Complete virtual memory map with 4-level page tables
> ffffe90000000000 | -23 TB | ffffe9ffffffffff | 1 TB | ... unused hole
> ffffea0000000000 | -22 TB | ffffeaffffffffff | 1 TB | virtual memory map (vmemmap_base)
> ffffeb0000000000 | -21 TB | ffffebffffffffff | 1 TB | ... unused hole
> - ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory
> + ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory (generic mode)
> + fffff40000000000 | -8 TB | fffffbffffffffff | 8 TB | KASAN shadow memory (software tag-based mode)
> __________________|____________|__________________|_________|____________________________________________________________
> |
> | Identical layout to the 56-bit one from here on:
> @@ -130,7 +131,8 @@ Complete virtual memory map with 5-level page tables
> ffd2000000000000 | -11.5 PB | ffd3ffffffffffff | 0.5 PB | ... unused hole
> ffd4000000000000 | -11 PB | ffd5ffffffffffff | 0.5 PB | virtual memory map (vmemmap_base)
> ffd6000000000000 | -10.5 PB | ffdeffffffffffff | 2.25 PB | ... unused hole
> - ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory
> + ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory (generic mode)
> + ffeffc0000000000 | -6 PB | fffffbffffffffff | 4 PB | KASAN shadow memory (software tag-based mode)
> __________________|____________|__________________|_________|____________________________________________________________

I think the idea of these is that you can run through, find *one* range
and know what a given address maps to. This adds overlapping ranges.
Could you make it clear that part of the area is "generic mode" only and
the other part is for generic mode and for "software tag-based mode"?

> @@ -176,5 +178,9 @@ Be very careful vs. KASLR when changing anything here. The KASLR address
> range must not overlap with anything except the KASAN shadow area, which is
> correct as KASAN disables KASLR.
>
> +The 'KASAN shadow memory (generic mode)/(software tag-based mode)' ranges are
> +mutually exclusive and depend on which KASAN setting is chosen:
> +CONFIG_KASAN_GENERIC or CONFIG_KASAN_SW_TAGS.
> +
> For both 4- and 5-level layouts, the KSTACK_ERASE_POISON value in the last 2MB
> hole: ffffffffffff4111
> diff --git a/Documentation/dev-tools/kasan.rst b/Documentation/dev-tools/kasan.rst
> index 64dbf8b308bd..03b508ebe673 100644
> --- a/Documentation/dev-tools/kasan.rst
> +++ b/Documentation/dev-tools/kasan.rst
> @@ -22,8 +22,8 @@ architectures, but it has significant performance and memory overheads.
>
> Software Tag-Based KASAN or SW_TAGS KASAN, enabled with CONFIG_KASAN_SW_TAGS,
> can be used for both debugging and dogfood testing, similar to userspace HWASan.
> -This mode is only supported for arm64, but its moderate memory overhead allows
> -using it for testing on memory-restricted devices with real workloads.
> +This mode is only supported for arm64 and x86, but its moderate memory overhead
> +allows using it for testing on memory-restricted devices with real workloads.
>
> Hardware Tag-Based KASAN or HW_TAGS KASAN, enabled with CONFIG_KASAN_HW_TAGS,
> is the mode intended to be used as an in-field memory bug detector or as a
> @@ -351,10 +351,12 @@ Software Tag-Based KASAN
> Software Tag-Based KASAN uses a software memory tagging approach to checking
> access validity. It is currently only implemented for the arm64 architecture.
>
> -Software Tag-Based KASAN uses the Top Byte Ignore (TBI) feature of arm64 CPUs
> -to store a pointer tag in the top byte of kernel pointers. It uses shadow memory
> -to store memory tags associated with each 16-byte memory cell (therefore, it
> -dedicates 1/16th of the kernel memory for shadow memory).
> +Software Tag-Based KASAN uses the Top Byte Ignore (TBI) feature of arm64 CPUs to
> +store a pointer tag in the top byte of kernel pointers. Analogously to TBI on
> +x86 CPUs Linear Address Masking (LAM) feature is used and the pointer tag is
> +stored in four bits of the kernel pointer's top byte. Software Tag-Based mode
> +uses shadow memory to store memory tags associated with each 16-byte memory cell
> +(therefore, it dedicates 1/16th of the kernel memory for shadow memory).

This is going to get really cumbersome really fast if all the
architectures doing this add their marketing terms in here.

Software Tag-Based KASAN uses the hardware CPU features* to
repurpose space inside kernel pointers to store pointer tags.
...

and then _elsewhere_ you can describe the two implementations.

> On each memory allocation, Software Tag-Based KASAN generates a random tag, tags
> the allocated memory with this tag, and embeds the same tag into the returned
> @@ -370,12 +372,14 @@ Software Tag-Based KASAN also has two instrumentation modes (outline, which
> emits callbacks to check memory accesses; and inline, which performs the shadow
> memory checks inline). With outline instrumentation mode, a bug report is
> printed from the function that performs the access check. With inline
> -instrumentation, a ``brk`` instruction is emitted by the compiler, and a
> -dedicated ``brk`` handler is used to print bug reports.
> -
> -Software Tag-Based KASAN uses 0xFF as a match-all pointer tag (accesses through
> -pointers with the 0xFF pointer tag are not checked). The value 0xFE is currently
> -reserved to tag freed memory regions.
> +instrumentation, arm64's implementation uses the ``brk`` instruction emitted by
> +the compiler, and a dedicated ``brk`` handler is used to print bug reports. On
> +x86 inline mode doesn't work yet due to missing compiler support.
> +
> +For arm64 Software Tag-Based KASAN uses 0xFF as a match-all pointer tag
> +(accesses through pointers with the 0xFF pointer tag are not checked). The value
> +0xFE is currently reserved to tag freed memory regions. On x86 the same tags
> +take on 0xF and 0xE respectively.

I think this would be more clear with a table or list of features and
supported architectures.

> Hardware Tag-Based KASAN
> ~~~~~~~~~~~~~~~~~~~~~~~~
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 80527299f859..877668cd5deb 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -67,6 +67,7 @@ config X86
> select ARCH_CLOCKSOURCE_INIT
> select ARCH_CONFIGURES_CPU_MITIGATIONS
> select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
> + select ARCH_DISABLE_KASAN_INLINE if X86_64 && KASAN_SW_TAGS
> select ARCH_ENABLE_HUGEPAGE_MIGRATION if X86_64 && HUGETLB_PAGE && MIGRATION
> select ARCH_ENABLE_MEMORY_HOTPLUG if X86_64
> select ARCH_ENABLE_MEMORY_HOTREMOVE if MEMORY_HOTPLUG
> @@ -196,6 +197,8 @@ config X86
> select HAVE_ARCH_JUMP_LABEL_RELATIVE
> select HAVE_ARCH_KASAN if X86_64
> select HAVE_ARCH_KASAN_VMALLOC if X86_64
> + select HAVE_ARCH_KASAN_SW_TAGS if ADDRESS_MASKING && CC_IS_CLANG
> + select ARCH_NEEDS_DEFER_KASAN if ADDRESS_MASKING
> select HAVE_ARCH_KFENCE
> select HAVE_ARCH_KMSAN if X86_64
> select HAVE_ARCH_KGDB
> @@ -410,6 +413,7 @@ config AUDIT_ARCH
> config KASAN_SHADOW_OFFSET
> hex
> depends on KASAN
> + default 0xeffffc0000000000 if KASAN_SW_TAGS
> default 0xdffffc0000000000

Please separate this from the documentation.

> config HAVE_INTEL_TXT
> diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
> index fd855e32c9b9..ba70036c2abd 100644
> --- a/arch/x86/boot/compressed/misc.h
> +++ b/arch/x86/boot/compressed/misc.h
> @@ -13,6 +13,7 @@
> #undef CONFIG_PARAVIRT_SPINLOCKS
> #undef CONFIG_KASAN
> #undef CONFIG_KASAN_GENERIC
> +#undef CONFIG_KASAN_SW_TAGS
>
> #define __NO_FORTIFY
>
> diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
> index 90c18e30848f..53ab7de16517 100644
> --- a/arch/x86/include/asm/kasan.h
> +++ b/arch/x86/include/asm/kasan.h
> @@ -6,7 +6,12 @@
> #include <linux/kasan-tags.h>
> #include <linux/types.h>
> #define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
> +
> +#ifdef CONFIG_KASAN_SW_TAGS
> +#define KASAN_SHADOW_SCALE_SHIFT 4
> +#else
> #define KASAN_SHADOW_SCALE_SHIFT 3
> +#endif
>
> /*
> * Compiler uses shadow offset assuming that addresses start
> diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
> index 7f5c11328ec1..8cbb8ec32061 100644
> --- a/arch/x86/mm/kasan_init_64.c
> +++ b/arch/x86/mm/kasan_init_64.c
> @@ -465,4 +465,9 @@ void __init kasan_init(void)
>
> init_task.kasan_depth = 0;
> kasan_init_generic();
> +
> + if (cpu_feature_enabled(X86_FEATURE_LAM))
> + kasan_init_sw_tags();
> + else
> + pr_info("KernelAddressSanitizer not initialized (sw-tags): hardware doesn't support LAM\n");
> }
> diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
> index a4bb610a7a6f..d13ea8da7bfd 100644
> --- a/lib/Kconfig.kasan
> +++ b/lib/Kconfig.kasan
> @@ -112,7 +112,8 @@ config KASAN_SW_TAGS
>
> Requires GCC 11+ or Clang.
>
> - Supported only on arm64 CPUs and relies on Top Byte Ignore.
> + Supported on arm64 CPUs that support Top Byte Ignore and on x86 CPUs
> + that support Linear Address Masking.

Can this read more like:

Supported on:
arm64: CPUs with Top Byte Ignore
x86: CPUs with Linear Address Masking.

please?