* [PATCH v11 01/15] kasan: sw_tags: Use arithmetic shift for shadow computation
2026-03-10 17:51 [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
@ 2026-03-10 17:53 ` Maciej Wieczor-Retman
2026-03-10 17:55 ` [PATCH v11 15/15] docs: Update KASAN and x86 memory map documentations Maciej Wieczor-Retman
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-10 17:53 UTC (permalink / raw)
To: akpm, Catalin Marinas, Will Deacon, Jonathan Corbet, Shuah Khan,
Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
Dmitry Vyukov, Vincenzo Frascino, Jan Kiszka, Kieran Bingham,
Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt
Cc: m.wieczorretman, Samuel Holland, Maciej Wieczor-Retman,
linux-arm-kernel, linux-doc, linux-kernel, kasan-dev, workflows,
linux-mm, llvm
From: Samuel Holland <samuel.holland@sifive.com>
Currently, kasan_mem_to_shadow() uses a logical right shift, which turns
canonical kernel addresses into non-canonical addresses by clearing the
high KASAN_SHADOW_SCALE_SHIFT bits. The value of KASAN_SHADOW_OFFSET is
then chosen so that the addition results in a canonical address for the
shadow memory.
For KASAN_GENERIC, this shift/add combination is ABI with the compiler,
because KASAN_SHADOW_OFFSET is used in compiler-generated inline tag
checks[1], which must only attempt to dereference canonical addresses.
However, for KASAN_SW_TAGS there is some freedom to change the algorithm
without breaking the ABI. Because TBI is enabled for kernel addresses,
the top bits of shadow memory addresses computed during tag checks are
irrelevant, and so likewise are the top bits of KASAN_SHADOW_OFFSET.
This is demonstrated by the fact that LLVM uses a logical right shift in
the tag check fast path[2] but a sbfx (signed bitfield extract)
instruction in the slow path[3] without causing any issues.
Use an arithmetic shift in kasan_mem_to_shadow() as it provides a number
of benefits:
1) The memory layout doesn't change but is easier to understand.
KASAN_SHADOW_OFFSET becomes a canonical memory address, and the shifted
pointer becomes a negative offset, so KASAN_SHADOW_OFFSET ==
KASAN_SHADOW_END regardless of the shift amount or the size of the
virtual address space.
2) KASAN_SHADOW_OFFSET becomes a simpler constant, requiring only one
instruction to load instead of two. Since it must be loaded in each
function with a tag check, this decreases kernel text size by 0.5%.
3) This shift and the sign extension from kasan_reset_tag() can be
combined into a single sbfx instruction. When this same algorithm change
is applied to the compiler, it removes an instruction from each inline
tag check, further reducing kernel text size by an additional 4.6%.
These benefits extend to other architectures as well. On RISC-V, where
the baseline ISA does not shifted addition or have an equivalent to the
sbfx instruction, loading KASAN_SHADOW_OFFSET is reduced from 3 to 2
instructions, and kasan_mem_to_shadow(kasan_reset_tag(addr)) similarly
combines two consecutive right shifts.
Link: https://github.com/llvm/llvm-project/blob/llvmorg-20-init/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp#L1316 [1]
Link: https://github.com/llvm/llvm-project/blob/llvmorg-20-init/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp#L895 [2]
Link: https://github.com/llvm/llvm-project/blob/llvmorg-20-init/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp#L669 [3]
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Co-developed-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v11: (Maciej)
- Remove the arch_kasan_non_canonical_hook() scheme in favor of Andrey
Ryabinin's much nicer simple implementation.
Changelog v10: (Maciej)
- Update the Documentation/dev-tools/kasan.rst file with the changed
kasan_mem_to_shadow().
Changelog v9: (Maciej)
- Take out the arm64 related code from mm/kasan/report.c and put it in
the arch specific directory in a new file so the kasan_mem_to_shadow()
function can be included.
- Reset addr tag bits in arm64's arch_kasan_non_canonical_hook() so the
inline mode can also work with that function (Andrey Ryabinin).
- Fix incorrect number of zeros in a comment in mm/kasan/report.c.
- Remove Catalin's acked-by since changes were made.
Changelog v7: (Maciej)
- Change UL to ULL in report.c to fix some compilation warnings.
Changelog v6: (Maciej)
- Add Catalin's acked-by.
- Move x86 gdb snippet here from the last patch.
Changelog v5: (Maciej)
- (u64) -> (unsigned long) in report.c
Changelog v4: (Maciej)
- Revert x86 to signed mem_to_shadow mapping.
- Remove last two paragraphs since they were just poorer duplication of
the comments in kasan_non_canonical_hook().
Changelog v3: (Maciej)
- Fix scripts/gdb/linux/kasan.py so the new signed mem_to_shadow() is
reflected there.
- Fix Documentation/arch/arm64/kasan-offsets.sh to take new offsets into
account.
- Made changes to the kasan_non_canonical_hook() according to upstream
discussion. Settled on overflow on both ranges and separate checks for
x86 and arm.
Changelog v2: (Maciej)
- Correct address range that's checked in kasan_non_canonical_hook().
Adjust the comment inside.
- Remove part of comment from arch/arm64/include/asm/memory.h.
- Append patch message paragraph about the overflow in
kasan_non_canonical_hook().
Documentation/arch/arm64/kasan-offsets.sh | 8 ++++++--
Documentation/dev-tools/kasan.rst | 18 ++++++++++++------
arch/arm64/Kconfig | 10 +++++-----
arch/arm64/include/asm/memory.h | 14 +++++++++++++-
arch/arm64/mm/kasan_init.c | 7 +++++--
include/linux/kasan.h | 10 ++++++++--
mm/kasan/report.c | 16 ++++++++++++----
scripts/gdb/linux/kasan.py | 5 ++++-
scripts/gdb/linux/mm.py | 5 +++--
9 files changed, 68 insertions(+), 25 deletions(-)
diff --git a/Documentation/arch/arm64/kasan-offsets.sh b/Documentation/arch/arm64/kasan-offsets.sh
index 2dc5f9e18039..ce777c7c7804 100644
--- a/Documentation/arch/arm64/kasan-offsets.sh
+++ b/Documentation/arch/arm64/kasan-offsets.sh
@@ -5,8 +5,12 @@
print_kasan_offset () {
printf "%02d\t" $1
- printf "0x%08x00000000\n" $(( (0xffffffff & (-1 << ($1 - 1 - 32))) \
- - (1 << (64 - 32 - $2)) ))
+ if [[ $2 -ne 4 ]] then
+ printf "0x%08x00000000\n" $(( (0xffffffff & (-1 << ($1 - 1 - 32))) \
+ - (1 << (64 - 32 - $2)) ))
+ else
+ printf "0x%08x00000000\n" $(( (0xffffffff & (-1 << ($1 - 1 - 32))) ))
+ fi
}
echo KASAN_SHADOW_SCALE_SHIFT = 3
diff --git a/Documentation/dev-tools/kasan.rst b/Documentation/dev-tools/kasan.rst
index 4968b2aa60c8..b11c1be8dff4 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -315,13 +315,19 @@ translate a memory address to its corresponding shadow address.
Here is the function which translates an address to its corresponding shadow
address::
- static inline void *kasan_mem_to_shadow(const void *addr)
- {
- return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
- + KASAN_SHADOW_OFFSET;
- }
+ static inline void *kasan_mem_to_shadow(const void *addr)
+ {
+ void *scaled;
-where ``KASAN_SHADOW_SCALE_SHIFT = 3``.
+ if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+ scaled = (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT);
+ else
+ scaled = (void *)((long)addr >> KASAN_SHADOW_SCALE_SHIFT);
+
+ return KASAN_SHADOW_OFFSET + scaled;
+ }
+
+where for Generic KASAN ``KASAN_SHADOW_SCALE_SHIFT = 3``.
Compile-time instrumentation is used to insert memory access checks. Compiler
inserts function calls (``__asan_load*(addr)``, ``__asan_store*(addr)``) before
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 38dba5f7e4d2..4de7e721f32e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -435,11 +435,11 @@ config KASAN_SHADOW_OFFSET
default 0xdffffe0000000000 if ARM64_VA_BITS_42 && !KASAN_SW_TAGS
default 0xdfffffc000000000 if ARM64_VA_BITS_39 && !KASAN_SW_TAGS
default 0xdffffff800000000 if ARM64_VA_BITS_36 && !KASAN_SW_TAGS
- default 0xefff800000000000 if (ARM64_VA_BITS_48 || (ARM64_VA_BITS_52 && !ARM64_16K_PAGES)) && KASAN_SW_TAGS
- default 0xefffc00000000000 if (ARM64_VA_BITS_47 || ARM64_VA_BITS_52) && ARM64_16K_PAGES && KASAN_SW_TAGS
- default 0xeffffe0000000000 if ARM64_VA_BITS_42 && KASAN_SW_TAGS
- default 0xefffffc000000000 if ARM64_VA_BITS_39 && KASAN_SW_TAGS
- default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
+ default 0xffff800000000000 if (ARM64_VA_BITS_48 || (ARM64_VA_BITS_52 && !ARM64_16K_PAGES)) && KASAN_SW_TAGS
+ default 0xffffc00000000000 if (ARM64_VA_BITS_47 || ARM64_VA_BITS_52) && ARM64_16K_PAGES && KASAN_SW_TAGS
+ default 0xfffffe0000000000 if ARM64_VA_BITS_42 && KASAN_SW_TAGS
+ default 0xffffffc000000000 if ARM64_VA_BITS_39 && KASAN_SW_TAGS
+ default 0xfffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
default 0xffffffffffffffff
config UNWIND_TABLES
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index a2b7a33966ff..875c0bd0d85a 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -89,7 +89,15 @@
*
* KASAN_SHADOW_END is defined first as the shadow address that corresponds to
* the upper bound of possible virtual kernel memory addresses UL(1) << 64
- * according to the mapping formula.
+ * according to the mapping formula. For Generic KASAN, the address in the
+ * mapping formula is treated as unsigned (part of the compiler's ABI), so the
+ * end of the shadow memory region is at a large positive offset from
+ * KASAN_SHADOW_OFFSET. For Software Tag-Based KASAN, the address in the
+ * formula is treated as signed. Since all kernel addresses are negative, they
+ * map to shadow memory below KASAN_SHADOW_OFFSET, making KASAN_SHADOW_OFFSET
+ * itself the end of the shadow memory region. (User pointers are positive and
+ * would map to shadow memory above KASAN_SHADOW_OFFSET, but shadow memory is
+ * not allocated for them.)
*
* KASAN_SHADOW_START is defined second based on KASAN_SHADOW_END. The shadow
* memory start must map to the lowest possible kernel virtual memory address
@@ -100,7 +108,11 @@
*/
#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
+#ifdef CONFIG_KASAN_GENERIC
#define KASAN_SHADOW_END ((UL(1) << (64 - KASAN_SHADOW_SCALE_SHIFT)) + KASAN_SHADOW_OFFSET)
+#else
+#define KASAN_SHADOW_END KASAN_SHADOW_OFFSET
+#endif
#define _KASAN_SHADOW_START(va) (KASAN_SHADOW_END - (UL(1) << ((va) - KASAN_SHADOW_SCALE_SHIFT)))
#define KASAN_SHADOW_START _KASAN_SHADOW_START(vabits_actual)
#define PAGE_END KASAN_SHADOW_START
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index abeb81bf6ebd..937f6eb8115b 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -198,8 +198,11 @@ static bool __init root_level_aligned(u64 addr)
/* The early shadow maps everything to a single page of zeroes */
asmlinkage void __init kasan_early_init(void)
{
- BUILD_BUG_ON(KASAN_SHADOW_OFFSET !=
- KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT)));
+ if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+ BUILD_BUG_ON(KASAN_SHADOW_OFFSET !=
+ KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT)));
+ else
+ BUILD_BUG_ON(KASAN_SHADOW_OFFSET != KASAN_SHADOW_END);
BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS), SHADOW_ALIGN));
BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS_MIN), SHADOW_ALIGN));
BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, SHADOW_ALIGN));
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 338a1921a50a..81c83dcfcebe 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -62,8 +62,14 @@ int kasan_populate_early_shadow(const void *shadow_start,
#ifndef kasan_mem_to_shadow
static inline void *kasan_mem_to_shadow(const void *addr)
{
- return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
- + KASAN_SHADOW_OFFSET;
+ void *scaled;
+
+ if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+ scaled = (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT);
+ else
+ scaled = (void *)((long)addr >> KASAN_SHADOW_SCALE_SHIFT);
+
+ return KASAN_SHADOW_OFFSET + scaled;
}
#endif
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index e804b1e1f886..1e4521b5ef14 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -640,12 +640,20 @@ void kasan_non_canonical_hook(unsigned long addr)
{
unsigned long orig_addr, user_orig_addr;
const char *bug_type;
+ void *tagged_null = set_tag(NULL, KASAN_TAG_KERNEL);
+ void *tagged_addr = set_tag((void *)addr, KASAN_TAG_KERNEL);
/*
- * All addresses that came as a result of the memory-to-shadow mapping
- * (even for bogus pointers) must be >= KASAN_SHADOW_OFFSET.
+ * Filter out addresses that cannot be shadow memory accesses generated
+ * by the compiler.
+ *
+ * In SW_TAGS mode, when computing a shadow address, the compiler always
+ * sets the kernel tag (some top bits) on the pointer *before* computing
+ * the memory-to-shadow mapping. As a result, valid shadow addresses
+ * are derived from tagged kernel pointers.
*/
- if (addr < KASAN_SHADOW_OFFSET)
+ if (tagged_addr < kasan_mem_to_shadow(tagged_null) ||
+ tagged_addr > kasan_mem_to_shadow((void *)(~0ULL)))
return;
orig_addr = (unsigned long)kasan_shadow_to_mem((void *)addr);
@@ -670,7 +678,7 @@ void kasan_non_canonical_hook(unsigned long addr)
} else if (user_orig_addr < TASK_SIZE) {
bug_type = "probably user-memory-access";
orig_addr = user_orig_addr;
- } else if (addr_in_shadow((void *)addr))
+ } else if (addr_in_shadow(tagged_addr))
bug_type = "probably wild-memory-access";
else
bug_type = "maybe wild-memory-access";
diff --git a/scripts/gdb/linux/kasan.py b/scripts/gdb/linux/kasan.py
index 56730b3fde0b..4b86202b155f 100644
--- a/scripts/gdb/linux/kasan.py
+++ b/scripts/gdb/linux/kasan.py
@@ -7,7 +7,8 @@
#
import gdb
-from linux import constants, mm
+from linux import constants, utils, mm
+from ctypes import c_int64 as s64
def help():
t = """Usage: lx-kasan_mem_to_shadow [Hex memory addr]
@@ -39,6 +40,8 @@ class KasanMemToShadow(gdb.Command):
else:
help()
def kasan_mem_to_shadow(self, addr):
+ if constants.CONFIG_KASAN_SW_TAGS and not utils.is_target_arch('x86'):
+ addr = s64(addr)
return (addr >> self.p_ops.KASAN_SHADOW_SCALE_SHIFT) + self.p_ops.KASAN_SHADOW_OFFSET
KasanMemToShadow()
diff --git a/scripts/gdb/linux/mm.py b/scripts/gdb/linux/mm.py
index d78908f6664d..d4ab341d89c5 100644
--- a/scripts/gdb/linux/mm.py
+++ b/scripts/gdb/linux/mm.py
@@ -281,12 +281,13 @@ class aarch64_page_ops():
self.KERNEL_END = gdb.parse_and_eval("_end")
if constants.LX_CONFIG_KASAN_GENERIC or constants.LX_CONFIG_KASAN_SW_TAGS:
+ self.KASAN_SHADOW_OFFSET = constants.LX_CONFIG_KASAN_SHADOW_OFFSET
if constants.LX_CONFIG_KASAN_GENERIC:
self.KASAN_SHADOW_SCALE_SHIFT = 3
+ self.KASAN_SHADOW_END = (1 << (64 - self.KASAN_SHADOW_SCALE_SHIFT)) + self.KASAN_SHADOW_OFFSET
else:
self.KASAN_SHADOW_SCALE_SHIFT = 4
- self.KASAN_SHADOW_OFFSET = constants.LX_CONFIG_KASAN_SHADOW_OFFSET
- self.KASAN_SHADOW_END = (1 << (64 - self.KASAN_SHADOW_SCALE_SHIFT)) + self.KASAN_SHADOW_OFFSET
+ self.KASAN_SHADOW_END = self.KASAN_SHADOW_OFFSET
self.PAGE_END = self.KASAN_SHADOW_END - (1 << (self.vabits_actual - self.KASAN_SHADOW_SCALE_SHIFT))
else:
self.PAGE_END = self._PAGE_END(self.VA_BITS_MIN)
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v11 15/15] docs: Update KASAN and x86 memory map documentations
2026-03-10 17:51 [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
2026-03-10 17:53 ` [PATCH v11 01/15] kasan: sw_tags: Use arithmetic shift for shadow computation Maciej Wieczor-Retman
@ 2026-03-10 17:55 ` Maciej Wieczor-Retman
2026-03-10 18:24 ` [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86 Andrew Morton
2026-03-10 19:00 ` Peter Zijlstra
3 siblings, 0 replies; 9+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-10 17:55 UTC (permalink / raw)
To: akpm, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Jonathan Corbet, Shuah Khan, Andrey Ryabinin,
Alexander Potapenko, Andrey Konovalov, Dmitry Vyukov,
Vincenzo Frascino
Cc: m.wieczorretman, Maciej Wieczor-Retman, linux-kernel, linux-doc,
kasan-dev, workflows
From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Update the documentation concerning changes to x86's memory address
space and new architecture addition to KASAN's software tag-based mode.
Redo paragraphs in KASAN's documentation on hardware and software
implementation details to allow better extensibility.
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v11:
- Split off the documentation portion of v10's patch 13.
- Apply Dave's suggestions to reformat the footer explaining alternate
ranges for KASAN shadow memory, put arch hardware implementation in a
separate paragraph and make a table to hold various implementation
details.
Documentation/arch/x86/x86_64/mm.rst | 21 +++++++++-
Documentation/dev-tools/kasan.rst | 61 ++++++++++++++++++++--------
2 files changed, 62 insertions(+), 20 deletions(-)
diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
index a6cf05d51bd8..3c78ab1afd8d 100644
--- a/Documentation/arch/x86/x86_64/mm.rst
+++ b/Documentation/arch/x86/x86_64/mm.rst
@@ -60,7 +60,7 @@ 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[1]
__________________|____________|__________________|_________|____________________________________________________________
|
| Identical layout to the 56-bit one from here on:
@@ -130,7 +130,7 @@ 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[1]
__________________|____________|__________________|_________|____________________________________________________________
|
| Identical layout to the 47-bit one from here on:
@@ -178,3 +178,20 @@ correct as KASAN disables KASLR.
For both 4- and 5-level layouts, the KSTACK_ERASE_POISON value in the last 2MB
hole: ffffffffffff4111
+
+1. The range is different based on what KASAN mode is used and what paging level
+ is used:
+
+::
+
+ ============================================================================================================
+ Start addr | Offset | End addr | Size | VM area description
+ ============================================================================================================
+ | | | | 4-level paging:
+ ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory (generic mode)
+ fffff40000000000 | -8 TB | fffffbffffffffff | 8 TB | KASAN shadow memory (software tag-based mode)
+ __________________|____________|__________________|_________|_______________________________________________
+ | | | | 5-level paging:
+ 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)
+ __________________|____________|__________________|_________|_______________________________________________
diff --git a/Documentation/dev-tools/kasan.rst b/Documentation/dev-tools/kasan.rst
index b11c1be8dff4..d42d80e9fcf1 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
@@ -346,16 +346,21 @@ 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).
-
-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
-pointer.
+access validity. It is currently only implemented for the arm64 and x86
+architectures. To function, special hardware CPU features* are needed for
+repurposing space inside the kernel pointers to store pointer tags.
+
+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). 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 pointer.
+
+Two special tag values can be distinguished. A match-all pointer tag (otherwise
+called the 'kernel tag' because it's supposed to be equal to the value normally
+present in the same bits of the linear address when KASAN is disabled) -
+accesses through such pointers are not checked. Another value is also reserved
+to tag freed memory regions.
Software Tag-Based KASAN uses compile-time instrumentation to insert checks
before each memory access. These checks make sure that the tag of the memory
@@ -367,12 +372,32 @@ 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, the compiler emits a specific arch-dependent instruction with a
+dedicated handler to print bug reports.
+
+Architecture specific details:
+
+::
+
+ +-----------------------+--------+---------------------+
+ | detail \ architecture | arm64 | x86 |
+ +=======================+========+=====================+
+ | Hardware feature | TBI | LAM |
+ +-----------------------+--------+---------------------+
+ | Kernel tag | 0xFF | 0x0F |
+ +-----------------------+--------+---------------------+
+ | Freed memory tag | 0xFE | 0x0E |
+ +-----------------------+--------+---------------------+
+ | Tag width | 8 bits | 4 bits |
+ +-----------------------+--------+---------------------+
+ | Inline instruction | brk | no compiler support |
+ +-----------------------+--------+---------------------+
+
+* Different architectures implement different hardware features to mask and
+ repurpose linear address bits. arm64 utilizes Top Byte Ignore (TBI) to mask
+ out and allow storing tags in the top byte of the pointer. x86 uses Linear
+ Address Masking (LAM) to store tags in the four bits of the kernel pointer's
+ top byte.
Hardware Tag-Based KASAN
~~~~~~~~~~~~~~~~~~~~~~~~
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86
2026-03-10 17:51 [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
2026-03-10 17:53 ` [PATCH v11 01/15] kasan: sw_tags: Use arithmetic shift for shadow computation Maciej Wieczor-Retman
2026-03-10 17:55 ` [PATCH v11 15/15] docs: Update KASAN and x86 memory map documentations Maciej Wieczor-Retman
@ 2026-03-10 18:24 ` Andrew Morton
2026-03-10 19:17 ` Maciej Wieczor-Retman
2026-03-10 19:00 ` Peter Zijlstra
3 siblings, 1 reply; 9+ messages in thread
From: Andrew Morton @ 2026-03-10 18:24 UTC (permalink / raw)
To: Maciej Wieczor-Retman
Cc: urezki, ryan.roberts, kevin.brodsky, samuel.holland, dave.hansen,
jeremy.linton, peterz, weixugc, ljs, ryabinin.a.a, rppt, bp, luto,
jan.kiszka, mingo, david, mhocko, andreas, kas, Liam.Howlett,
morbo, thuth, catalin.marinas, ankur.a.arora, kbingham,
nick.desaulniers+lkml, andreyknvl, dvyukov, corbet, leitao, hpa,
tglx, yuanchu, ardb, vincenzo.frascino, tabba, joey.gouly, nsc,
will, yeoreum.yun, nathan, maciej.wieczor-retman, skhan,
axelrasmussen, osandov, surenb, justinstitt, kees, vbabka,
hsj0512, trintaeoitogc, jackmanb, maz, glider, linux-doc, x86,
linux-kernel, kasan-dev, workflows, llvm, linux-arm-kernel,
linux-kbuild, linux-mm
On Tue, 10 Mar 2026 17:51:19 +0000 Maciej Wieczor-Retman <m.wieczorretman@pm.me> wrote:
>
> [1] Currently inline mode doesn't work on x86 due to things missing in
> the compiler. I have written a patch for clang that seems to fix the
> inline mode and I was able to boot and check that all patches regarding
> the inline mode work as expected. My hope is to post the patch to LLVM
> once this series is completed, and then make inline mode available in
> the kernel config.
>
> [2] While I was able to boot the inline tag-based kernel with my
> compiler changes in a simulated environment, due to toolchain
> difficulties I couldn't get it to boot on the machine I had access to.
> Also boot time results from the simulation seem too good to be true, and
> they're much too worse for the generic case to be believable. Therefore
> I'm posting only results from the physical server platform.
>
> ======= Compilation
> Clang was used to compile the series (make LLVM=1) since gcc doesn't
> seem to have support for KASAN tag-based compiler instrumentation on
> x86. Patchset does seem to compile with gcc without an issue but doesn't
> boot afterwards.
So LLVM works partially and gcc doesn't work at all?
Do we know which compiler people are using? Google tells me that
Android, ChromeOS, and OpenMandriva use LLVM. That's pretty thin.
This is all rather problematic and it isn't clear (to me) how to
proceed at this time. Do we have any projections on when all this will
be fixed up?
> The series is based on mm-new.
I actually carry kexec patches in the mm-nonmm-[un]stable branches.
But the series applies OK anyway.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86
2026-03-10 18:24 ` [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86 Andrew Morton
@ 2026-03-10 19:17 ` Maciej Wieczor-Retman
0 siblings, 0 replies; 9+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-10 19:17 UTC (permalink / raw)
To: Andrew Morton
Cc: urezki, ryan.roberts, kevin.brodsky, samuel.holland, dave.hansen,
jeremy.linton, peterz, weixugc, ljs, ryabinin.a.a, rppt, bp, luto,
jan.kiszka, mingo, david, mhocko, andreas, kas, Liam.Howlett,
morbo, thuth, catalin.marinas, ankur.a.arora, kbingham,
nick.desaulniers+lkml, andreyknvl, dvyukov, corbet, leitao, hpa,
tglx, yuanchu, ardb, vincenzo.frascino, tabba, joey.gouly, nsc,
will, yeoreum.yun, nathan, maciej.wieczor-retman, skhan,
axelrasmussen, osandov, surenb, justinstitt, kees, vbabka,
hsj0512, trintaeoitogc, jackmanb, maz, glider, linux-doc, x86,
linux-kernel, kasan-dev, workflows, llvm, linux-arm-kernel,
linux-kbuild, linux-mm
On 2026-03-10 at 11:24:21 -0700, Andrew Morton wrote:
>On Tue, 10 Mar 2026 17:51:19 +0000 Maciej Wieczor-Retman <m.wieczorretman@pm.me> wrote:
>
>>
>> [1] Currently inline mode doesn't work on x86 due to things missing in
>> the compiler. I have written a patch for clang that seems to fix the
>> inline mode and I was able to boot and check that all patches regarding
>> the inline mode work as expected. My hope is to post the patch to LLVM
>> once this series is completed, and then make inline mode available in
>> the kernel config.
>>
>> [2] While I was able to boot the inline tag-based kernel with my
>> compiler changes in a simulated environment, due to toolchain
>> difficulties I couldn't get it to boot on the machine I had access to.
>> Also boot time results from the simulation seem too good to be true, and
>> they're much too worse for the generic case to be believable. Therefore
>> I'm posting only results from the physical server platform.
>>
>> ======= Compilation
>> Clang was used to compile the series (make LLVM=1) since gcc doesn't
>> seem to have support for KASAN tag-based compiler instrumentation on
>> x86. Patchset does seem to compile with gcc without an issue but doesn't
>> boot afterwards.
>
>So LLVM works partially and gcc doesn't work at all?
The non-working options are disabled in Kconfig so right now only outline KASAN
with LLVM works fully.
>Do we know which compiler people are using? Google tells me that
>Android, ChromeOS, and OpenMandriva use LLVM. That's pretty thin.
I don't have any numbers on this matter, from working on this I only got that
there is much more KASAN traffic around clang. So I thought that most KASAN
users prefer LLVM.
>This is all rather problematic and it isn't clear (to me) how to
>proceed at this time. Do we have any projections on when all this will
>be fixed up?
My understanding is that there is something off in gcc support. I recall Andrey
Konovalov mentioning that gcc also doesn't work well with arm64's KASAN
tag-based mode. As for LLVM inline support I do know the codebase a bit so I got
some WIP patches there. But I wanted to see where this review process goes
before posting to LLVM.
>> The series is based on mm-new.
>
>I actually carry kexec patches in the mm-nonmm-[un]stable branches.
>But the series applies OK anyway.
Should I base this patchset on top of mm-nonmm-stable in the future? I was after
one patch by Andrey Ryabinin that was in mm-new and I needed to rebase on top of
it.
--
Kind regards
Maciej Wieczór-Retman
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86
2026-03-10 17:51 [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
` (2 preceding siblings ...)
2026-03-10 18:24 ` [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86 Andrew Morton
@ 2026-03-10 19:00 ` Peter Zijlstra
2026-03-10 19:30 ` Maciej Wieczor-Retman
3 siblings, 1 reply; 9+ messages in thread
From: Peter Zijlstra @ 2026-03-10 19:00 UTC (permalink / raw)
To: Maciej Wieczor-Retman
Cc: urezki, ryan.roberts, kevin.brodsky, samuel.holland, dave.hansen,
jeremy.linton, weixugc, ljs, ryabinin.a.a, rppt, bp, luto,
jan.kiszka, mingo, david, mhocko, akpm, andreas, kas,
Liam.Howlett, morbo, thuth, catalin.marinas, ankur.a.arora,
kbingham, nick.desaulniers+lkml, andreyknvl, dvyukov, corbet,
leitao, hpa, tglx, yuanchu, ardb, vincenzo.frascino, tabba,
joey.gouly, nsc, will, yeoreum.yun, nathan, maciej.wieczor-retman,
skhan, axelrasmussen, osandov, surenb, justinstitt, kees, vbabka,
hsj0512, trintaeoitogc, jackmanb, maz, glider, linux-doc, x86,
linux-kernel, kasan-dev, workflows, llvm, linux-arm-kernel,
linux-kbuild, linux-mm
On Tue, Mar 10, 2026 at 05:51:19PM +0000, Maciej Wieczor-Retman wrote:
> ======= Compilation
> Clang was used to compile the series (make LLVM=1) since gcc doesn't
> seem to have support for KASAN tag-based compiler instrumentation on
> x86. Patchset does seem to compile with gcc without an issue but doesn't
> boot afterwards.
Can you put all that under a specific CONFIG and make that depend on
CC_IS_CLANG?
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86
2026-03-10 19:00 ` Peter Zijlstra
@ 2026-03-10 19:30 ` Maciej Wieczor-Retman
2026-03-11 11:05 ` Peter Zijlstra
0 siblings, 1 reply; 9+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-10 19:30 UTC (permalink / raw)
To: Peter Zijlstra
Cc: urezki, ryan.roberts, kevin.brodsky, samuel.holland, dave.hansen,
jeremy.linton, weixugc, ljs, ryabinin.a.a, rppt, bp, luto,
jan.kiszka, mingo, david, mhocko, akpm, andreas, kas,
Liam.Howlett, morbo, thuth, catalin.marinas, ankur.a.arora,
kbingham, nick.desaulniers+lkml, andreyknvl, dvyukov, corbet,
leitao, hpa, tglx, yuanchu, ardb, vincenzo.frascino, tabba,
joey.gouly, nsc, will, yeoreum.yun, nathan, maciej.wieczor-retman,
skhan, axelrasmussen, osandov, surenb, justinstitt, kees, vbabka,
hsj0512, trintaeoitogc, jackmanb, maz, glider, linux-doc, x86,
linux-kernel, kasan-dev, workflows, llvm, linux-arm-kernel,
linux-kbuild, linux-mm
On 2026-03-10 at 20:00:22 +0100, Peter Zijlstra wrote:
>On Tue, Mar 10, 2026 at 05:51:19PM +0000, Maciej Wieczor-Retman wrote:
>
>> ======= Compilation
>> Clang was used to compile the series (make LLVM=1) since gcc doesn't
>> seem to have support for KASAN tag-based compiler instrumentation on
>> x86. Patchset does seem to compile with gcc without an issue but doesn't
>> boot afterwards.
>
>Can you put all that under a specific CONFIG and make that depend on
>CC_IS_CLANG?
I made HAVE_ARCH_KASAN_SW_TAGS depend on CC_IS_CLANG, and that controls all the
software tags stuff, like ARCH_DISABLE_KASAN_INLINE through KASAN_SW_TAGS.
And ARCH_NEEDS_DEFER_KASAN is for if KASAN is compiled but LAM is not available,
so that it gets disabled in runtime.
But sure, I suppose I can add a separate CONFIG with CC_IS_CLANG to these three
so the clang connection is more transparent.
--
Kind regards
Maciej Wieczór-Retman
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86
2026-03-10 19:30 ` Maciej Wieczor-Retman
@ 2026-03-11 11:05 ` Peter Zijlstra
2026-03-11 11:13 ` Maciej Wieczor-Retman
0 siblings, 1 reply; 9+ messages in thread
From: Peter Zijlstra @ 2026-03-11 11:05 UTC (permalink / raw)
To: Maciej Wieczor-Retman
Cc: urezki, ryan.roberts, kevin.brodsky, samuel.holland, dave.hansen,
jeremy.linton, weixugc, ljs, ryabinin.a.a, rppt, bp, luto,
jan.kiszka, mingo, david, mhocko, akpm, andreas, kas,
Liam.Howlett, morbo, thuth, catalin.marinas, ankur.a.arora,
kbingham, nick.desaulniers+lkml, andreyknvl, dvyukov, corbet,
leitao, hpa, tglx, yuanchu, ardb, vincenzo.frascino, tabba,
joey.gouly, nsc, will, yeoreum.yun, nathan, maciej.wieczor-retman,
skhan, axelrasmussen, osandov, surenb, justinstitt, kees, vbabka,
hsj0512, trintaeoitogc, jackmanb, maz, glider, linux-doc, x86,
linux-kernel, kasan-dev, workflows, llvm, linux-arm-kernel,
linux-kbuild, linux-mm
On Tue, Mar 10, 2026 at 07:30:36PM +0000, Maciej Wieczor-Retman wrote:
> On 2026-03-10 at 20:00:22 +0100, Peter Zijlstra wrote:
> >On Tue, Mar 10, 2026 at 05:51:19PM +0000, Maciej Wieczor-Retman wrote:
> >
> >> ======= Compilation
> >> Clang was used to compile the series (make LLVM=1) since gcc doesn't
> >> seem to have support for KASAN tag-based compiler instrumentation on
> >> x86. Patchset does seem to compile with gcc without an issue but doesn't
> >> boot afterwards.
> >
> >Can you put all that under a specific CONFIG and make that depend on
> >CC_IS_CLANG?
>
> I made HAVE_ARCH_KASAN_SW_TAGS depend on CC_IS_CLANG, and that controls all the
> software tags stuff, like ARCH_DISABLE_KASAN_INLINE through KASAN_SW_TAGS.
> And ARCH_NEEDS_DEFER_KASAN is for if KASAN is compiled but LAM is not available,
> so that it gets disabled in runtime.
>
> But sure, I suppose I can add a separate CONFIG with CC_IS_CLANG to these three
> so the clang connection is more transparent.
Right, because building but not booting is BAD :-) While compiler
specific features are a dime a dozen.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v11 00/15] kasan: x86: arm64: KASAN tag-based mode for x86
2026-03-11 11:05 ` Peter Zijlstra
@ 2026-03-11 11:13 ` Maciej Wieczor-Retman
0 siblings, 0 replies; 9+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-11 11:13 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Maciej Wieczor-Retman, urezki, ryan.roberts, kevin.brodsky,
samuel.holland, dave.hansen, jeremy.linton, weixugc, ljs,
ryabinin.a.a, rppt, bp, luto, jan.kiszka, mingo, david, mhocko,
akpm, andreas, kas, Liam.Howlett, morbo, thuth, catalin.marinas,
ankur.a.arora, kbingham, nick.desaulniers+lkml, andreyknvl,
dvyukov, corbet, leitao, hpa, tglx, yuanchu, ardb,
vincenzo.frascino, tabba, joey.gouly, nsc, will, yeoreum.yun,
nathan, skhan, axelrasmussen, osandov, surenb, justinstitt, kees,
vbabka, hsj0512, trintaeoitogc, jackmanb, maz, glider, linux-doc,
x86, linux-kernel, kasan-dev, workflows, llvm, linux-arm-kernel,
linux-kbuild, linux-mm
On 2026-03-11 at 12:05:53 +0100, Peter Zijlstra wrote:
>On Tue, Mar 10, 2026 at 07:30:36PM +0000, Maciej Wieczor-Retman wrote:
>> On 2026-03-10 at 20:00:22 +0100, Peter Zijlstra wrote:
>> >On Tue, Mar 10, 2026 at 05:51:19PM +0000, Maciej Wieczor-Retman wrote:
>> >
>> >> ======= Compilation
>> >> Clang was used to compile the series (make LLVM=1) since gcc doesn't
>> >> seem to have support for KASAN tag-based compiler instrumentation on
>> >> x86. Patchset does seem to compile with gcc without an issue but doesn't
>> >> boot afterwards.
>> >
>> >Can you put all that under a specific CONFIG and make that depend on
>> >CC_IS_CLANG?
>>
>> I made HAVE_ARCH_KASAN_SW_TAGS depend on CC_IS_CLANG, and that controls all the
>> software tags stuff, like ARCH_DISABLE_KASAN_INLINE through KASAN_SW_TAGS.
>> And ARCH_NEEDS_DEFER_KASAN is for if KASAN is compiled but LAM is not available,
>> so that it gets disabled in runtime.
>>
>> But sure, I suppose I can add a separate CONFIG with CC_IS_CLANG to these three
>> so the clang connection is more transparent.
>
>Right, because building but not booting is BAD :-) While compiler
>specific features are a dime a dozen.
I'll make the change and I agree of course, what I meant is that with this patch
I'm pretty sure you already can't hit the condition of 'building but not
booting'. All the 'not booting' options are already hidden behind CC_IS_CLANG
(so really only HAVE_ARCH_KASAN_SW_TAGS which controls all the other ones).
--
Kind regards
Maciej Wieczór-Retman
^ permalink raw reply [flat|nested] 9+ messages in thread