public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
@ 2026-01-12 17:26 Maciej Wieczor-Retman
  2026-01-12 17:27 ` [PATCH v8 01/14] kasan: sw_tags: Use arithmetic shift for shadow computation Maciej Wieczor-Retman
                   ` (16 more replies)
  0 siblings, 17 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:26 UTC (permalink / raw)
  To: corbet, morbo, rppt, lorenzo.stoakes, ubizjak, mingo,
	vincenzo.frascino, maciej.wieczor-retman, maz, catalin.marinas,
	yeoreum.yun, will, jackmanb, samuel.holland, glider, osandov, nsc,
	luto, jpoimboe, akpm, Liam.Howlett, kees, jan.kiszka,
	thomas.lendacky, jeremy.linton, dvyukov, axelrasmussen, leitao,
	ryabinin.a.a, bigeasy, peterz, mark.rutland, urezki, brgerst, hpa,
	mhocko, andreyknvl, weixugc, kbingham, vbabka, nathan,
	trintaeoitogc, samitolvanen, tglx, thuth, surenb,
	anshuman.khandual, smostafa, yuanchu, ada.coupriediaz,
	dave.hansen, kas, nick.desaulniers+lkml, david, bp, ardb,
	justinstitt
  Cc: linux-kernel, linux-mm, kasan-dev, llvm, linux-arm-kernel,
	linux-doc, linux-kbuild, x86, m.wieczorretman

======= Introduction
The patchset aims to add a KASAN tag-based mode for the x86 architecture
with the help of the new CPU feature called Linear Address Masking
(LAM). Main improvement introduced by the series is 2x lower memory
usage compared to KASAN's generic mode, the only currently available
mode on x86. The tag based mode may also find errors that the generic
mode couldn't because of differences in how these modes operate.

======= How does KASAN' tag-based mode work?
When enabled, memory accesses and allocations are augmented by the
compiler during kernel compilation. Instrumentation functions are added
to each memory allocation and each pointer dereference.

The allocation related functions generate a random tag and save it in
two places: in shadow memory that maps to the allocated memory, and in
the top bits of the pointer that points to the allocated memory. Storing
the tag in the top of the pointer is possible because of Top-Byte Ignore
(TBI) on arm64 architecture and LAM on x86.

The access related functions are performing a comparison between the tag
stored in the pointer and the one stored in shadow memory. If the tags
don't match an out of bounds error must have occurred and so an error
report is generated.

The general idea for the tag-based mode is very well explained in the
series with the original implementation [1].

[1] https://lore.kernel.org/all/cover.1544099024.git.andreyknvl@google.com/

======= Differences summary compared to the arm64 tag-based mode
- Tag width:
	- Tag width influences the chance of a tag mismatch due to two
	  tags from different allocations having the same value. The
	  bigger the possible range of tag values the lower the chance
	  of that happening.
	- Shortening the tag width from 8 bits to 4, while it can help
	  with memory usage, it also increases the chance of not
	  reporting an error. 4 bit tags have a ~7% chance of a tag
	  mismatch.

- Address masking mechanism
	- TBI in arm64 allows for storing metadata in the top 8 bits of
	  the virtual address.
	- LAM in x86 allows storing tags in bits [62:57] of the pointer.
	  To maximize memory savings the tag width is reduced to bits
	  [60:57].

- Inline mode mismatch reporting
	- Arm64 inserts a BRK instruction to pass metadata about a tag
	  mismatch to the KASAN report.
	- Right now on x86 the INT3 instruction is used for the same
	  purpose. The attempt to move it over to use UD1 is already
	  implemented and tested but relies on another series that needs
	  merging first. Therefore this patch will be posted separately
	  once the dependency is satisfied by being merged upstream.

======= Testing
Checked all the kunits for both software tags and generic KASAN after
making changes.

In generic mode (both with these patches and without) the results were:

kasan: pass:61 fail:1 skip:14 total:76
Totals: pass:61 fail:1 skip:14 total:76
not ok 1 kasan

and for software tags:

kasan: pass:65 fail:1 skip:10 total:76
Totals: pass:65 fail:1 skip:10 total:76
not ok 1 kasan

At the time of testing the one failing case is also present on generic
mode without this patchset applied. This seems to point to something
else being at fault for the one case not passing. The test case in
question concerns strscpy() out of bounds error not getting caught.

======= Benchmarks [1]
All tests were ran on a Sierra Forest server platform. The only
differences between the tests were kernel options:
	- CONFIG_KASAN
	- CONFIG_KASAN_GENERIC
	- CONFIG_KASAN_SW_TAGS
	- CONFIG_KASAN_INLINE [1]
	- CONFIG_KASAN_OUTLINE

Boot time (until login prompt):
* 02:55 for clean kernel
* 05:42 / 06:32 for generic KASAN (inline/outline)
* 05:58 for tag-based KASAN (outline) [2]

Total memory usage (512GB present on the system - MemAvailable just
after boot):
* 12.56 GB for clean kernel
* 81.74 GB for generic KASAN
* 44.39 GB for tag-based KASAN

Kernel size:
* 14 MB for clean kernel
* 24.7 MB / 19.5 MB for generic KASAN (inline/outline)
* 27.1 MB / 18.1 MB for tag-based KASAN (inline/outline)

Work under load time comparison (compiling the mainline kernel) (200 cores):
*  62s for clean kernel
* 171s / 125s for generic KASAN (outline/inline)
* 145s for tag-based KASAN (outline) [2]

[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.

======= Dependencies
The series is based on 6.19-rc5.

======= Previous versions
v7: https://lore.kernel.org/all/cover.1765386422.git.m.wieczorretman@pm.me/
v6: https://lore.kernel.org/all/cover.1761763681.git.m.wieczorretman@pm.me/
v5: https://lore.kernel.org/all/cover.1756151769.git.maciej.wieczor-retman@intel.com/
v4: https://lore.kernel.org/all/cover.1755004923.git.maciej.wieczor-retman@intel.com/
v3: https://lore.kernel.org/all/cover.1743772053.git.maciej.wieczor-retman@intel.com/
v2: https://lore.kernel.org/all/cover.1739866028.git.maciej.wieczor-retman@intel.com/
v1: https://lore.kernel.org/all/cover.1738686764.git.maciej.wieczor-retman@intel.com/

=== (two fixes patches were split off after v6) (merged into mm-unstable)
v1: https://lore.kernel.org/all/cover.1762267022.git.m.wieczorretman@pm.me/
v2: https://lore.kernel.org/all/cover.1764685296.git.m.wieczorretman@pm.me/
v3: https://lore.kernel.org/all/cover.1764874575.git.m.wieczorretman@pm.me/
v4: https://lore.kernel.org/all/cover.1764945396.git.m.wieczorretman@pm.me/

Changes v8:
- Detached the UD1/INT3 inline patch from the series so the whole
  patchset can be merged without waiting on other dependency series. For
  now with lack of compiler support for the inline mode that patch
  didn't work anyway so this delay is not an issue.
- Rebased patches onto 6.19-rc5.
- Added acked-by tag to "kasan: arm64: x86: Make special tags arch
  specific".

Changes v7:
- Rebased the series onto Peter Zijlstra's "WARN() hackery" v2 patchset.
- Fix flipped memset arguments in "x86/kasan: KASAN raw shadow memory
  PTE init".
- Reorder tag width defines on arm64 to avoid redefinition warnings.
- Split off the pcpu unpoison patches into a separate fix oriented
  series.
- Redid the canonicality checks so it works for KVM too (didn't change
  the __canonical_address() function previously).
- A lot of fixes pointed out by Alexander in his great review:
	- Fixed "x86/mm: Physical address comparisons in fill_p*d/pte"
	- Merged "Support tag widths less than 8 bits" and "Make special
	  tags arch specific".
	- Added comments and extended patch messages for patches
	  "x86/kasan: Make software tag-based kasan available" and
	  "mm/execmem: Untag addresses in EXECMEM_ROX related pointer arithmetic",
	- Fixed KASAN_TAG_MASK definition order so all patches compile
	  individually.
	- Renamed kasan_inline.c to kasan_sw_tags.c.

Changes v6:
- Initialize sw-tags only when LAM is available.
- Move inline mode to use UD1 instead of INT3
- Remove inline multishot patch.
- Fix the canonical check to work for user addresses too.
- Revise patch names and messages to align to tip tree rules.
- Fix vdso compilation issue.

Changes v5:
- Fix a bunch of arm64 compilation errors I didn't catch earlier.
  Thank You Ada for testing the series!
- Simplify the usage of the tag handling x86 functions (virt_to_page,
  phys_addr etc.).
- Remove within() and within_range() from the EXECMEM_ROX patch.

Changes v4:
- Revert x86 kasan_mem_to_shadow() scheme to the same on used in generic
  KASAN. Keep the arithmetic shift idea for the KASAN in general since
  it makes more sense for arm64 and in risc-v.
- Fix inline mode but leave it unavailable until a complementary
  compiler patch can be merged.
- Apply Dave Hansen's comments on series formatting, patch style and
  code simplifications.

Changes v3:
- Remove the runtime_const patch and setup a unified offset for both 5
  and 4 paging levels.
- Add a fix for inline mode on x86 tag-based KASAN. Add a handler for
  int3 that is generated on inline tag mismatches.
- 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.
- Remove patches 2 and 3 since they related to risc-v and this series
  adds only x86 related things.
- Reorder __tag_*() functions so they're before arch_kasan_*(). Remove
  CONFIG_KASAN condition from __tag_set().

Changes v2:
- Split the series into one adding KASAN tag-based mode (this one) and
  another one that adds the dense mode to KASAN (will post later).
- Removed exporting kasan_poison() and used a wrapper instead in
  kasan_init_64.c
- Prepended series with 4 patches from the risc-v series and applied
  review comments to the first patch as the rest already are reviewed.

Maciej Wieczor-Retman (12):
  kasan: Fix inline mode for x86 tag-based mode
  x86/kasan: Add arch specific kasan functions
  x86/mm: Reset tag for virtual to physical address conversions
  mm/execmem: Untag addresses in EXECMEM_ROX related pointer arithmetic
  x86/mm: Physical address comparisons in fill_p*d/pte
  x86/kasan: KASAN raw shadow memory PTE init
  x86/mm: LAM compatible non-canonical definition
  x86/mm: LAM initialization
  x86: Minimal SLAB alignment
  arm64: Unify software tag-based KASAN inline recovery path
  x86/kasan: Logical bit shift for kasan_mem_to_shadow
  x86/kasan: Make software tag-based kasan available

Samuel Holland (2):
  kasan: sw_tags: Use arithmetic shift for shadow computation
  kasan: arm64: x86: Make special tags arch specific

 Documentation/arch/arm64/kasan-offsets.sh |  8 ++-
 Documentation/arch/x86/x86_64/mm.rst      |  6 ++-
 MAINTAINERS                               |  2 +-
 arch/arm64/Kconfig                        | 10 ++--
 arch/arm64/include/asm/kasan-tags.h       | 14 +++++
 arch/arm64/include/asm/kasan.h            |  2 -
 arch/arm64/include/asm/memory.h           | 14 ++++-
 arch/arm64/include/asm/uaccess.h          |  1 +
 arch/arm64/kernel/traps.c                 | 17 +------
 arch/arm64/mm/kasan_init.c                |  7 ++-
 arch/x86/Kconfig                          |  4 ++
 arch/x86/boot/compressed/misc.h           |  1 +
 arch/x86/include/asm/cache.h              |  4 ++
 arch/x86/include/asm/kasan-tags.h         |  9 ++++
 arch/x86/include/asm/kasan.h              | 62 ++++++++++++++++++++++-
 arch/x86/include/asm/page.h               | 23 ++++++++-
 arch/x86/include/asm/page_64.h            |  1 +
 arch/x86/kernel/head_64.S                 |  3 ++
 arch/x86/mm/init.c                        |  3 ++
 arch/x86/mm/init_64.c                     | 11 ++--
 arch/x86/mm/kasan_init_64.c               | 25 +++++++--
 arch/x86/mm/physaddr.c                    |  2 +
 include/linux/kasan-tags.h                | 21 ++++++--
 include/linux/kasan.h                     | 13 +++--
 include/linux/mm.h                        |  6 +--
 include/linux/mmzone.h                    |  2 +-
 include/linux/page-flags-layout.h         |  9 +---
 lib/Kconfig.kasan                         |  3 +-
 mm/execmem.c                              |  9 +++-
 mm/kasan/report.c                         | 37 ++++++++++++--
 mm/vmalloc.c                              |  7 ++-
 scripts/Makefile.kasan                    |  3 ++
 scripts/gdb/linux/kasan.py                |  5 +-
 scripts/gdb/linux/mm.py                   |  5 +-
 34 files changed, 277 insertions(+), 72 deletions(-)
 create mode 100644 arch/arm64/include/asm/kasan-tags.h
 create mode 100644 arch/x86/include/asm/kasan-tags.h

-- 
2.52.0



^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH v8 01/14] kasan: sw_tags: Use arithmetic shift for shadow computation
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
@ 2026-01-12 17:27 ` Maciej Wieczor-Retman
  2026-01-15 22:42   ` Andrey Ryabinin
  2026-01-12 17:27 ` [PATCH v8 02/14] kasan: arm64: x86: Make special tags arch specific Maciej Wieczor-Retman
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:27 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Jonathan Corbet, Andrey Ryabinin,
	Alexander Potapenko, Andrey Konovalov, Dmitry Vyukov,
	Vincenzo Frascino, Andrew Morton, 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, 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.

Using an arithmetic shift in kasan_mem_to_shadow() 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>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---
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 +++--
 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                         | 36 ++++++++++++++++++++---
 scripts/gdb/linux/kasan.py                |  5 +++-
 scripts/gdb/linux/mm.py                   |  5 ++--
 8 files changed, 76 insertions(+), 19 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/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 93173f0a09c7..c1b7261cdb96 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -434,11 +434,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 9d54b2ea49d6..f127fbf691ac 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 9c6ac4b62eb9..0f65e88cc3f6 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 62c01b4527eb..b5beb1b10bd2 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -642,11 +642,39 @@ void kasan_non_canonical_hook(unsigned long addr)
 	const char *bug_type;
 
 	/*
-	 * All addresses that came as a result of the memory-to-shadow mapping
-	 * (even for bogus pointers) must be >= KASAN_SHADOW_OFFSET.
+	 * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift
+	 * and never overflows with the chosen KASAN_SHADOW_OFFSET values (on
+	 * both x86 and arm64). Thus, the possible shadow addresses (even for
+	 * bogus pointers) belong to a single contiguous region that is the
+	 * result of kasan_mem_to_shadow() applied to the whole address space.
 	 */
-	if (addr < KASAN_SHADOW_OFFSET)
-		return;
+	if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
+		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
+		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
+			return;
+	}
+
+	/*
+	 * For Software Tag-Based KASAN, kasan_mem_to_shadow() uses the
+	 * arithmetic shift. Normally, this would make checking for a possible
+	 * shadow address complicated, as the shadow address computation
+	 * operation would overflow only for some memory addresses. However, due
+	 * to the chosen KASAN_SHADOW_OFFSET values and the fact the
+	 * kasan_mem_to_shadow() only operates on pointers with the tag reset,
+	 * the overflow always happens.
+	 *
+	 * For arm64, the top byte of the pointer gets reset to 0xFF. Thus, the
+	 * possible shadow addresses belong to a region that is the result of
+	 * kasan_mem_to_shadow() applied to the memory range
+	 * [0xFF000000000000, 0xFFFFFFFFFFFFFFFF]. Despite the overflow, the
+	 * resulting possible shadow region is contiguous, as the overflow
+	 * happens for both 0xFF000000000000 and 0xFFFFFFFFFFFFFFFF.
+	 */
+	if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && IS_ENABLED(CONFIG_ARM64)) {
+		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0xFFULL << 56)) ||
+		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
+			return;
+	}
 
 	orig_addr = (unsigned long)kasan_shadow_to_mem((void *)addr);
 
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 7571aebbe650..2e63f3dedd53 100644
--- a/scripts/gdb/linux/mm.py
+++ b/scripts/gdb/linux/mm.py
@@ -110,12 +110,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.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 02/14] kasan: arm64: x86: Make special tags arch specific
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
  2026-01-12 17:27 ` [PATCH v8 01/14] kasan: sw_tags: Use arithmetic shift for shadow computation Maciej Wieczor-Retman
@ 2026-01-12 17:27 ` Maciej Wieczor-Retman
  2026-01-13  1:21   ` Andrey Konovalov
  2026-01-16 13:32   ` Andrey Ryabinin
  2026-01-12 17:27 ` [PATCH v8 03/14] kasan: Fix inline mode for x86 tag-based mode Maciej Wieczor-Retman
                   ` (14 subsequent siblings)
  16 siblings, 2 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:27 UTC (permalink / raw)
  To: Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Catalin Marinas, Will Deacon,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko
  Cc: m.wieczorretman, Samuel Holland, Maciej Wieczor-Retman,
	linux-kernel, kasan-dev, linux-arm-kernel, linux-mm

From: Samuel Holland <samuel.holland@sifive.com>

KASAN's tag-based mode defines multiple special tag values. They're
reserved for:
- Native kernel value. On arm64 it's 0xFF and it causes an early return
  in the tag checking function.
- Invalid value. 0xFE marks an area as freed / unallocated. It's also
  the value that is used to initialize regions of shadow memory.
- Min and max values. 0xFD is the highest value that can be randomly
  generated for a new tag. 0 is the minimal value with the exception of
  arm64's hardware mode where it is equal to 0xF0.

Metadata macro is also defined:
- Tag width equal to 8.

Tag-based mode on x86 is going to use 4 bit wide tags so all the above
values need to be changed accordingly.

Make tag width and native kernel tag arch specific for x86 and arm64.

Base the invalid tag value and the max value on the native kernel tag
since they follow the same pattern on both mentioned architectures.

Also generalize KASAN_SHADOW_INIT and 0xff used in various
page_kasan_tag* helpers.

Give KASAN_TAG_MIN the default value of zero, and move the special value
for hw_tags arm64 to its arch specific kasan-tags.h.

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>
Acked-by: Will Deacon <will@kernel.org> (for the arm part)
---
Changelog v7:
- Reorder defines of arm64 tag width to prevent redefinition warnings.
- Remove KASAN_TAG_MASK so it's only defined in mmzone.h (Andrey
  Konovalov)
- Merge the 'support tag widths less than 8 bits' with this patch since
  they do similar things and overwrite each other. (Alexander)

Changelog v6:
- Add hardware tags KASAN_TAG_WIDTH value to the arm64 arch file.
- Keep KASAN_TAG_MASK in the mmzone.h.
- Remove ifndef from KASAN_SHADOW_INIT.

Changelog v5:
- Move KASAN_TAG_MIN to the arm64 kasan-tags.h for the hardware KASAN
  mode case.

Changelog v4:
- Move KASAN_TAG_MASK to kasan-tags.h.

Changelog v2:
- Remove risc-v from the patch.

 MAINTAINERS                         |  2 +-
 arch/arm64/include/asm/kasan-tags.h | 14 ++++++++++++++
 arch/arm64/include/asm/kasan.h      |  2 --
 arch/arm64/include/asm/uaccess.h    |  1 +
 arch/x86/include/asm/kasan-tags.h   |  9 +++++++++
 include/linux/kasan-tags.h          | 19 ++++++++++++++-----
 include/linux/kasan.h               |  3 +--
 include/linux/mm.h                  |  6 +++---
 include/linux/page-flags-layout.h   |  9 +--------
 9 files changed, 44 insertions(+), 21 deletions(-)
 create mode 100644 arch/arm64/include/asm/kasan-tags.h
 create mode 100644 arch/x86/include/asm/kasan-tags.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 0d044a58cbfe..84fdf497a97c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13581,7 +13581,7 @@ L:	kasan-dev@googlegroups.com
 S:	Maintained
 B:	https://bugzilla.kernel.org/buglist.cgi?component=Sanitizers&product=Memory%20Management
 F:	Documentation/dev-tools/kasan.rst
-F:	arch/*/include/asm/*kasan.h
+F:	arch/*/include/asm/*kasan*.h
 F:	arch/*/mm/kasan_init*
 F:	include/linux/kasan*.h
 F:	lib/Kconfig.kasan
diff --git a/arch/arm64/include/asm/kasan-tags.h b/arch/arm64/include/asm/kasan-tags.h
new file mode 100644
index 000000000000..259952677443
--- /dev/null
+++ b/arch/arm64/include/asm/kasan-tags.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_KASAN_TAGS_H
+#define __ASM_KASAN_TAGS_H
+
+#define KASAN_TAG_KERNEL	0xFF /* native kernel pointers tag */
+
+#ifdef CONFIG_KASAN_HW_TAGS
+#define KASAN_TAG_MIN		0xF0 /* minimum value for random tags */
+#define KASAN_TAG_WIDTH		4
+#else
+#define KASAN_TAG_WIDTH		8
+#endif
+
+#endif /* ASM_KASAN_TAGS_H */
diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h
index b167e9d3da91..fd4a8557d736 100644
--- a/arch/arm64/include/asm/kasan.h
+++ b/arch/arm64/include/asm/kasan.h
@@ -6,8 +6,6 @@
 
 #include <linux/linkage.h>
 #include <asm/memory.h>
-#include <asm/mte-kasan.h>
-#include <asm/pgtable-types.h>
 
 #define arch_kasan_set_tag(addr, tag)	__tag_set(addr, tag)
 #define arch_kasan_reset_tag(addr)	__tag_reset(addr)
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 6490930deef8..ccd41a39e3a1 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -22,6 +22,7 @@
 #include <asm/cpufeature.h>
 #include <asm/mmu.h>
 #include <asm/mte.h>
+#include <asm/mte-kasan.h>
 #include <asm/ptrace.h>
 #include <asm/memory.h>
 #include <asm/extable.h>
diff --git a/arch/x86/include/asm/kasan-tags.h b/arch/x86/include/asm/kasan-tags.h
new file mode 100644
index 000000000000..68ba385bc75c
--- /dev/null
+++ b/arch/x86/include/asm/kasan-tags.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_KASAN_TAGS_H
+#define __ASM_KASAN_TAGS_H
+
+#define KASAN_TAG_KERNEL	0xF /* native kernel pointers tag */
+
+#define KASAN_TAG_WIDTH		4
+
+#endif /* ASM_KASAN_TAGS_H */
diff --git a/include/linux/kasan-tags.h b/include/linux/kasan-tags.h
index 4f85f562512c..ad5c11950233 100644
--- a/include/linux/kasan-tags.h
+++ b/include/linux/kasan-tags.h
@@ -2,13 +2,22 @@
 #ifndef _LINUX_KASAN_TAGS_H
 #define _LINUX_KASAN_TAGS_H
 
+#if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS)
+#include <asm/kasan-tags.h>
+#endif
+
+#ifndef KASAN_TAG_WIDTH
+#define KASAN_TAG_WIDTH		0
+#endif
+
+#ifndef KASAN_TAG_KERNEL
 #define KASAN_TAG_KERNEL	0xFF /* native kernel pointers tag */
-#define KASAN_TAG_INVALID	0xFE /* inaccessible memory tag */
-#define KASAN_TAG_MAX		0xFD /* maximum value for random tags */
+#endif
+
+#define KASAN_TAG_INVALID	(KASAN_TAG_KERNEL - 1) /* inaccessible memory tag */
+#define KASAN_TAG_MAX		(KASAN_TAG_KERNEL - 2) /* maximum value for random tags */
 
-#ifdef CONFIG_KASAN_HW_TAGS
-#define KASAN_TAG_MIN		0xF0 /* minimum value for random tags */
-#else
+#ifndef KASAN_TAG_MIN
 #define KASAN_TAG_MIN		0x00 /* minimum value for random tags */
 #endif
 
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 0f65e88cc3f6..1c7acdb5f297 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -40,8 +40,7 @@ typedef unsigned int __bitwise kasan_vmalloc_flags_t;
 /* Software KASAN implementations use shadow memory. */
 
 #ifdef CONFIG_KASAN_SW_TAGS
-/* This matches KASAN_TAG_INVALID. */
-#define KASAN_SHADOW_INIT 0xFE
+#define KASAN_SHADOW_INIT KASAN_TAG_INVALID
 #else
 #define KASAN_SHADOW_INIT 0
 #endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6f959d8ca4b4..8ba91f38a794 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1949,7 +1949,7 @@ static inline u8 page_kasan_tag(const struct page *page)
 
 	if (kasan_enabled()) {
 		tag = (page->flags.f >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK;
-		tag ^= 0xff;
+		tag ^= KASAN_TAG_KERNEL;
 	}
 
 	return tag;
@@ -1962,7 +1962,7 @@ static inline void page_kasan_tag_set(struct page *page, u8 tag)
 	if (!kasan_enabled())
 		return;
 
-	tag ^= 0xff;
+	tag ^= KASAN_TAG_KERNEL;
 	old_flags = READ_ONCE(page->flags.f);
 	do {
 		flags = old_flags;
@@ -1981,7 +1981,7 @@ static inline void page_kasan_tag_reset(struct page *page)
 
 static inline u8 page_kasan_tag(const struct page *page)
 {
-	return 0xff;
+	return KASAN_TAG_KERNEL;
 }
 
 static inline void page_kasan_tag_set(struct page *page, u8 tag) { }
diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h
index 760006b1c480..b2cc4cb870e0 100644
--- a/include/linux/page-flags-layout.h
+++ b/include/linux/page-flags-layout.h
@@ -3,6 +3,7 @@
 #define PAGE_FLAGS_LAYOUT_H
 
 #include <linux/numa.h>
+#include <linux/kasan-tags.h>
 #include <generated/bounds.h>
 
 /*
@@ -72,14 +73,6 @@
 #define NODE_NOT_IN_PAGE_FLAGS	1
 #endif
 
-#if defined(CONFIG_KASAN_SW_TAGS)
-#define KASAN_TAG_WIDTH 8
-#elif defined(CONFIG_KASAN_HW_TAGS)
-#define KASAN_TAG_WIDTH 4
-#else
-#define KASAN_TAG_WIDTH 0
-#endif
-
 #ifdef CONFIG_NUMA_BALANCING
 #define LAST__PID_SHIFT 8
 #define LAST__PID_MASK  ((1 << LAST__PID_SHIFT)-1)
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 03/14] kasan: Fix inline mode for x86 tag-based mode
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
  2026-01-12 17:27 ` [PATCH v8 01/14] kasan: sw_tags: Use arithmetic shift for shadow computation Maciej Wieczor-Retman
  2026-01-12 17:27 ` [PATCH v8 02/14] kasan: arm64: x86: Make special tags arch specific Maciej Wieczor-Retman
@ 2026-01-12 17:27 ` Maciej Wieczor-Retman
  2026-01-16 13:33   ` Andrey Ryabinin
  2026-01-12 17:27 ` [PATCH v8 04/14] x86/kasan: Add arch specific kasan functions Maciej Wieczor-Retman
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:27 UTC (permalink / raw)
  To: Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Nathan Chancellor,
	Nicolas Schier, Nick Desaulniers, Bill Wendling, Justin Stitt
  Cc: m.wieczorretman, Maciej Wieczor-Retman, kasan-dev, linux-kbuild,
	linux-kernel, llvm

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

The LLVM compiler uses hwasan-instrument-with-calls parameter to setup
inline or outline mode in tag-based KASAN. If zeroed, it means the
instrumentation implementation will be pasted into each relevant
location along with KASAN related constants during compilation. If set
to one all function instrumentation will be done with function calls
instead.

The default hwasan-instrument-with-calls value for the x86 architecture
in the compiler is "1", which is not true for other architectures.
Because of this, enabling inline mode in software tag-based KASAN
doesn't work on x86 as the kernel script doesn't zero out the parameter
and always sets up the outline mode.

Explicitly zero out hwasan-instrument-with-calls when enabling inline
mode in tag-based KASAN.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Reviewed-by: Alexander Potapenko <glider@google.com>
---
Changelog v7:
- Add Alexander's Reviewed-by tag.

Changelog v6:
- Add Andrey's Reviewed-by tag.

Changelog v3:
- Add this patch to the series.

 scripts/Makefile.kasan | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan
index 0ba2aac3b8dc..e485814df3e9 100644
--- a/scripts/Makefile.kasan
+++ b/scripts/Makefile.kasan
@@ -76,8 +76,11 @@ CFLAGS_KASAN := -fsanitize=kernel-hwaddress
 RUSTFLAGS_KASAN := -Zsanitizer=kernel-hwaddress \
 		   -Zsanitizer-recover=kernel-hwaddress
 
+# LLVM sets hwasan-instrument-with-calls to 1 on x86 by default. Set it to 0
+# when inline mode is enabled.
 ifdef CONFIG_KASAN_INLINE
 	kasan_params += hwasan-mapping-offset=$(KASAN_SHADOW_OFFSET)
+	kasan_params += hwasan-instrument-with-calls=0
 else
 	kasan_params += hwasan-instrument-with-calls=1
 endif
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 04/14] x86/kasan: Add arch specific kasan functions
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (2 preceding siblings ...)
  2026-01-12 17:27 ` [PATCH v8 03/14] kasan: Fix inline mode for x86 tag-based mode Maciej Wieczor-Retman
@ 2026-01-12 17:27 ` Maciej Wieczor-Retman
  2026-01-13  1:21   ` Andrey Konovalov
  2026-01-16 13:35   ` Andrey Ryabinin
  2026-01-12 17:27 ` [PATCH v8 05/14] x86/mm: Reset tag for virtual to physical address conversions Maciej Wieczor-Retman
                   ` (12 subsequent siblings)
  16 siblings, 2 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:27 UTC (permalink / raw)
  To: Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Axel Rasmussen, Yuanchu Xie, Wei Xu
  Cc: m.wieczorretman, Maciej Wieczor-Retman, kasan-dev, linux-kernel,
	linux-mm

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

KASAN's software tag-based mode needs multiple macros/functions to
handle tag and pointer interactions - to set, retrieve and reset tags
from the top bits of a pointer.

Mimic functions currently used by arm64 but change the tag's position to
bits [60:57] in the pointer.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v7:
- Add KASAN_TAG_BYTE_MASK to avoid circular includes and avoid removing
  KASAN_TAG_MASK from mmzone.h.
- Remove Andrey's Acked-by tag.

Changelog v6:
- Remove empty line after ifdef CONFIG_KASAN_SW_TAGS
- Add ifdef 64 bit to avoid problems in vdso32.
- Add Andrey's Acked-by tag.

Changelog v4:
- Rewrite __tag_set() without pointless casts and make it more readable.

Changelog v3:
- Reorder functions so that __tag_*() etc are above the
  arch_kasan_*() ones.
- Remove CONFIG_KASAN condition from __tag_set()

 arch/x86/include/asm/kasan.h | 42 ++++++++++++++++++++++++++++++++++--
 include/linux/kasan-tags.h   |  2 ++
 include/linux/mmzone.h       |  2 +-
 3 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
index d7e33c7f096b..eab12527ed7f 100644
--- a/arch/x86/include/asm/kasan.h
+++ b/arch/x86/include/asm/kasan.h
@@ -3,6 +3,8 @@
 #define _ASM_X86_KASAN_H
 
 #include <linux/const.h>
+#include <linux/kasan-tags.h>
+#include <linux/types.h>
 #define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
 #define KASAN_SHADOW_SCALE_SHIFT 3
 
@@ -24,8 +26,43 @@
 						  KASAN_SHADOW_SCALE_SHIFT)))
 
 #ifndef __ASSEMBLER__
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+
+#ifdef CONFIG_KASAN_SW_TAGS
+#define __tag_shifted(tag)		FIELD_PREP(GENMASK_ULL(60, 57), tag)
+#define __tag_reset(addr)		(sign_extend64((u64)(addr), 56))
+#define __tag_get(addr)			((u8)FIELD_GET(GENMASK_ULL(60, 57), (u64)addr))
+#else
+#define __tag_shifted(tag)		0UL
+#define __tag_reset(addr)		(addr)
+#define __tag_get(addr)			0
+#endif /* CONFIG_KASAN_SW_TAGS */
+
+#ifdef CONFIG_64BIT
+static inline void *__tag_set(const void *__addr, u8 tag)
+{
+	u64 addr = (u64)__addr;
+
+	addr &= ~__tag_shifted(KASAN_TAG_BYTE_MASK);
+	addr |= __tag_shifted(tag & KASAN_TAG_BYTE_MASK);
+
+	return (void *)addr;
+}
+#else
+static inline void *__tag_set(void *__addr, u8 tag)
+{
+	return __addr;
+}
+#endif
+
+#define arch_kasan_set_tag(addr, tag)	__tag_set(addr, tag)
+#define arch_kasan_reset_tag(addr)	__tag_reset(addr)
+#define arch_kasan_get_tag(addr)	__tag_get(addr)
 
 #ifdef CONFIG_KASAN
+
 void __init kasan_early_init(void);
 void __init kasan_init(void);
 void __init kasan_populate_shadow_for_vaddr(void *va, size_t size, int nid);
@@ -34,8 +71,9 @@ static inline void kasan_early_init(void) { }
 static inline void kasan_init(void) { }
 static inline void kasan_populate_shadow_for_vaddr(void *va, size_t size,
 						   int nid) { }
-#endif
 
-#endif
+#endif /* CONFIG_KASAN */
+
+#endif /* __ASSEMBLER__ */
 
 #endif
diff --git a/include/linux/kasan-tags.h b/include/linux/kasan-tags.h
index ad5c11950233..e4f26bec3673 100644
--- a/include/linux/kasan-tags.h
+++ b/include/linux/kasan-tags.h
@@ -10,6 +10,8 @@
 #define KASAN_TAG_WIDTH		0
 #endif
 
+#define KASAN_TAG_BYTE_MASK	((1UL << KASAN_TAG_WIDTH) - 1)
+
 #ifndef KASAN_TAG_KERNEL
 #define KASAN_TAG_KERNEL	0xFF /* native kernel pointers tag */
 #endif
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 75ef7c9f9307..3839052121d4 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1177,7 +1177,7 @@ static inline bool zone_is_empty(const struct zone *zone)
 #define NODES_MASK		((1UL << NODES_WIDTH) - 1)
 #define SECTIONS_MASK		((1UL << SECTIONS_WIDTH) - 1)
 #define LAST_CPUPID_MASK	((1UL << LAST_CPUPID_SHIFT) - 1)
-#define KASAN_TAG_MASK		((1UL << KASAN_TAG_WIDTH) - 1)
+#define KASAN_TAG_MASK		KASAN_TAG_BYTE_MASK
 #define ZONEID_MASK		((1UL << ZONEID_SHIFT) - 1)
 
 static inline enum zone_type memdesc_zonenum(memdesc_flags_t flags)
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 05/14] x86/mm: Reset tag for virtual to physical address conversions
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (3 preceding siblings ...)
  2026-01-12 17:27 ` [PATCH v8 04/14] x86/kasan: Add arch specific kasan functions Maciej Wieczor-Retman
@ 2026-01-12 17:27 ` Maciej Wieczor-Retman
  2026-01-12 17:27 ` [PATCH v8 06/14] mm/execmem: Untag addresses in EXECMEM_ROX related pointer arithmetic Maciej Wieczor-Retman
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:27 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Andy Lutomirski, Peter Zijlstra
  Cc: m.wieczorretman, Maciej Wieczor-Retman, Alexander Potapenko,
	linux-kernel

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

Any place where pointer arithmetic is used to convert a virtual address
into a physical one can raise errors if the virtual address is tagged.

Reset the pointer's tag by sign extending the tag bits in macros that do
pointer arithmetic in address conversions. There will be no change in
compiled code with KASAN disabled since the compiler will optimize the
__tag_reset() out.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Acked-by: Alexander Potapenko <glider@google.com>
---
Changelog v7:
- Add Alexander's Acked-by tag.

Changelog v5:
- Move __tag_reset() calls into __phys_addr_nodebug() and
  __virt_addr_valid() instead of calling it on the arguments of higher
  level functions.

Changelog v4:
- Simplify page_to_virt() by removing pointless casts.
- Remove change in __is_canonical_address() because it's taken care of
  in a later patch due to a LAM compatible definition of canonical.

 arch/x86/include/asm/page.h    | 8 ++++++++
 arch/x86/include/asm/page_64.h | 1 +
 arch/x86/mm/physaddr.c         | 2 ++
 3 files changed, 11 insertions(+)

diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index 9265f2fca99a..bcf5cad3da36 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -7,6 +7,7 @@
 #ifdef __KERNEL__
 
 #include <asm/page_types.h>
+#include <asm/kasan.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/page_64.h>
@@ -65,6 +66,13 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
  * virt_to_page(kaddr) returns a valid pointer if and only if
  * virt_addr_valid(kaddr) returns true.
  */
+
+#ifdef CONFIG_KASAN_SW_TAGS
+#define page_to_virt(x) ({							\
+	void *__addr = __va(page_to_pfn((struct page *)x) << PAGE_SHIFT);	\
+	__tag_set(__addr, page_kasan_tag(x));					\
+})
+#endif
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 extern bool __virt_addr_valid(unsigned long kaddr);
 #define virt_addr_valid(kaddr)	__virt_addr_valid((unsigned long) (kaddr))
diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h
index 2f0e47be79a4..01f9e6233bba 100644
--- a/arch/x86/include/asm/page_64.h
+++ b/arch/x86/include/asm/page_64.h
@@ -22,6 +22,7 @@ extern unsigned long direct_map_physmem_end;
 
 static __always_inline unsigned long __phys_addr_nodebug(unsigned long x)
 {
+	x = __tag_reset(x);
 	unsigned long y = x - __START_KERNEL_map;
 
 	/* use the carry flag to determine if x was < __START_KERNEL_map */
diff --git a/arch/x86/mm/physaddr.c b/arch/x86/mm/physaddr.c
index 8d31c6b9e184..8f18273be0d2 100644
--- a/arch/x86/mm/physaddr.c
+++ b/arch/x86/mm/physaddr.c
@@ -14,6 +14,7 @@
 #ifdef CONFIG_DEBUG_VIRTUAL
 unsigned long __phys_addr(unsigned long x)
 {
+	x = __tag_reset(x);
 	unsigned long y = x - __START_KERNEL_map;
 
 	/* use the carry flag to determine if x was < __START_KERNEL_map */
@@ -35,6 +36,7 @@ EXPORT_SYMBOL(__phys_addr);
 
 bool __virt_addr_valid(unsigned long x)
 {
+	x = __tag_reset(x);
 	unsigned long y = x - __START_KERNEL_map;
 
 	/* use the carry flag to determine if x was < __START_KERNEL_map */
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 06/14] mm/execmem: Untag addresses in EXECMEM_ROX related pointer arithmetic
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (4 preceding siblings ...)
  2026-01-12 17:27 ` [PATCH v8 05/14] x86/mm: Reset tag for virtual to physical address conversions Maciej Wieczor-Retman
@ 2026-01-12 17:27 ` Maciej Wieczor-Retman
  2026-01-12 17:27 ` [PATCH v8 07/14] x86/mm: Physical address comparisons in fill_p*d/pte Maciej Wieczor-Retman
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:27 UTC (permalink / raw)
  To: Andrew Morton, Mike Rapoport, Uladzislau Rezki
  Cc: m.wieczorretman, Maciej Wieczor-Retman, Alexander Potapenko,
	linux-mm, linux-kernel

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

ARCH_HAS_EXECMEM_ROX was re-enabled in x86 at Linux 6.14 release.
vm_reset_perms() calculates range's start and end addresses using min()
and max() functions. To do that it compares pointers but, with KASAN
software tags mode enabled, some are tagged - addr variable is, while
start and end variables aren't. This can cause the wrong address to be
chosen and result in various errors in different places.

Reset tags in the address used as function argument in min(), max().

execmem_cache_add() adds tagged pointers to a maple tree structure,
which then are incorrectly compared when walking the tree. That results
in different pointers being returned later and page permission violation
errors panicking the kernel.

Reset tag of the address range inserted into the maple tree inside
execmem_vmalloc() which then gets propagated to execmem_cache_add().

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Acked-by: Alexander Potapenko <glider@google.com>
---
Changelog v7:
- Add Alexander's acked-by tag.
- Add comments on why these tag resets are needed (Alexander)

Changelog v6:
- Move back the tag reset from execmem_cache_add() to execmem_vmalloc()
  (Mike Rapoport)
- Rewrite the changelogs to match the code changes from v6 and v5.

Changelog v5:
- Remove the within_range() change.
- arch_kasan_reset_tag -> kasan_reset_tag.

Changelog v4:
- Add patch to the series.

 mm/execmem.c | 9 ++++++++-
 mm/vmalloc.c | 7 ++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/mm/execmem.c b/mm/execmem.c
index 810a4ba9c924..dc7422222cf7 100644
--- a/mm/execmem.c
+++ b/mm/execmem.c
@@ -59,7 +59,14 @@ static void *execmem_vmalloc(struct execmem_range *range, size_t size,
 		return NULL;
 	}
 
-	return p;
+	/*
+	 * Resetting the tag here is necessary to avoid the tagged address
+	 * ending up in the maple tree structure. There it's linear address
+	 * can be incorrectly compared with other addresses which can result in
+	 * a wrong address being picked down the line and for example a page
+	 * permission violation error panicking the kernel.
+	 */
+	return kasan_reset_tag(p);
 }
 
 struct vm_struct *execmem_vmap(size_t size)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 41dd01e8430c..6ea8d48f70c2 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -3354,7 +3354,12 @@ static void vm_reset_perms(struct vm_struct *area)
 	 * the vm_unmap_aliases() flush includes the direct map.
 	 */
 	for (i = 0; i < area->nr_pages; i += 1U << page_order) {
-		unsigned long addr = (unsigned long)page_address(area->pages[i]);
+		/*
+		 * Addresses' tag needs resetting so it can be properly used in
+		 * the min() and max() below. Otherwise the start or end values
+		 * might be favoured.
+		 */
+		unsigned long addr = (unsigned long)kasan_reset_tag(page_address(area->pages[i]));
 
 		if (addr) {
 			unsigned long page_size;
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 07/14] x86/mm: Physical address comparisons in fill_p*d/pte
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (5 preceding siblings ...)
  2026-01-12 17:27 ` [PATCH v8 06/14] mm/execmem: Untag addresses in EXECMEM_ROX related pointer arithmetic Maciej Wieczor-Retman
@ 2026-01-12 17:27 ` Maciej Wieczor-Retman
  2026-01-12 17:28 ` [PATCH v8 08/14] x86/kasan: KASAN raw shadow memory PTE init Maciej Wieczor-Retman
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:27 UTC (permalink / raw)
  To: Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, x86, H. Peter Anvin
  Cc: m.wieczorretman, Maciej Wieczor-Retman, linux-kernel

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

Calculating page offset returns a pointer without a tag. When comparing
the calculated offset to a tagged page pointer an error is raised
because they are not equal.

Change pointer comparisons to physical address comparisons as to avoid
issues with tagged pointers that pointer arithmetic would create. Open
code pte_offset_kernel(), pmd_offset(), pud_offset() and p4d_offset().
Because one parameter is always zero and the rest of the function
insides are enclosed inside __va(), removing that layer lowers the
complexity of final assembly.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v7:
- Swap ternary operator outcomes in fill_p4d since the order was
  incorrect.

Changelog v2:
- Open code *_offset() to avoid it's internal __va().

 arch/x86/mm/init_64.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 9983017ecbe0..cee14855acaf 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -269,7 +269,10 @@ static p4d_t *fill_p4d(pgd_t *pgd, unsigned long vaddr)
 	if (pgd_none(*pgd)) {
 		p4d_t *p4d = (p4d_t *)spp_getpage();
 		pgd_populate(&init_mm, pgd, p4d);
-		if (p4d != p4d_offset(pgd, 0))
+
+		if (__pa(p4d) != (pgtable_l5_enabled() ?
+				  (unsigned long)pgd_val(*pgd) & PTE_PFN_MASK :
+				  __pa(pgd)))
 			printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n",
 			       p4d, p4d_offset(pgd, 0));
 	}
@@ -281,7 +284,7 @@ static pud_t *fill_pud(p4d_t *p4d, unsigned long vaddr)
 	if (p4d_none(*p4d)) {
 		pud_t *pud = (pud_t *)spp_getpage();
 		p4d_populate(&init_mm, p4d, pud);
-		if (pud != pud_offset(p4d, 0))
+		if (__pa(pud) != (p4d_val(*p4d) & p4d_pfn_mask(*p4d)))
 			printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n",
 			       pud, pud_offset(p4d, 0));
 	}
@@ -293,7 +296,7 @@ static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr)
 	if (pud_none(*pud)) {
 		pmd_t *pmd = (pmd_t *) spp_getpage();
 		pud_populate(&init_mm, pud, pmd);
-		if (pmd != pmd_offset(pud, 0))
+		if (__pa(pmd) != (pud_val(*pud) & pud_pfn_mask(*pud)))
 			printk(KERN_ERR "PAGETABLE BUG #02! %p <-> %p\n",
 			       pmd, pmd_offset(pud, 0));
 	}
@@ -305,7 +308,7 @@ static pte_t *fill_pte(pmd_t *pmd, unsigned long vaddr)
 	if (pmd_none(*pmd)) {
 		pte_t *pte = (pte_t *) spp_getpage();
 		pmd_populate_kernel(&init_mm, pmd, pte);
-		if (pte != pte_offset_kernel(pmd, 0))
+		if (__pa(pte) != (pmd_val(*pmd) & pmd_pfn_mask(*pmd)))
 			printk(KERN_ERR "PAGETABLE BUG #03!\n");
 	}
 	return pte_offset_kernel(pmd, vaddr);
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 08/14] x86/kasan: KASAN raw shadow memory PTE init
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (6 preceding siblings ...)
  2026-01-12 17:27 ` [PATCH v8 07/14] x86/mm: Physical address comparisons in fill_p*d/pte Maciej Wieczor-Retman
@ 2026-01-12 17:28 ` Maciej Wieczor-Retman
  2026-01-16 13:36   ` Andrey Ryabinin
  2026-01-12 17:28 ` [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition Maciej Wieczor-Retman
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:28 UTC (permalink / raw)
  To: Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Dave Hansen, Andy Lutomirski,
	Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	x86, H. Peter Anvin
  Cc: m.wieczorretman, Maciej Wieczor-Retman, kasan-dev, linux-kernel

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

In KASAN's generic mode the default value in shadow memory is zero.
During initialization of shadow memory pages they are allocated and
zeroed.

In KASAN's tag-based mode the default tag for the arm64 architecture is
0xFE which corresponds to any memory that should not be accessed. On x86
(where tags are 4-bit wide instead of 8-bit wide) that tag is 0xE so
during the initializations all the bytes in shadow memory pages should
be filled with it.

Use memblock_alloc_try_nid_raw() instead of memblock_alloc_try_nid() to
avoid zeroing out the memory so it can be set with the KASAN invalid
tag.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Reviewed-by: Alexander Potapenko <glider@google.com>
---
Changelog v7:
- Fix flipped arguments in memset().
- Add Alexander's reviewed-by tag.

Changelog v2:
- Remove dense mode references, use memset() instead of kasan_poison().

 arch/x86/mm/kasan_init_64.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index 998b6010d6d3..7f5c11328ec1 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -34,6 +34,18 @@ static __init void *early_alloc(size_t size, int nid, bool should_panic)
 	return ptr;
 }
 
+static __init void *early_raw_alloc(size_t size, int nid, bool should_panic)
+{
+	void *ptr = memblock_alloc_try_nid_raw(size, size,
+			__pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid);
+
+	if (!ptr && should_panic)
+		panic("%pS: Failed to allocate page, nid=%d from=%lx\n",
+		      (void *)_RET_IP_, nid, __pa(MAX_DMA_ADDRESS));
+
+	return ptr;
+}
+
 static void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr,
 				      unsigned long end, int nid)
 {
@@ -63,8 +75,9 @@ static void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr,
 		if (!pte_none(*pte))
 			continue;
 
-		p = early_alloc(PAGE_SIZE, nid, true);
-		entry = pfn_pte(PFN_DOWN(__pa(p)), PAGE_KERNEL);
+		p = early_raw_alloc(PAGE_SIZE, nid, true);
+		memset(p, KASAN_SHADOW_INIT, PAGE_SIZE);
+		entry = pfn_pte(PFN_DOWN(__pa_nodebug(p)), PAGE_KERNEL);
 		set_pte_at(&init_mm, addr, pte, entry);
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 }
@@ -436,7 +449,7 @@ void __init kasan_init(void)
 	 * it may contain some garbage. Now we can clear and write protect it,
 	 * since after the TLB flush no one should write to it.
 	 */
-	memset(kasan_early_shadow_page, 0, PAGE_SIZE);
+	memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE);
 	for (i = 0; i < PTRS_PER_PTE; i++) {
 		pte_t pte;
 		pgprot_t prot;
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (7 preceding siblings ...)
  2026-01-12 17:28 ` [PATCH v8 08/14] x86/kasan: KASAN raw shadow memory PTE init Maciej Wieczor-Retman
@ 2026-01-12 17:28 ` Maciej Wieczor-Retman
  2026-01-16 14:25   ` Andrey Ryabinin
  2026-01-12 17:28 ` [PATCH v8 10/14] x86/mm: LAM initialization Maciej Wieczor-Retman
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:28 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin
  Cc: m.wieczorretman, Maciej Wieczor-Retman, Alexander Potapenko,
	linux-kernel

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

For an address to be canonical it has to have its top bits equal to each
other. The number of bits depends on the paging level and whether
they're supposed to be ones or zeroes depends on whether the address
points to kernel or user space.

With Linear Address Masking (LAM) enabled, the definition of linear
address canonicality is modified. Not all of the previously required
bits need to be equal, only the first and last from the previously equal
bitmask. So for example a 5-level paging kernel address needs to have
bits [63] and [56] set.

Change the canonical checking function to use bit masks instead of bit
shifts.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Acked-by: Alexander Potapenko <glider@google.com>
---
Changelog v7:
- Add Alexander's acked-by tag.
- Add parentheses around vaddr_bits as suggested by checkpatch.
- Apply the bitmasks to the __canonical_address() function which is used
  in kvm code.

Changelog v6:
- Use bitmasks to check both kernel and userspace addresses in the
  __is_canonical_address() (Dave Hansen and Samuel Holland).

Changelog v4:
- Add patch to the series.

 arch/x86/include/asm/page.h | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index bcf5cad3da36..b7940fa49e64 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -82,9 +82,22 @@ static __always_inline void *pfn_to_kaddr(unsigned long pfn)
 	return __va(pfn << PAGE_SHIFT);
 }
 
+#ifdef CONFIG_KASAN_SW_TAGS
+#define CANONICAL_MASK(vaddr_bits) (BIT_ULL(63) | BIT_ULL((vaddr_bits) - 1))
+#else
+#define CANONICAL_MASK(vaddr_bits) GENMASK_ULL(63, vaddr_bits)
+#endif
+
+/*
+ * To make an address canonical either set or clear the bits defined by the
+ * CANONICAL_MASK(). Clear the bits for userspace addresses if the top address
+ * bit is a zero. Set the bits for kernel addresses if the top address bit is a
+ * one.
+ */
 static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
 {
-	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
+	return (vaddr & BIT_ULL(63)) ? vaddr | CANONICAL_MASK(vaddr_bits) :
+				       vaddr & ~CANONICAL_MASK(vaddr_bits);
 }
 
 static __always_inline u64 __is_canonical_address(u64 vaddr, u8 vaddr_bits)
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 10/14] x86/mm: LAM initialization
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (8 preceding siblings ...)
  2026-01-12 17:28 ` [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition Maciej Wieczor-Retman
@ 2026-01-12 17:28 ` Maciej Wieczor-Retman
  2026-01-12 17:28 ` [PATCH v8 11/14] x86: Minimal SLAB alignment Maciej Wieczor-Retman
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:28 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Andy Lutomirski, Peter Zijlstra
  Cc: m.wieczorretman, Maciej Wieczor-Retman, Alexander Potapenko,
	linux-kernel

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

To make use of KASAN's tag based mode on x86, Linear Address Masking
(LAM) needs to be enabled. To do that the 28th bit in CR4 has to be set.

Set the bit in early memory initialization.

When launching secondary CPUs the LAM bit gets lost. To avoid this add
it in a mask in head_64.S. The bitmask permits some bits of CR4 to pass
from the primary CPU to the secondary CPUs without being cleared.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Acked-by: Alexander Potapenko <glider@google.com>
---
Changelog v7:
- Add Alexander's acked-by tag.

Changelog v6:
- boot_cpu_has() -> cpu_feature_enabled()

 arch/x86/kernel/head_64.S | 3 +++
 arch/x86/mm/init.c        | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 21816b48537c..c5a0bfbe280d 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -209,6 +209,9 @@ SYM_INNER_LABEL(common_startup_64, SYM_L_LOCAL)
 	 *  there will be no global TLB entries after the execution."
 	 */
 	movl	$(X86_CR4_PAE | X86_CR4_LA57), %edx
+#ifdef CONFIG_ADDRESS_MASKING
+	orl	$X86_CR4_LAM_SUP, %edx
+#endif
 #ifdef CONFIG_X86_MCE
 	/*
 	 * Preserve CR4.MCE if the kernel will enable #MC support.
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 8bf6ad4b9400..a8442b255481 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -764,6 +764,9 @@ void __init init_mem_mapping(void)
 	probe_page_size_mask();
 	setup_pcid();
 
+	if (cpu_feature_enabled(X86_FEATURE_LAM) && IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+		cr4_set_bits_and_update_boot(X86_CR4_LAM_SUP);
+
 #ifdef CONFIG_X86_64
 	end = max_pfn << PAGE_SHIFT;
 #else
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 11/14] x86: Minimal SLAB alignment
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (9 preceding siblings ...)
  2026-01-12 17:28 ` [PATCH v8 10/14] x86/mm: LAM initialization Maciej Wieczor-Retman
@ 2026-01-12 17:28 ` Maciej Wieczor-Retman
  2026-01-12 17:28 ` [PATCH v8 12/14] arm64: Unify software tag-based KASAN inline recovery path Maciej Wieczor-Retman
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:28 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin
  Cc: m.wieczorretman, Maciej Wieczor-Retman, Andrey Konovalov,
	linux-kernel

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

8 byte minimal SLAB alignment interferes with KASAN's granularity of 16
bytes. It causes a lot of out-of-bounds errors for unaligned 8 byte
allocations.

Compared to a kernel with KASAN disabled, the memory footprint increases
because all kmalloc-8 allocations now are realized as kmalloc-16, which
has twice the object size. But more meaningfully, when compared to a
kernel with generic KASAN enabled, there is no difference. Because of
redzones in generic KASAN, kmalloc-8' and kmalloc-16' object size is the
same (48 bytes). So changing the minimal SLAB alignment of the tag-based
mode doesn't have any negative impact when compared to the other
software KASAN mode.

Adjust x86 minimal SLAB alignment to match KASAN granularity size.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
---
Changelog v6:
- Add Andrey's Reviewed-by tag.

Changelog v4:
- Extend the patch message with some more context and impact
  information.

Changelog v3:
- Fix typo in patch message 4 -> 16.
- Change define location to arch/x86/include/asm/cache.c.

 arch/x86/include/asm/cache.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/x86/include/asm/cache.h b/arch/x86/include/asm/cache.h
index 69404eae9983..3232583b5487 100644
--- a/arch/x86/include/asm/cache.h
+++ b/arch/x86/include/asm/cache.h
@@ -21,4 +21,8 @@
 #endif
 #endif
 
+#ifdef CONFIG_KASAN_SW_TAGS
+#define ARCH_SLAB_MINALIGN (1ULL << KASAN_SHADOW_SCALE_SHIFT)
+#endif
+
 #endif /* _ASM_X86_CACHE_H */
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 12/14] arm64: Unify software tag-based KASAN inline recovery path
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (10 preceding siblings ...)
  2026-01-12 17:28 ` [PATCH v8 11/14] x86: Minimal SLAB alignment Maciej Wieczor-Retman
@ 2026-01-12 17:28 ` Maciej Wieczor-Retman
  2026-01-12 17:28 ` [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow Maciej Wieczor-Retman
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:28 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: m.wieczorretman, Maciej Wieczor-Retman, Alexander Potapenko,
	linux-arm-kernel, linux-kernel

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

To avoid having a copy of a long comment explaining the intricacies of
the inline KASAN recovery system and issues for every architecture that
uses the software tag-based mode, a unified kasan_die_unless_recover()
function was added.

Use kasan_die_unless_recover() in the kasan brk handler to cleanup the
long comment, that's kept in the non-arch KASAN code.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Alexander Potapenko <glider@google.com>
---
Changelog v7:
- Add Alexander's Acked-by tag.

Changelog v6:
- Add Catalin's Acked-by tag.

Changelog v5:
- Split arm64 portion of patch 13/18 into this one. (Peter Zijlstra)

 arch/arm64/kernel/traps.c | 17 +----------------
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 914282016069..e076753576e0 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -1071,22 +1071,7 @@ int kasan_brk_handler(struct pt_regs *regs, unsigned long esr)
 
 	kasan_report(addr, size, write, pc);
 
-	/*
-	 * The instrumentation allows to control whether we can proceed after
-	 * a crash was detected. This is done by passing the -recover flag to
-	 * the compiler. Disabling recovery allows to generate more compact
-	 * code.
-	 *
-	 * Unfortunately disabling recovery doesn't work for the kernel right
-	 * now. KASAN reporting is disabled in some contexts (for example when
-	 * the allocator accesses slab object metadata; this is controlled by
-	 * current->kasan_depth). All these accesses are detected by the tool,
-	 * even though the reports for them are not printed.
-	 *
-	 * This is something that might be fixed at some point in the future.
-	 */
-	if (!recover)
-		die("Oops - KASAN", regs, esr);
+	kasan_die_unless_recover(recover, "Oops - KASAN", regs, esr, die);
 
 	/* If thread survives, skip over the brk instruction and continue: */
 	arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (11 preceding siblings ...)
  2026-01-12 17:28 ` [PATCH v8 12/14] arm64: Unify software tag-based KASAN inline recovery path Maciej Wieczor-Retman
@ 2026-01-12 17:28 ` Maciej Wieczor-Retman
  2026-01-13  1:21   ` Andrey Konovalov
  2026-01-12 17:28 ` [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available Maciej Wieczor-Retman
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:28 UTC (permalink / raw)
  To: Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Andrew Morton
  Cc: m.wieczorretman, Maciej Wieczor-Retman, kasan-dev, linux-kernel,
	linux-mm

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

The tag-based KASAN adopts an arithemitc bit shift to convert a memory
address to a shadow memory address. While it makes a lot of sense on
arm64, it doesn't work well for all cases on x86 - either the
non-canonical hook becomes quite complex for different paging levels, or
the inline mode would need a lot more adjustments. Thus the best working
scheme is the logical bit shift and non-canonical shadow offset that x86
uses for generic KASAN, of course adjusted for the increased granularity
from 8 to 16 bytes.

Add an arch specific implementation of kasan_mem_to_shadow() that uses
the logical bit shift.

The non-canonical hook tries to calculate whether an address came from
kasan_mem_to_shadow(). First it checks whether this address fits into
the legal set of values possible to output from the mem to shadow
function.

Tie both generic and tag-based x86 KASAN modes to the address range
check associated with generic KASAN.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v7:
- Redo the patch message and add a comment to __kasan_mem_to_shadow() to
  provide better explanation on why x86 doesn't work well with the
  arithemitc bit shift approach (Marco).

Changelog v4:
- Add this patch to the series.

 arch/x86/include/asm/kasan.h | 15 +++++++++++++++
 mm/kasan/report.c            |  5 +++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
index eab12527ed7f..9b7951a79753 100644
--- a/arch/x86/include/asm/kasan.h
+++ b/arch/x86/include/asm/kasan.h
@@ -31,6 +31,21 @@
 #include <linux/bits.h>
 
 #ifdef CONFIG_KASAN_SW_TAGS
+/*
+ * Using the non-arch specific implementation of __kasan_mem_to_shadow() with a
+ * arithmetic bit shift can cause high code complexity in KASAN's non-canonical
+ * hook for x86 or might not work for some paging level and KASAN mode
+ * combinations. The inline mode compiler support could also suffer from higher
+ * complexity for no specific benefit. Therefore the generic mode's logical
+ * shift implementation is used.
+ */
+static inline void *__kasan_mem_to_shadow(const void *addr)
+{
+	return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
+		+ KASAN_SHADOW_OFFSET;
+}
+
+#define kasan_mem_to_shadow(addr)	__kasan_mem_to_shadow(addr)
 #define __tag_shifted(tag)		FIELD_PREP(GENMASK_ULL(60, 57), tag)
 #define __tag_reset(addr)		(sign_extend64((u64)(addr), 56))
 #define __tag_get(addr)			((u8)FIELD_GET(GENMASK_ULL(60, 57), (u64)addr))
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index b5beb1b10bd2..db6a9a3d01b2 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -642,13 +642,14 @@ void kasan_non_canonical_hook(unsigned long addr)
 	const char *bug_type;
 
 	/*
-	 * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift
+	 * For Generic KASAN and Software Tag-Based mode on the x86
+	 * architecture, kasan_mem_to_shadow() uses the logical right shift
 	 * and never overflows with the chosen KASAN_SHADOW_OFFSET values (on
 	 * both x86 and arm64). Thus, the possible shadow addresses (even for
 	 * bogus pointers) belong to a single contiguous region that is the
 	 * result of kasan_mem_to_shadow() applied to the whole address space.
 	 */
-	if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
+	if (IS_ENABLED(CONFIG_KASAN_GENERIC) || IS_ENABLED(CONFIG_X86_64)) {
 		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
 		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
 			return;
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (12 preceding siblings ...)
  2026-01-12 17:28 ` [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow Maciej Wieczor-Retman
@ 2026-01-12 17:28 ` Maciej Wieczor-Retman
  2026-01-13  1:21   ` Andrey Konovalov
  2026-01-13 11:45   ` Borislav Petkov
  2026-01-12 18:29 ` [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Andrew Morton
                   ` (2 subsequent siblings)
  16 siblings, 2 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-12 17:28 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Jonathan Corbet, Andrey Ryabinin,
	Alexander Potapenko, Andrey Konovalov, Dmitry Vyukov,
	Vincenzo Frascino, Andy Lutomirski, Peter Zijlstra, Andrew Morton
  Cc: m.wieczorretman, Maciej Wieczor-Retman, linux-kernel, linux-doc,
	kasan-dev

From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

Make CONFIG_KASAN_SW_TAGS available for x86 machines if they have
ADDRESS_MASKING enabled (LAM) as that works similarly to Top-Byte Ignore
(TBI) that allows the software tag-based mode on arm64 platform.

The value for sw_tags KASAN_SHADOW_OFFSET was calculated by rearranging
the formulas for KASAN_SHADOW_START and KASAN_SHADOW_END from
arch/x86/include/asm/kasan.h - the only prerequisites being
KASAN_SHADOW_SCALE_SHIFT of 4, and KASAN_SHADOW_END equal to the
one from KASAN generic mode.

Set scale macro based on KASAN mode: in software tag-based mode 16 bytes
of memory map to one shadow byte and 8 in generic mode.

Disable CONFIG_KASAN_INLINE and CONFIG_KASAN_STACK when
CONFIG_KASAN_SW_TAGS is enabled on x86 until the appropriate compiler
support is available.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v7:
- Add a paragraph to the patch message explaining how the various
  addresses and the KASAN_SHADOW_OFFSET were calculated.

Changelog v6:
- Don't enable KASAN if LAM is not supported.
- Move kasan_init_tags() to kasan_init_64.c to not clutter the setup.c
  file.
- Move the #ifdef for the KASAN scale shift here.
- Move the gdb code to patch "Use arithmetic shift for shadow
  computation".
- Return "depends on KASAN" line to Kconfig.
- Add the defer kasan config option so KASAN can be disabled on hardware
  that doesn't have LAM.

Changelog v4:
- Add x86 specific kasan_mem_to_shadow().
- Revert x86 to the older unsigned KASAN_SHADOW_OFFSET. Do the same to
  KASAN_SHADOW_START/END.
- Modify scripts/gdb/linux/kasan.py to keep x86 using unsigned offset.
- Disable inline and stack support when software tags are enabled on
  x86.

Changelog v3:
- Remove runtime_const from previous patch and merge the rest here.
- Move scale shift definition back to header file.
- Add new kasan offset for software tag based mode.
- Fix patch message typo 32 -> 16, and 16 -> 8.
- Update lib/Kconfig.kasan with x86 now having software tag-based
  support.

Changelog v2:
- Remove KASAN dense code.

 Documentation/arch/x86/x86_64/mm.rst | 6 ++++--
 arch/x86/Kconfig                     | 4 ++++
 arch/x86/boot/compressed/misc.h      | 1 +
 arch/x86/include/asm/kasan.h         | 5 +++++
 arch/x86/mm/kasan_init_64.c          | 6 ++++++
 lib/Kconfig.kasan                    | 3 ++-
 6 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
index a6cf05d51bd8..ccbdbb4cda36 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)
   __________________|____________|__________________|_________|____________________________________________________________
                                                               |
                                                               | Identical layout to the 47-bit one from here on:
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 80527299f859..21c71d9e0698 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
+	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
 
 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 9b7951a79753..b38a1a83af96 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..3a5577341805 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -465,4 +465,10 @@ void __init kasan_init(void)
 
 	init_task.kasan_depth = 0;
 	kasan_init_generic();
+	pr_info("KernelAddressSanitizer initialized\n");
+
+	if (boot_cpu_has(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.
 
 	  Consumes about 1/16th of available memory at kernel start and
 	  add an overhead of ~20% for dynamic allocations.
-- 
2.52.0



^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (13 preceding siblings ...)
  2026-01-12 17:28 ` [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available Maciej Wieczor-Retman
@ 2026-01-12 18:29 ` Andrew Morton
  2026-01-12 20:08   ` Maciej Wieczór-Retman
                     ` (2 more replies)
  2026-01-13  1:44 ` Andrey Konovalov
  2026-01-19 16:33 ` Andrey Ryabinin
  16 siblings, 3 replies; 53+ messages in thread
From: Andrew Morton @ 2026-01-12 18:29 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: corbet, morbo, rppt, lorenzo.stoakes, ubizjak, mingo,
	vincenzo.frascino, maciej.wieczor-retman, maz, catalin.marinas,
	yeoreum.yun, will, jackmanb, samuel.holland, glider, osandov, nsc,
	luto, jpoimboe, Liam.Howlett, kees, jan.kiszka, thomas.lendacky,
	jeremy.linton, dvyukov, axelrasmussen, leitao, ryabinin.a.a,
	bigeasy, peterz, mark.rutland, urezki, brgerst, hpa, mhocko,
	andreyknvl, weixugc, kbingham, vbabka, nathan, trintaeoitogc,
	samitolvanen, tglx, thuth, surenb, anshuman.khandual, smostafa,
	yuanchu, ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml,
	david, bp, ardb, justinstitt, linux-kernel, linux-mm, kasan-dev,
	llvm, linux-arm-kernel, linux-doc, linux-kbuild, x86

On Mon, 12 Jan 2026 17:26:29 +0000 Maciej Wieczor-Retman <m.wieczorretman@pm.me> wrote:

> The patchset aims to add a KASAN tag-based mode for the x86 architecture
> with the help of the new CPU feature called Linear Address Masking
> (LAM). Main improvement introduced by the series is 2x lower memory
> usage compared to KASAN's generic mode, the only currently available
> mode on x86. The tag based mode may also find errors that the generic
> mode couldn't because of differences in how these modes operate.

Well this is a hearty mixture of arm, x86 and MM.  I guess that means
mm.git.

The review process seems to be proceeding OK so I'll add this to
mm.git's mm-new branch, which is not included in linux-next.  I'll aim
to hold it there for a week while people check the patches over and
send out their acks (please).  Then I hope I can move it into mm.git's
mm-unstable branch where it will receive linux-next exposure.

> [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.

OK, known issues and they are understandable.  With this patchset is
there any way in which our testers can encounter these things?  If so
can we make changes to protect them from hitting known issues?

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-12 18:29 ` [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Andrew Morton
@ 2026-01-12 20:08   ` Maciej Wieczór-Retman
  2026-01-12 20:53     ` Andrew Morton
  2026-01-12 20:27   ` Dave Hansen
  2026-01-13 11:47   ` Borislav Petkov
  2 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczór-Retman @ 2026-01-12 20:08 UTC (permalink / raw)
  To: Andrew Morton
  Cc: corbet, morbo, rppt, lorenzo.stoakes, ubizjak, mingo,
	vincenzo.frascino, maciej.wieczor-retman, maz, catalin.marinas,
	yeoreum.yun, will, jackmanb, samuel.holland, glider, osandov, nsc,
	luto, jpoimboe, Liam.Howlett, kees, jan.kiszka, thomas.lendacky,
	jeremy.linton, dvyukov, axelrasmussen, leitao, ryabinin.a.a,
	bigeasy, peterz, mark.rutland, urezki, brgerst, hpa, mhocko,
	andreyknvl, weixugc, kbingham, vbabka, nathan, trintaeoitogc,
	samitolvanen, tglx, thuth, surenb, anshuman.khandual, smostafa,
	yuanchu, ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml,
	david, bp, ardb, justinstitt, linux-kernel, linux-mm, kasan-dev,
	llvm, linux-arm-kernel, linux-doc, linux-kbuild, x86

On 2026-01-12 at 10:29:57 -0800, Andrew Morton wrote:
>On Mon, 12 Jan 2026 17:26:29 +0000 Maciej Wieczor-Retman <m.wieczorretman@pm.me> wrote:
>
>> The patchset aims to add a KASAN tag-based mode for the x86 architecture
>> with the help of the new CPU feature called Linear Address Masking
>> (LAM). Main improvement introduced by the series is 2x lower memory
>> usage compared to KASAN's generic mode, the only currently available
>> mode on x86. The tag based mode may also find errors that the generic
>> mode couldn't because of differences in how these modes operate.
>
>Well this is a hearty mixture of arm, x86 and MM.  I guess that means
>mm.git.
>
>The review process seems to be proceeding OK so I'll add this to
>mm.git's mm-new branch, which is not included in linux-next.  I'll aim
>to hold it there for a week while people check the patches over and
>send out their acks (please).  Then I hope I can move it into mm.git's
>mm-unstable branch where it will receive linux-next exposure.

Thank you :)

>
>> [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.
>
>OK, known issues and they are understandable.  With this patchset is
>there any way in which our testers can encounter these things?  If so
>can we make changes to protect them from hitting known issues?

The gcc documentation states that the -fsanitize=kernel-hwaddress is
similar to -fsanitize=hwaddress, which only works on AArch64. So that
hints that it shouldn't work.

But while with KASAN sw_tags enabled the kernel compiles fine with gcc,
at least in my patched qemu it doesn't run. I remember Ada Couprie Diaz
mention that passing -march=arrowlake might help since the tag support
seems to be based on arch.

I'll check if there's a non-hacky way to have gcc work too, but perhaps
to minimize hitting known issue, for now HAVE_ARCH_KASAN_SW_TAGS should
be locked behind both ADDRESS_MASKING and CC_IS_CLANG in the Kconfig?

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-12 18:29 ` [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Andrew Morton
  2026-01-12 20:08   ` Maciej Wieczór-Retman
@ 2026-01-12 20:27   ` Dave Hansen
  2026-01-13 11:47   ` Borislav Petkov
  2 siblings, 0 replies; 53+ messages in thread
From: Dave Hansen @ 2026-01-12 20:27 UTC (permalink / raw)
  To: Andrew Morton, Maciej Wieczor-Retman
  Cc: corbet, morbo, rppt, lorenzo.stoakes, ubizjak, mingo,
	vincenzo.frascino, maciej.wieczor-retman, maz, catalin.marinas,
	yeoreum.yun, will, jackmanb, samuel.holland, glider, osandov, nsc,
	luto, jpoimboe, Liam.Howlett, kees, jan.kiszka, thomas.lendacky,
	jeremy.linton, dvyukov, axelrasmussen, leitao, ryabinin.a.a,
	bigeasy, peterz, mark.rutland, urezki, brgerst, hpa, mhocko,
	andreyknvl, weixugc, kbingham, vbabka, nathan, trintaeoitogc,
	samitolvanen, tglx, thuth, surenb, anshuman.khandual, smostafa,
	yuanchu, ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml,
	david, bp, ardb, justinstitt, linux-kernel, linux-mm, kasan-dev,
	llvm, linux-arm-kernel, linux-doc, linux-kbuild, x86

On 1/12/26 10:29, Andrew Morton wrote:
> On Mon, 12 Jan 2026 17:26:29 +0000 Maciej Wieczor-Retman <m.wieczorretman@pm.me> wrote:
>> The patchset aims to add a KASAN tag-based mode for the x86 architecture
>> with the help of the new CPU feature called Linear Address Masking
>> (LAM). Main improvement introduced by the series is 2x lower memory
>> usage compared to KASAN's generic mode, the only currently available
>> mode on x86. The tag based mode may also find errors that the generic
>> mode couldn't because of differences in how these modes operate.
> Well this is a hearty mixture of arm, x86 and MM.  I guess that means
> mm.git.
> 
> The review process seems to be proceeding OK so I'll add this to
> mm.git's mm-new branch, which is not included in linux-next.  I'll aim
> to hold it there for a week while people check the patches over and
> send out their acks (please).  Then I hope I can move it into mm.git's
> mm-unstable branch where it will receive linux-next exposure.

Yeah, it'll be good to get it some more testing exposure.

But, we definitely don't want it going upstream until it's more
thoroughly reviewed than it stands. Maciej, this would be a good time to
make sure you have a good idea who needs to review this and go rattle
some cages.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-12 20:08   ` Maciej Wieczór-Retman
@ 2026-01-12 20:53     ` Andrew Morton
  2026-01-13  1:47       ` Andrey Konovalov
  0 siblings, 1 reply; 53+ messages in thread
From: Andrew Morton @ 2026-01-12 20:53 UTC (permalink / raw)
  To: Maciej Wieczór-Retman
  Cc: corbet, morbo, rppt, lorenzo.stoakes, ubizjak, mingo,
	vincenzo.frascino, maciej.wieczor-retman, maz, catalin.marinas,
	yeoreum.yun, will, jackmanb, samuel.holland, glider, osandov, nsc,
	luto, jpoimboe, Liam.Howlett, kees, jan.kiszka, thomas.lendacky,
	jeremy.linton, dvyukov, axelrasmussen, leitao, ryabinin.a.a,
	bigeasy, peterz, mark.rutland, urezki, brgerst, hpa, mhocko,
	andreyknvl, weixugc, kbingham, vbabka, nathan, trintaeoitogc,
	samitolvanen, tglx, thuth, surenb, anshuman.khandual, smostafa,
	yuanchu, ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml,
	david, bp, ardb, justinstitt, linux-kernel, linux-mm, kasan-dev,
	llvm, linux-arm-kernel, linux-doc, linux-kbuild, x86

On Mon, 12 Jan 2026 20:08:23 +0000 Maciej Wieczór-Retman <m.wieczorretman@pm.me> wrote:

> >OK, known issues and they are understandable.  With this patchset is
> >there any way in which our testers can encounter these things?  If so
> >can we make changes to protect them from hitting known issues?
> 
> The gcc documentation states that the -fsanitize=kernel-hwaddress is
> similar to -fsanitize=hwaddress, which only works on AArch64. So that
> hints that it shouldn't work.
> 
> But while with KASAN sw_tags enabled the kernel compiles fine with gcc,
> at least in my patched qemu it doesn't run. I remember Ada Couprie Diaz
> mention that passing -march=arrowlake might help since the tag support
> seems to be based on arch.
> 
> I'll check if there's a non-hacky way to have gcc work too, but perhaps
> to minimize hitting known issue, for now HAVE_ARCH_KASAN_SW_TAGS should
> be locked behind both ADDRESS_MASKING and CC_IS_CLANG in the Kconfig?

Yes please - my main concern is that we avoid causing any disruption to
testers/buildbots/fuzzers/etc.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 02/14] kasan: arm64: x86: Make special tags arch specific
  2026-01-12 17:27 ` [PATCH v8 02/14] kasan: arm64: x86: Make special tags arch specific Maciej Wieczor-Retman
@ 2026-01-13  1:21   ` Andrey Konovalov
  2026-01-13 17:32     ` Maciej Wieczor-Retman
  2026-01-16 13:32   ` Andrey Ryabinin
  1 sibling, 1 reply; 53+ messages in thread
From: Andrey Konovalov @ 2026-01-13  1:21 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: Andrey Ryabinin, Alexander Potapenko, Dmitry Vyukov,
	Vincenzo Frascino, Catalin Marinas, Will Deacon, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Samuel Holland,
	Maciej Wieczor-Retman, linux-kernel, kasan-dev, linux-arm-kernel,
	linux-mm

On Mon, Jan 12, 2026 at 6:27 PM Maciej Wieczor-Retman
<m.wieczorretman@pm.me> wrote:
>
> From: Samuel Holland <samuel.holland@sifive.com>
>
> KASAN's tag-based mode defines multiple special tag values. They're
> reserved for:
> - Native kernel value. On arm64 it's 0xFF and it causes an early return
>   in the tag checking function.
> - Invalid value. 0xFE marks an area as freed / unallocated. It's also
>   the value that is used to initialize regions of shadow memory.
> - Min and max values. 0xFD is the highest value that can be randomly
>   generated for a new tag. 0 is the minimal value with the exception of
>   arm64's hardware mode where it is equal to 0xF0.
>
> Metadata macro is also defined:
> - Tag width equal to 8.
>
> Tag-based mode on x86 is going to use 4 bit wide tags so all the above
> values need to be changed accordingly.
>
> Make tag width and native kernel tag arch specific for x86 and arm64.
>
> Base the invalid tag value and the max value on the native kernel tag
> since they follow the same pattern on both mentioned architectures.
>
> Also generalize KASAN_SHADOW_INIT and 0xff used in various
> page_kasan_tag* helpers.
>
> Give KASAN_TAG_MIN the default value of zero, and move the special value
> for hw_tags arm64 to its arch specific kasan-tags.h.
>
> 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>
> Acked-by: Will Deacon <will@kernel.org> (for the arm part)
> ---
> Changelog v7:
> - Reorder defines of arm64 tag width to prevent redefinition warnings.
> - Remove KASAN_TAG_MASK so it's only defined in mmzone.h (Andrey
>   Konovalov)
> - Merge the 'support tag widths less than 8 bits' with this patch since
>   they do similar things and overwrite each other. (Alexander)
>
> Changelog v6:
> - Add hardware tags KASAN_TAG_WIDTH value to the arm64 arch file.
> - Keep KASAN_TAG_MASK in the mmzone.h.
> - Remove ifndef from KASAN_SHADOW_INIT.
>
> Changelog v5:
> - Move KASAN_TAG_MIN to the arm64 kasan-tags.h for the hardware KASAN
>   mode case.
>
> Changelog v4:
> - Move KASAN_TAG_MASK to kasan-tags.h.
>
> Changelog v2:
> - Remove risc-v from the patch.
>
>  MAINTAINERS                         |  2 +-
>  arch/arm64/include/asm/kasan-tags.h | 14 ++++++++++++++
>  arch/arm64/include/asm/kasan.h      |  2 --
>  arch/arm64/include/asm/uaccess.h    |  1 +
>  arch/x86/include/asm/kasan-tags.h   |  9 +++++++++
>  include/linux/kasan-tags.h          | 19 ++++++++++++++-----
>  include/linux/kasan.h               |  3 +--
>  include/linux/mm.h                  |  6 +++---
>  include/linux/page-flags-layout.h   |  9 +--------
>  9 files changed, 44 insertions(+), 21 deletions(-)
>  create mode 100644 arch/arm64/include/asm/kasan-tags.h
>  create mode 100644 arch/x86/include/asm/kasan-tags.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0d044a58cbfe..84fdf497a97c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -13581,7 +13581,7 @@ L:      kasan-dev@googlegroups.com
>  S:     Maintained
>  B:     https://bugzilla.kernel.org/buglist.cgi?component=Sanitizers&product=Memory%20Management
>  F:     Documentation/dev-tools/kasan.rst
> -F:     arch/*/include/asm/*kasan.h
> +F:     arch/*/include/asm/*kasan*.h
>  F:     arch/*/mm/kasan_init*
>  F:     include/linux/kasan*.h
>  F:     lib/Kconfig.kasan
> diff --git a/arch/arm64/include/asm/kasan-tags.h b/arch/arm64/include/asm/kasan-tags.h
> new file mode 100644
> index 000000000000..259952677443
> --- /dev/null
> +++ b/arch/arm64/include/asm/kasan-tags.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __ASM_KASAN_TAGS_H
> +#define __ASM_KASAN_TAGS_H
> +
> +#define KASAN_TAG_KERNEL       0xFF /* native kernel pointers tag */
> +
> +#ifdef CONFIG_KASAN_HW_TAGS
> +#define KASAN_TAG_MIN          0xF0 /* minimum value for random tags */
> +#define KASAN_TAG_WIDTH                4
> +#else
> +#define KASAN_TAG_WIDTH                8
> +#endif
> +
> +#endif /* ASM_KASAN_TAGS_H */
> diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h
> index b167e9d3da91..fd4a8557d736 100644
> --- a/arch/arm64/include/asm/kasan.h
> +++ b/arch/arm64/include/asm/kasan.h
> @@ -6,8 +6,6 @@
>
>  #include <linux/linkage.h>
>  #include <asm/memory.h>
> -#include <asm/mte-kasan.h>
> -#include <asm/pgtable-types.h>
>
>  #define arch_kasan_set_tag(addr, tag)  __tag_set(addr, tag)
>  #define arch_kasan_reset_tag(addr)     __tag_reset(addr)
> diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
> index 6490930deef8..ccd41a39e3a1 100644
> --- a/arch/arm64/include/asm/uaccess.h
> +++ b/arch/arm64/include/asm/uaccess.h
> @@ -22,6 +22,7 @@
>  #include <asm/cpufeature.h>
>  #include <asm/mmu.h>
>  #include <asm/mte.h>
> +#include <asm/mte-kasan.h>
>  #include <asm/ptrace.h>
>  #include <asm/memory.h>
>  #include <asm/extable.h>
> diff --git a/arch/x86/include/asm/kasan-tags.h b/arch/x86/include/asm/kasan-tags.h
> new file mode 100644
> index 000000000000..68ba385bc75c
> --- /dev/null
> +++ b/arch/x86/include/asm/kasan-tags.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __ASM_KASAN_TAGS_H
> +#define __ASM_KASAN_TAGS_H
> +
> +#define KASAN_TAG_KERNEL       0xF /* native kernel pointers tag */

One thing that stood out to me here was that for x86, KASAN_TAG_KERNEL
is defined as a 4-bit value (0xF). Which makes sense, as
KASAN_TAG_WIDTH == 4.

But for arm64, KASAN_TAG_KERNEL and others are defined as 8-bit values
(0xFF, etc.), even though for HW_TAGS, KASAN_TAG_WIDTH is also == 4
and only the lower 4 bits of these values define the tags.

This happens to work out: for HW_TAGS, __tag_set resets the top byte
but then uses the given value as is, so the higher 4 bits gets set to
0xF and the lower set to the tag. And for saving/restoring the tag in
page->flags, everything also works, as we only store the meaningful
lower 4 bits in flags, and restore the higher 0xF when doing ^ 0xFF.

But this is not related to this series: I think the way x86 defines
KASAN_TAG_KERNEL to be 0xF makes sense; we might just need to clean up
the arm64 implementation at some point.

> +
> +#define KASAN_TAG_WIDTH                4
> +
> +#endif /* ASM_KASAN_TAGS_H */
> diff --git a/include/linux/kasan-tags.h b/include/linux/kasan-tags.h
> index 4f85f562512c..ad5c11950233 100644
> --- a/include/linux/kasan-tags.h
> +++ b/include/linux/kasan-tags.h
> @@ -2,13 +2,22 @@
>  #ifndef _LINUX_KASAN_TAGS_H
>  #define _LINUX_KASAN_TAGS_H
>
> +#if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS)
> +#include <asm/kasan-tags.h>
> +#endif
> +
> +#ifndef KASAN_TAG_WIDTH
> +#define KASAN_TAG_WIDTH                0
> +#endif
> +
> +#ifndef KASAN_TAG_KERNEL
>  #define KASAN_TAG_KERNEL       0xFF /* native kernel pointers tag */
> -#define KASAN_TAG_INVALID      0xFE /* inaccessible memory tag */
> -#define KASAN_TAG_MAX          0xFD /* maximum value for random tags */
> +#endif
> +
> +#define KASAN_TAG_INVALID      (KASAN_TAG_KERNEL - 1) /* inaccessible memory tag */
> +#define KASAN_TAG_MAX          (KASAN_TAG_KERNEL - 2) /* maximum value for random tags */
>
> -#ifdef CONFIG_KASAN_HW_TAGS
> -#define KASAN_TAG_MIN          0xF0 /* minimum value for random tags */
> -#else
> +#ifndef KASAN_TAG_MIN
>  #define KASAN_TAG_MIN          0x00 /* minimum value for random tags */
>  #endif
>
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index 0f65e88cc3f6..1c7acdb5f297 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -40,8 +40,7 @@ typedef unsigned int __bitwise kasan_vmalloc_flags_t;
>  /* Software KASAN implementations use shadow memory. */
>
>  #ifdef CONFIG_KASAN_SW_TAGS
> -/* This matches KASAN_TAG_INVALID. */
> -#define KASAN_SHADOW_INIT 0xFE
> +#define KASAN_SHADOW_INIT KASAN_TAG_INVALID
>  #else
>  #define KASAN_SHADOW_INIT 0
>  #endif
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 6f959d8ca4b4..8ba91f38a794 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1949,7 +1949,7 @@ static inline u8 page_kasan_tag(const struct page *page)
>
>         if (kasan_enabled()) {
>                 tag = (page->flags.f >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK;
> -               tag ^= 0xff;
> +               tag ^= KASAN_TAG_KERNEL;
>         }
>
>         return tag;
> @@ -1962,7 +1962,7 @@ static inline void page_kasan_tag_set(struct page *page, u8 tag)
>         if (!kasan_enabled())
>                 return;
>
> -       tag ^= 0xff;
> +       tag ^= KASAN_TAG_KERNEL;
>         old_flags = READ_ONCE(page->flags.f);
>         do {
>                 flags = old_flags;
> @@ -1981,7 +1981,7 @@ static inline void page_kasan_tag_reset(struct page *page)
>
>  static inline u8 page_kasan_tag(const struct page *page)
>  {
> -       return 0xff;
> +       return KASAN_TAG_KERNEL;
>  }
>
>  static inline void page_kasan_tag_set(struct page *page, u8 tag) { }
> diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h
> index 760006b1c480..b2cc4cb870e0 100644
> --- a/include/linux/page-flags-layout.h
> +++ b/include/linux/page-flags-layout.h
> @@ -3,6 +3,7 @@
>  #define PAGE_FLAGS_LAYOUT_H
>
>  #include <linux/numa.h>
> +#include <linux/kasan-tags.h>
>  #include <generated/bounds.h>
>
>  /*
> @@ -72,14 +73,6 @@
>  #define NODE_NOT_IN_PAGE_FLAGS 1
>  #endif
>
> -#if defined(CONFIG_KASAN_SW_TAGS)
> -#define KASAN_TAG_WIDTH 8
> -#elif defined(CONFIG_KASAN_HW_TAGS)
> -#define KASAN_TAG_WIDTH 4
> -#else
> -#define KASAN_TAG_WIDTH 0
> -#endif
> -
>  #ifdef CONFIG_NUMA_BALANCING
>  #define LAST__PID_SHIFT 8
>  #define LAST__PID_MASK  ((1 << LAST__PID_SHIFT)-1)
> --
> 2.52.0
>
>

Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 04/14] x86/kasan: Add arch specific kasan functions
  2026-01-12 17:27 ` [PATCH v8 04/14] x86/kasan: Add arch specific kasan functions Maciej Wieczor-Retman
@ 2026-01-13  1:21   ` Andrey Konovalov
  2026-01-13 16:12     ` Maciej Wieczor-Retman
  2026-01-16 13:35   ` Andrey Ryabinin
  1 sibling, 1 reply; 53+ messages in thread
From: Andrey Konovalov @ 2026-01-13  1:21 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: Andrey Ryabinin, Alexander Potapenko, Dmitry Vyukov,
	Vincenzo Frascino, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Axel Rasmussen, Yuanchu Xie, Wei Xu, Maciej Wieczor-Retman,
	kasan-dev, linux-kernel, linux-mm

On Mon, Jan 12, 2026 at 6:27 PM Maciej Wieczor-Retman
<m.wieczorretman@pm.me> wrote:
>
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>
> KASAN's software tag-based mode needs multiple macros/functions to
> handle tag and pointer interactions - to set, retrieve and reset tags
> from the top bits of a pointer.
>
> Mimic functions currently used by arm64 but change the tag's position to
> bits [60:57] in the pointer.
>
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> ---
> Changelog v7:
> - Add KASAN_TAG_BYTE_MASK to avoid circular includes and avoid removing
>   KASAN_TAG_MASK from mmzone.h.
> - Remove Andrey's Acked-by tag.
>
> Changelog v6:
> - Remove empty line after ifdef CONFIG_KASAN_SW_TAGS
> - Add ifdef 64 bit to avoid problems in vdso32.
> - Add Andrey's Acked-by tag.
>
> Changelog v4:
> - Rewrite __tag_set() without pointless casts and make it more readable.
>
> Changelog v3:
> - Reorder functions so that __tag_*() etc are above the
>   arch_kasan_*() ones.
> - Remove CONFIG_KASAN condition from __tag_set()
>
>  arch/x86/include/asm/kasan.h | 42 ++++++++++++++++++++++++++++++++++--
>  include/linux/kasan-tags.h   |  2 ++
>  include/linux/mmzone.h       |  2 +-
>  3 files changed, 43 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
> index d7e33c7f096b..eab12527ed7f 100644
> --- a/arch/x86/include/asm/kasan.h
> +++ b/arch/x86/include/asm/kasan.h
> @@ -3,6 +3,8 @@
>  #define _ASM_X86_KASAN_H
>
>  #include <linux/const.h>
> +#include <linux/kasan-tags.h>
> +#include <linux/types.h>
>  #define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
>  #define KASAN_SHADOW_SCALE_SHIFT 3
>
> @@ -24,8 +26,43 @@
>                                                   KASAN_SHADOW_SCALE_SHIFT)))
>
>  #ifndef __ASSEMBLER__
> +#include <linux/bitops.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +
> +#ifdef CONFIG_KASAN_SW_TAGS
> +#define __tag_shifted(tag)             FIELD_PREP(GENMASK_ULL(60, 57), tag)
> +#define __tag_reset(addr)              (sign_extend64((u64)(addr), 56))
> +#define __tag_get(addr)                        ((u8)FIELD_GET(GENMASK_ULL(60, 57), (u64)addr))
> +#else
> +#define __tag_shifted(tag)             0UL
> +#define __tag_reset(addr)              (addr)
> +#define __tag_get(addr)                        0
> +#endif /* CONFIG_KASAN_SW_TAGS */
> +
> +#ifdef CONFIG_64BIT
> +static inline void *__tag_set(const void *__addr, u8 tag)
> +{
> +       u64 addr = (u64)__addr;
> +
> +       addr &= ~__tag_shifted(KASAN_TAG_BYTE_MASK);
> +       addr |= __tag_shifted(tag & KASAN_TAG_BYTE_MASK);
> +
> +       return (void *)addr;
> +}
> +#else
> +static inline void *__tag_set(void *__addr, u8 tag)
> +{
> +       return __addr;
> +}
> +#endif
> +
> +#define arch_kasan_set_tag(addr, tag)  __tag_set(addr, tag)
> +#define arch_kasan_reset_tag(addr)     __tag_reset(addr)
> +#define arch_kasan_get_tag(addr)       __tag_get(addr)
>
>  #ifdef CONFIG_KASAN
> +
>  void __init kasan_early_init(void);
>  void __init kasan_init(void);
>  void __init kasan_populate_shadow_for_vaddr(void *va, size_t size, int nid);
> @@ -34,8 +71,9 @@ static inline void kasan_early_init(void) { }
>  static inline void kasan_init(void) { }
>  static inline void kasan_populate_shadow_for_vaddr(void *va, size_t size,
>                                                    int nid) { }
> -#endif
>
> -#endif
> +#endif /* CONFIG_KASAN */
> +
> +#endif /* __ASSEMBLER__ */
>
>  #endif
> diff --git a/include/linux/kasan-tags.h b/include/linux/kasan-tags.h
> index ad5c11950233..e4f26bec3673 100644
> --- a/include/linux/kasan-tags.h
> +++ b/include/linux/kasan-tags.h
> @@ -10,6 +10,8 @@
>  #define KASAN_TAG_WIDTH                0
>  #endif
>
> +#define KASAN_TAG_BYTE_MASK    ((1UL << KASAN_TAG_WIDTH) - 1)

How about KASAN_TAG_BITS_MASK?

When KASAN_TAG_WIDTH == 4, the mask does not cover a whole byte.


> +
>  #ifndef KASAN_TAG_KERNEL
>  #define KASAN_TAG_KERNEL       0xFF /* native kernel pointers tag */
>  #endif
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index 75ef7c9f9307..3839052121d4 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -1177,7 +1177,7 @@ static inline bool zone_is_empty(const struct zone *zone)
>  #define NODES_MASK             ((1UL << NODES_WIDTH) - 1)
>  #define SECTIONS_MASK          ((1UL << SECTIONS_WIDTH) - 1)
>  #define LAST_CPUPID_MASK       ((1UL << LAST_CPUPID_SHIFT) - 1)
> -#define KASAN_TAG_MASK         ((1UL << KASAN_TAG_WIDTH) - 1)
> +#define KASAN_TAG_MASK         KASAN_TAG_BYTE_MASK
>  #define ZONEID_MASK            ((1UL << ZONEID_SHIFT) - 1)
>
>  static inline enum zone_type memdesc_zonenum(memdesc_flags_t flags)
> --
> 2.52.0
>
>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow
  2026-01-12 17:28 ` [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow Maciej Wieczor-Retman
@ 2026-01-13  1:21   ` Andrey Konovalov
  2026-01-14 16:52     ` Maciej Wieczor-Retman
  0 siblings, 1 reply; 53+ messages in thread
From: Andrey Konovalov @ 2026-01-13  1:21 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: Andrey Ryabinin, Alexander Potapenko, Dmitry Vyukov,
	Vincenzo Frascino, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	Maciej Wieczor-Retman, kasan-dev, linux-kernel, linux-mm

On Mon, Jan 12, 2026 at 6:28 PM Maciej Wieczor-Retman
<m.wieczorretman@pm.me> wrote:
>
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>
> The tag-based KASAN adopts an arithemitc bit shift to convert a memory
> address to a shadow memory address. While it makes a lot of sense on
> arm64, it doesn't work well for all cases on x86 - either the
> non-canonical hook becomes quite complex for different paging levels, or
> the inline mode would need a lot more adjustments. Thus the best working
> scheme is the logical bit shift and non-canonical shadow offset that x86
> uses for generic KASAN, of course adjusted for the increased granularity
> from 8 to 16 bytes.
>
> Add an arch specific implementation of kasan_mem_to_shadow() that uses
> the logical bit shift.
>
> The non-canonical hook tries to calculate whether an address came from
> kasan_mem_to_shadow(). First it checks whether this address fits into
> the legal set of values possible to output from the mem to shadow
> function.
>
> Tie both generic and tag-based x86 KASAN modes to the address range
> check associated with generic KASAN.
>
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> ---
> Changelog v7:
> - Redo the patch message and add a comment to __kasan_mem_to_shadow() to
>   provide better explanation on why x86 doesn't work well with the
>   arithemitc bit shift approach (Marco).
>
> Changelog v4:
> - Add this patch to the series.
>
>  arch/x86/include/asm/kasan.h | 15 +++++++++++++++
>  mm/kasan/report.c            |  5 +++--
>  2 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
> index eab12527ed7f..9b7951a79753 100644
> --- a/arch/x86/include/asm/kasan.h
> +++ b/arch/x86/include/asm/kasan.h
> @@ -31,6 +31,21 @@
>  #include <linux/bits.h>
>
>  #ifdef CONFIG_KASAN_SW_TAGS
> +/*
> + * Using the non-arch specific implementation of __kasan_mem_to_shadow() with a
> + * arithmetic bit shift can cause high code complexity in KASAN's non-canonical
> + * hook for x86 or might not work for some paging level and KASAN mode
> + * combinations. The inline mode compiler support could also suffer from higher
> + * complexity for no specific benefit. Therefore the generic mode's logical
> + * shift implementation is used.
> + */
> +static inline void *__kasan_mem_to_shadow(const void *addr)
> +{
> +       return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
> +               + KASAN_SHADOW_OFFSET;
> +}
> +
> +#define kasan_mem_to_shadow(addr)      __kasan_mem_to_shadow(addr)
>  #define __tag_shifted(tag)             FIELD_PREP(GENMASK_ULL(60, 57), tag)
>  #define __tag_reset(addr)              (sign_extend64((u64)(addr), 56))
>  #define __tag_get(addr)                        ((u8)FIELD_GET(GENMASK_ULL(60, 57), (u64)addr))
> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> index b5beb1b10bd2..db6a9a3d01b2 100644
> --- a/mm/kasan/report.c
> +++ b/mm/kasan/report.c
> @@ -642,13 +642,14 @@ void kasan_non_canonical_hook(unsigned long addr)
>         const char *bug_type;
>
>         /*
> -        * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift
> +        * For Generic KASAN and Software Tag-Based mode on the x86
> +        * architecture, kasan_mem_to_shadow() uses the logical right shift
>          * and never overflows with the chosen KASAN_SHADOW_OFFSET values (on
>          * both x86 and arm64). Thus, the possible shadow addresses (even for
>          * bogus pointers) belong to a single contiguous region that is the
>          * result of kasan_mem_to_shadow() applied to the whole address space.
>          */
> -       if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
> +       if (IS_ENABLED(CONFIG_KASAN_GENERIC) || IS_ENABLED(CONFIG_X86_64)) {

Not a functionality but just a code organization related concern:

Here, we embed the CONFIG_X86_64 special case in the core KASAN code,
but the __kasan_mem_to_shadow definition to use the logical shift
exists in the x86-64 arch code, and it just copy-pastes one of the
cases from the core kasan_mem_to_shadow definition.

Should we just move the x86-64 special case to the core KASAN code too
then? I.e., change the kasan_mem_to_shadow definition in
include/linux/kasan.h to check for IS_ENABLED(CONFIG_X86_64)).

And we could also add a comment there explaining how using the logical
shift for SW_TAGS benefits some architectures (just arm64 for now, but
riscv in the future as well). And put your comment about why it's not
worth it for x86 there as well.

I don't have a strong preference, just an idea.

Any thoughts?

>                 if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
>                     addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
>                         return;

There's also a comment lower in the function that needs to be updated
to mention Software Tag-Based mode on arm64 specifically.




> --
> 2.52.0
>
>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available
  2026-01-12 17:28 ` [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available Maciej Wieczor-Retman
@ 2026-01-13  1:21   ` Andrey Konovalov
  2026-01-13 15:31     ` Maciej Wieczor-Retman
  2026-01-13 11:45   ` Borislav Petkov
  1 sibling, 1 reply; 53+ messages in thread
From: Andrey Konovalov @ 2026-01-13  1:21 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Jonathan Corbet, Andrey Ryabinin,
	Alexander Potapenko, Dmitry Vyukov, Vincenzo Frascino,
	Andy Lutomirski, Peter Zijlstra, Andrew Morton,
	Maciej Wieczor-Retman, linux-kernel, linux-doc, kasan-dev

On Mon, Jan 12, 2026 at 6:28 PM Maciej Wieczor-Retman
<m.wieczorretman@pm.me> wrote:
>
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>
> Make CONFIG_KASAN_SW_TAGS available for x86 machines if they have
> ADDRESS_MASKING enabled (LAM) as that works similarly to Top-Byte Ignore
> (TBI) that allows the software tag-based mode on arm64 platform.
>
> The value for sw_tags KASAN_SHADOW_OFFSET was calculated by rearranging
> the formulas for KASAN_SHADOW_START and KASAN_SHADOW_END from
> arch/x86/include/asm/kasan.h - the only prerequisites being
> KASAN_SHADOW_SCALE_SHIFT of 4, and KASAN_SHADOW_END equal to the
> one from KASAN generic mode.
>
> Set scale macro based on KASAN mode: in software tag-based mode 16 bytes
> of memory map to one shadow byte and 8 in generic mode.
>
> Disable CONFIG_KASAN_INLINE and CONFIG_KASAN_STACK when
> CONFIG_KASAN_SW_TAGS is enabled on x86 until the appropriate compiler
> support is available.
>
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> ---
> Changelog v7:
> - Add a paragraph to the patch message explaining how the various
>   addresses and the KASAN_SHADOW_OFFSET were calculated.
>
> Changelog v6:
> - Don't enable KASAN if LAM is not supported.
> - Move kasan_init_tags() to kasan_init_64.c to not clutter the setup.c
>   file.
> - Move the #ifdef for the KASAN scale shift here.
> - Move the gdb code to patch "Use arithmetic shift for shadow
>   computation".
> - Return "depends on KASAN" line to Kconfig.
> - Add the defer kasan config option so KASAN can be disabled on hardware
>   that doesn't have LAM.
>
> Changelog v4:
> - Add x86 specific kasan_mem_to_shadow().
> - Revert x86 to the older unsigned KASAN_SHADOW_OFFSET. Do the same to
>   KASAN_SHADOW_START/END.
> - Modify scripts/gdb/linux/kasan.py to keep x86 using unsigned offset.
> - Disable inline and stack support when software tags are enabled on
>   x86.
>
> Changelog v3:
> - Remove runtime_const from previous patch and merge the rest here.
> - Move scale shift definition back to header file.
> - Add new kasan offset for software tag based mode.
> - Fix patch message typo 32 -> 16, and 16 -> 8.
> - Update lib/Kconfig.kasan with x86 now having software tag-based
>   support.
>
> Changelog v2:
> - Remove KASAN dense code.
>
>  Documentation/arch/x86/x86_64/mm.rst | 6 ++++--
>  arch/x86/Kconfig                     | 4 ++++
>  arch/x86/boot/compressed/misc.h      | 1 +
>  arch/x86/include/asm/kasan.h         | 5 +++++
>  arch/x86/mm/kasan_init_64.c          | 6 ++++++
>  lib/Kconfig.kasan                    | 3 ++-
>  6 files changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
> index a6cf05d51bd8..ccbdbb4cda36 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)
>    __________________|____________|__________________|_________|____________________________________________________________
>                                                                |
>                                                                | Identical layout to the 47-bit one from here on:
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 80527299f859..21c71d9e0698 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
> +       select ARCH_NEEDS_DEFER_KASAN           if ADDRESS_MASKING

Do we need this?

>         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
>
>  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 9b7951a79753..b38a1a83af96 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..3a5577341805 100644
> --- a/arch/x86/mm/kasan_init_64.c
> +++ b/arch/x86/mm/kasan_init_64.c
> @@ -465,4 +465,10 @@ void __init kasan_init(void)
>
>         init_task.kasan_depth = 0;
>         kasan_init_generic();
> +       pr_info("KernelAddressSanitizer initialized\n");

This pr_info is not needed, kasan_init_generic already prints the message.



> +
> +       if (boot_cpu_has(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.
>
>           Consumes about 1/16th of available memory at kernel start and
>           add an overhead of ~20% for dynamic allocations.
> --
> 2.52.0
>
>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (14 preceding siblings ...)
  2026-01-12 18:29 ` [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Andrew Morton
@ 2026-01-13  1:44 ` Andrey Konovalov
  2026-01-19 16:33 ` Andrey Ryabinin
  16 siblings, 0 replies; 53+ messages in thread
From: Andrey Konovalov @ 2026-01-13  1:44 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: corbet, morbo, rppt, lorenzo.stoakes, ubizjak, mingo,
	vincenzo.frascino, maciej.wieczor-retman, maz, catalin.marinas,
	yeoreum.yun, will, jackmanb, samuel.holland, glider, osandov, nsc,
	luto, jpoimboe, akpm, Liam.Howlett, kees, jan.kiszka,
	thomas.lendacky, jeremy.linton, dvyukov, axelrasmussen, leitao,
	ryabinin.a.a, bigeasy, peterz, mark.rutland, urezki, brgerst, hpa,
	mhocko, weixugc, kbingham, vbabka, nathan, trintaeoitogc,
	samitolvanen, tglx, thuth, surenb, anshuman.khandual, smostafa,
	yuanchu, ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml,
	david, bp, ardb, justinstitt, linux-kernel, linux-mm, kasan-dev,
	llvm, linux-arm-kernel, linux-doc, linux-kbuild, x86

On Mon, Jan 12, 2026 at 6:26 PM Maciej Wieczor-Retman
<m.wieczorretman@pm.me> wrote:
>
> ======= Introduction
> The patchset aims to add a KASAN tag-based mode for the x86 architecture
> with the help of the new CPU feature called Linear Address Masking
> (LAM). Main improvement introduced by the series is 2x lower memory
> usage compared to KASAN's generic mode, the only currently available
> mode on x86. The tag based mode may also find errors that the generic
> mode couldn't because of differences in how these modes operate.
>
> ======= How does KASAN' tag-based mode work?
> When enabled, memory accesses and allocations are augmented by the
> compiler during kernel compilation. Instrumentation functions are added
> to each memory allocation and each pointer dereference.
>
> The allocation related functions generate a random tag and save it in
> two places: in shadow memory that maps to the allocated memory, and in
> the top bits of the pointer that points to the allocated memory. Storing
> the tag in the top of the pointer is possible because of Top-Byte Ignore
> (TBI) on arm64 architecture and LAM on x86.
>
> The access related functions are performing a comparison between the tag
> stored in the pointer and the one stored in shadow memory. If the tags
> don't match an out of bounds error must have occurred and so an error
> report is generated.
>
> The general idea for the tag-based mode is very well explained in the
> series with the original implementation [1].
>
> [1] https://lore.kernel.org/all/cover.1544099024.git.andreyknvl@google.com/
>
> ======= Differences summary compared to the arm64 tag-based mode
> - Tag width:
>         - Tag width influences the chance of a tag mismatch due to two
>           tags from different allocations having the same value. The
>           bigger the possible range of tag values the lower the chance
>           of that happening.
>         - Shortening the tag width from 8 bits to 4, while it can help
>           with memory usage, it also increases the chance of not
>           reporting an error. 4 bit tags have a ~7% chance of a tag
>           mismatch.
>
> - Address masking mechanism
>         - TBI in arm64 allows for storing metadata in the top 8 bits of
>           the virtual address.
>         - LAM in x86 allows storing tags in bits [62:57] of the pointer.
>           To maximize memory savings the tag width is reduced to bits
>           [60:57].
>
> - Inline mode mismatch reporting
>         - Arm64 inserts a BRK instruction to pass metadata about a tag
>           mismatch to the KASAN report.
>         - Right now on x86 the INT3 instruction is used for the same
>           purpose. The attempt to move it over to use UD1 is already
>           implemented and tested but relies on another series that needs
>           merging first. Therefore this patch will be posted separately
>           once the dependency is satisfied by being merged upstream.
>

Please also update the Software Tag-Based KASAN section in
Documentation/dev-tools/kasan.rst accordingly.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-12 20:53     ` Andrew Morton
@ 2026-01-13  1:47       ` Andrey Konovalov
  0 siblings, 0 replies; 53+ messages in thread
From: Andrey Konovalov @ 2026-01-13  1:47 UTC (permalink / raw)
  To: Andrew Morton, Maciej Wieczór-Retman
  Cc: corbet, morbo, rppt, lorenzo.stoakes, ubizjak, mingo,
	vincenzo.frascino, maciej.wieczor-retman, maz, catalin.marinas,
	yeoreum.yun, will, jackmanb, samuel.holland, glider, osandov, nsc,
	luto, jpoimboe, Liam.Howlett, kees, jan.kiszka, thomas.lendacky,
	jeremy.linton, dvyukov, axelrasmussen, leitao, ryabinin.a.a,
	bigeasy, peterz, mark.rutland, urezki, brgerst, hpa, mhocko,
	weixugc, kbingham, vbabka, nathan, trintaeoitogc, samitolvanen,
	tglx, thuth, surenb, anshuman.khandual, smostafa, yuanchu,
	ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml, david,
	bp, ardb, justinstitt, linux-kernel, linux-mm, kasan-dev, llvm,
	linux-arm-kernel, linux-doc, linux-kbuild, x86

On Mon, Jan 12, 2026 at 9:53 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Mon, 12 Jan 2026 20:08:23 +0000 Maciej Wieczór-Retman <m.wieczorretman@pm.me> wrote:
>
> > >OK, known issues and they are understandable.  With this patchset is
> > >there any way in which our testers can encounter these things?  If so
> > >can we make changes to protect them from hitting known issues?
> >
> > The gcc documentation states that the -fsanitize=kernel-hwaddress is
> > similar to -fsanitize=hwaddress, which only works on AArch64. So that
> > hints that it shouldn't work.
> >
> > But while with KASAN sw_tags enabled the kernel compiles fine with gcc,
> > at least in my patched qemu it doesn't run. I remember Ada Couprie Diaz
> > mention that passing -march=arrowlake might help since the tag support
> > seems to be based on arch.

FYI, there are some known GCC issues with arm64 SW_TAGS mode as well:
https://bugzilla.kernel.org/show_bug.cgi?id=218043#c3.

> >
> > I'll check if there's a non-hacky way to have gcc work too, but perhaps
> > to minimize hitting known issue, for now HAVE_ARCH_KASAN_SW_TAGS should
> > be locked behind both ADDRESS_MASKING and CC_IS_CLANG in the Kconfig?
>
> Yes please - my main concern is that we avoid causing any disruption to
> testers/buildbots/fuzzers/etc.

I left some comments, but from my/KASAN point of view, the series is
ready for linux-next (but this could wait for a week and maybe the
next version of the series).

I wouldn't think there would be disruption issues: one would need to
deliberately enable the SW_TAGS mode for x86 (as GENERIC is the
default mode when just enabling KASAN). But I don't mind locking down
x86 SW_TAGS to be Clang-only for now if GCC is known not to work at
all.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available
  2026-01-12 17:28 ` [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available Maciej Wieczor-Retman
  2026-01-13  1:21   ` Andrey Konovalov
@ 2026-01-13 11:45   ` Borislav Petkov
  2026-01-13 16:00     ` Maciej Wieczor-Retman
  1 sibling, 1 reply; 53+ messages in thread
From: Borislav Petkov @ 2026-01-13 11:45 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: Thomas Gleixner, Ingo Molnar, Dave Hansen, x86, H. Peter Anvin,
	Jonathan Corbet, Andrey Ryabinin, Alexander Potapenko,
	Andrey Konovalov, Dmitry Vyukov, Vincenzo Frascino,
	Andy Lutomirski, Peter Zijlstra, Andrew Morton,
	Maciej Wieczor-Retman, linux-kernel, linux-doc, kasan-dev

For all your $Subjects: make sure they have a verb in the name.

For that consult:

https://kernel.org/doc/html/latest/process/maintainer-tip.html#patch-subject

and the following "Changelog" section.

On Mon, Jan 12, 2026 at 05:28:35PM +0000, Maciej Wieczor-Retman wrote:
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

...

>  Documentation/arch/x86/x86_64/mm.rst | 6 ++++--
>  arch/x86/Kconfig                     | 4 ++++
>  arch/x86/boot/compressed/misc.h      | 1 +
>  arch/x86/include/asm/kasan.h         | 5 +++++
>  arch/x86/mm/kasan_init_64.c          | 6 ++++++
>  lib/Kconfig.kasan                    | 3 ++-
>  6 files changed, 22 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
> index a6cf05d51bd8..ccbdbb4cda36 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)

These here are non-overlapping ranges. Yours are overlapping. Why?

>    __________________|____________|__________________|_________|____________________________________________________________
>                                                                |
>                                                                | 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)
>    __________________|____________|__________________|_________|____________________________________________________________
>                                                                |

...

> diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
> index 7f5c11328ec1..3a5577341805 100644
> --- a/arch/x86/mm/kasan_init_64.c
> +++ b/arch/x86/mm/kasan_init_64.c
> @@ -465,4 +465,10 @@ void __init kasan_init(void)
>  
>  	init_task.kasan_depth = 0;
>  	kasan_init_generic();
> +	pr_info("KernelAddressSanitizer initialized\n");

Why?

> +
> +	if (boot_cpu_has(X86_FEATURE_LAM))

cpu_feature_enabled()

> +		kasan_init_sw_tags();
> +	else
> +		pr_info("KernelAddressSanitizer not initialized (sw-tags): hardware doesn't support LAM\n");

You just said "initialized". Now it is not? How about we make up our minds
first and then issue one single true statement?

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-12 18:29 ` [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Andrew Morton
  2026-01-12 20:08   ` Maciej Wieczór-Retman
  2026-01-12 20:27   ` Dave Hansen
@ 2026-01-13 11:47   ` Borislav Petkov
  2026-01-13 17:34     ` Andrew Morton
  2 siblings, 1 reply; 53+ messages in thread
From: Borislav Petkov @ 2026-01-13 11:47 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Maciej Wieczor-Retman, corbet, morbo, rppt, lorenzo.stoakes,
	ubizjak, mingo, vincenzo.frascino, maciej.wieczor-retman, maz,
	catalin.marinas, yeoreum.yun, will, jackmanb, samuel.holland,
	glider, osandov, nsc, luto, jpoimboe, Liam.Howlett, kees,
	jan.kiszka, thomas.lendacky, jeremy.linton, dvyukov,
	axelrasmussen, leitao, ryabinin.a.a, bigeasy, peterz,
	mark.rutland, urezki, brgerst, hpa, mhocko, andreyknvl, weixugc,
	kbingham, vbabka, nathan, trintaeoitogc, samitolvanen, tglx,
	thuth, surenb, anshuman.khandual, smostafa, yuanchu,
	ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml, david,
	ardb, justinstitt, linux-kernel, linux-mm, kasan-dev, llvm,
	linux-arm-kernel, linux-doc, linux-kbuild, x86

On Mon, Jan 12, 2026 at 10:29:57AM -0800, Andrew Morton wrote:
> The review process seems to be proceeding OK so I'll add this to
> mm.git's mm-new branch, which is not included in linux-next.  I'll aim
> to hold it there for a week while people check the patches over and
> send out their acks (please).  Then I hope I can move it into mm.git's
> mm-unstable branch where it will receive linux-next exposure.

Yah, you can drop this one and take the next revision after all comments have
been addressed.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available
  2026-01-13  1:21   ` Andrey Konovalov
@ 2026-01-13 15:31     ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-13 15:31 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Jonathan Corbet, Andrey Ryabinin,
	Alexander Potapenko, Dmitry Vyukov, Vincenzo Frascino,
	Andy Lutomirski, Peter Zijlstra, Andrew Morton,
	Maciej Wieczor-Retman, linux-kernel, linux-doc, kasan-dev

On 2026-01-13 at 02:21:47 +0100, Andrey Konovalov wrote:
>On Mon, Jan 12, 2026 at 6:28 PM Maciej Wieczor-Retman
><m.wieczorretman@pm.me> wrote:
>>
>> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
...
>> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>> index 80527299f859..21c71d9e0698 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
>> +       select ARCH_NEEDS_DEFER_KASAN           if ADDRESS_MASKING
>
>Do we need this?

I added this to solve the problem "what should happen when there is no hardware
support (discovered at runtime) but someone requested/compiled the kernel with
LAM and KASAN sw_tags?". I think Samuel suggested the static keys approach
during v6 to solve this issue.

As I recall without it the kernel would just freeze since it would try doing a
bunch of LAM+KASAN related things without LAM working. So that'd end with
various faults and violations.

Technically kasan_init_sw_tags() is locked behind:
	if (boot_cpu_has(X86_FEATURE_LAM))
but not running kasan_init_sw_tags() normally doesn't actually disable software
KASAN if we don't have LAM available. Without ARCH_NEEDS_DEFER_KASAN it just
checks whether CONFIG_KASAN is enabled which it would in this scenario.

>
>>         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
>>
>>  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 9b7951a79753..b38a1a83af96 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..3a5577341805 100644
>> --- a/arch/x86/mm/kasan_init_64.c
>> +++ b/arch/x86/mm/kasan_init_64.c
>> @@ -465,4 +465,10 @@ void __init kasan_init(void)
>>
>>         init_task.kasan_depth = 0;
>>         kasan_init_generic();
>> +       pr_info("KernelAddressSanitizer initialized\n");
>
>This pr_info is not needed, kasan_init_generic already prints the message.

Thanks! I'll get rid of it.

>
>> +
>> +       if (boot_cpu_has(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.
>>
>>           Consumes about 1/16th of available memory at kernel start and
>>           add an overhead of ~20% for dynamic allocations.
>> --
>> 2.52.0
>>
>>

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available
  2026-01-13 11:45   ` Borislav Petkov
@ 2026-01-13 16:00     ` Maciej Wieczor-Retman
  2026-01-13 16:10       ` Borislav Petkov
  0 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-13 16:00 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Thomas Gleixner, Ingo Molnar, Dave Hansen, x86, H. Peter Anvin,
	Jonathan Corbet, Andrey Ryabinin, Alexander Potapenko,
	Andrey Konovalov, Dmitry Vyukov, Vincenzo Frascino,
	Andy Lutomirski, Peter Zijlstra, Andrew Morton,
	Maciej Wieczor-Retman, linux-kernel, linux-doc, kasan-dev

On 2026-01-13 at 12:45:39 +0100, Borislav Petkov wrote:
>For all your $Subjects: make sure they have a verb in the name.
>
>For that consult:
>
>https://kernel.org/doc/html/latest/process/maintainer-tip.html#patch-subject
>
>and the following "Changelog" section.

Sure, I'll revise these.

>
>On Mon, Jan 12, 2026 at 05:28:35PM +0000, Maciej Wieczor-Retman wrote:
>> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>
>...
>
>>  Documentation/arch/x86/x86_64/mm.rst | 6 ++++--
>>  arch/x86/Kconfig                     | 4 ++++
>>  arch/x86/boot/compressed/misc.h      | 1 +
>>  arch/x86/include/asm/kasan.h         | 5 +++++
>>  arch/x86/mm/kasan_init_64.c          | 6 ++++++
>>  lib/Kconfig.kasan                    | 3 ++-
>>  6 files changed, 22 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
>> index a6cf05d51bd8..ccbdbb4cda36 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)
>
>These here are non-overlapping ranges. Yours are overlapping. Why?

The two added lines are two alternative ranges based on which mode is chosen
during compile time. Is there some neater way to note this down here?

>> +   ffffec0000000000 |  -20    TB | fffffbffffffffff |   16 TB | KASAN shadow memory (generic mode)
>> +   or
>> +   fffff40000000000 |   -8    TB | fffffbffffffffff |    8 TB | KASAN shadow memory (software tag-based mode)

Something like this maybe ^ ? Or is the first take okay?

>
>>    __________________|____________|__________________|_________|____________________________________________________________
>>                                                                |
>>                                                                | 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)
>>    __________________|____________|__________________|_________|____________________________________________________________
>>                                                                |
>
>...
>
>> diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
>> index 7f5c11328ec1..3a5577341805 100644
>> --- a/arch/x86/mm/kasan_init_64.c
>> +++ b/arch/x86/mm/kasan_init_64.c
>> @@ -465,4 +465,10 @@ void __init kasan_init(void)
>>
>>  	init_task.kasan_depth = 0;
>>  	kasan_init_generic();
>> +	pr_info("KernelAddressSanitizer initialized\n");
>
>Why?

My mistake, that string is already printed by kasan_init_generic(), I'll remove
it.

>
>> +
>> +	if (boot_cpu_has(X86_FEATURE_LAM))
>
>cpu_feature_enabled()

Sure, thanks!

>
>> +		kasan_init_sw_tags();
>> +	else
>> +		pr_info("KernelAddressSanitizer not initialized (sw-tags): hardware doesn't support LAM\n");
>
>You just said "initialized". Now it is not? How about we make up our minds
>first and then issue one single true statement?

Yes, I'll keep this one since the "initialized" pr_info() are called from inside
kasan_init_generic() and kasan_init_sw_tags().

>
>--
>Regards/Gruss,
>    Boris.
>
>https://people.kernel.org/tglx/notes-about-netiquette

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available
  2026-01-13 16:00     ` Maciej Wieczor-Retman
@ 2026-01-13 16:10       ` Borislav Petkov
  0 siblings, 0 replies; 53+ messages in thread
From: Borislav Petkov @ 2026-01-13 16:10 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: Thomas Gleixner, Ingo Molnar, Dave Hansen, x86, H. Peter Anvin,
	Jonathan Corbet, Andrey Ryabinin, Alexander Potapenko,
	Andrey Konovalov, Dmitry Vyukov, Vincenzo Frascino,
	Andy Lutomirski, Peter Zijlstra, Andrew Morton,
	Maciej Wieczor-Retman, linux-kernel, linux-doc, kasan-dev

On Tue, Jan 13, 2026 at 04:00:47PM +0000, Maciej Wieczor-Retman wrote:
> The two added lines are two alternative ranges based on which mode is chosen
> during compile time. Is there some neater way to note this down here?

Explain it with words. Perhaps put a footnote or so. Say that those are
alternative ranges so that it is perfectly clear to readers.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 04/14] x86/kasan: Add arch specific kasan functions
  2026-01-13  1:21   ` Andrey Konovalov
@ 2026-01-13 16:12     ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-13 16:12 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: Andrey Ryabinin, Alexander Potapenko, Dmitry Vyukov,
	Vincenzo Frascino, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Axel Rasmussen, Yuanchu Xie, Wei Xu, Maciej Wieczor-Retman,
	kasan-dev, linux-kernel, linux-mm

On 2026-01-13 at 02:21:15 +0100, Andrey Konovalov wrote:
>On Mon, Jan 12, 2026 at 6:27 PM Maciej Wieczor-Retman
><m.wieczorretman@pm.me> wrote:
>>
>> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>> diff --git a/include/linux/kasan-tags.h b/include/linux/kasan-tags.h
>> index ad5c11950233..e4f26bec3673 100644
>> --- a/include/linux/kasan-tags.h
>> +++ b/include/linux/kasan-tags.h
>> @@ -10,6 +10,8 @@
>>  #define KASAN_TAG_WIDTH                0
>>  #endif
>>
>> +#define KASAN_TAG_BYTE_MASK    ((1UL << KASAN_TAG_WIDTH) - 1)
>
>How about KASAN_TAG_BITS_MASK?
>
>When KASAN_TAG_WIDTH == 4, the mask does not cover a whole byte.

Yes, I suppose that name makes more sense :)

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 02/14] kasan: arm64: x86: Make special tags arch specific
  2026-01-13  1:21   ` Andrey Konovalov
@ 2026-01-13 17:32     ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-13 17:32 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: Andrey Ryabinin, Alexander Potapenko, Dmitry Vyukov,
	Vincenzo Frascino, Catalin Marinas, Will Deacon, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Samuel Holland,
	Maciej Wieczor-Retman, linux-kernel, kasan-dev, linux-arm-kernel,
	linux-mm

On 2026-01-13 at 02:21:07 +0100, Andrey Konovalov wrote:
>On Mon, Jan 12, 2026 at 6:27 PM Maciej Wieczor-Retman
><m.wieczorretman@pm.me> wrote:
>>
>> From: Samuel Holland <samuel.holland@sifive.com>
>> diff --git a/arch/x86/include/asm/kasan-tags.h b/arch/x86/include/asm/kasan-tags.h
>> new file mode 100644
>> index 000000000000..68ba385bc75c
>> --- /dev/null
>> +++ b/arch/x86/include/asm/kasan-tags.h
>> @@ -0,0 +1,9 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +#ifndef __ASM_KASAN_TAGS_H
>> +#define __ASM_KASAN_TAGS_H
>> +
>> +#define KASAN_TAG_KERNEL       0xF /* native kernel pointers tag */
>
>One thing that stood out to me here was that for x86, KASAN_TAG_KERNEL
>is defined as a 4-bit value (0xF). Which makes sense, as
>KASAN_TAG_WIDTH == 4.
>
>But for arm64, KASAN_TAG_KERNEL and others are defined as 8-bit values
>(0xFF, etc.), even though for HW_TAGS, KASAN_TAG_WIDTH is also == 4
>and only the lower 4 bits of these values define the tags.
>
>This happens to work out: for HW_TAGS, __tag_set resets the top byte
>but then uses the given value as is, so the higher 4 bits gets set to
>0xF and the lower set to the tag. And for saving/restoring the tag in
>page->flags, everything also works, as we only store the meaningful
>lower 4 bits in flags, and restore the higher 0xF when doing ^ 0xFF.
>
>But this is not related to this series: I think the way x86 defines
>KASAN_TAG_KERNEL to be 0xF makes sense; we might just need to clean up
>the arm64 implementation at some point.
>

I suppose while there is only one such mode that stands out from the other two
there is little hint as to what should be generalized. As you said so far this
scheme we have works - altough it is somewhat convoluted.

One thing I was thinking of was cleaning up all the #ifdefs for different modes
into a more ordered structure. I think there are ~24 ifdefs in mm/kasan.h and
include/linux/kasan.h and many of them could potentially be merged.

...
>
>Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>

Thanks :)

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-13 11:47   ` Borislav Petkov
@ 2026-01-13 17:34     ` Andrew Morton
  2026-01-22 17:25       ` Maciej Wieczor-Retman
  0 siblings, 1 reply; 53+ messages in thread
From: Andrew Morton @ 2026-01-13 17:34 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Maciej Wieczor-Retman, corbet, morbo, rppt, lorenzo.stoakes,
	ubizjak, mingo, vincenzo.frascino, maciej.wieczor-retman, maz,
	catalin.marinas, yeoreum.yun, will, jackmanb, samuel.holland,
	glider, osandov, nsc, luto, jpoimboe, Liam.Howlett, kees,
	jan.kiszka, thomas.lendacky, jeremy.linton, dvyukov,
	axelrasmussen, leitao, ryabinin.a.a, bigeasy, peterz,
	mark.rutland, urezki, brgerst, hpa, mhocko, andreyknvl, weixugc,
	kbingham, vbabka, nathan, trintaeoitogc, samitolvanen, tglx,
	thuth, surenb, anshuman.khandual, smostafa, yuanchu,
	ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml, david,
	ardb, justinstitt, linux-kernel, linux-mm, kasan-dev, llvm,
	linux-arm-kernel, linux-doc, linux-kbuild, x86

On Tue, 13 Jan 2026 12:47:05 +0100 Borislav Petkov <bp@alien8.de> wrote:

> On Mon, Jan 12, 2026 at 10:29:57AM -0800, Andrew Morton wrote:
> > The review process seems to be proceeding OK so I'll add this to
> > mm.git's mm-new branch, which is not included in linux-next.  I'll aim
> > to hold it there for a week while people check the patches over and
> > send out their acks (please).  Then I hope I can move it into mm.git's
> > mm-unstable branch where it will receive linux-next exposure.
> 
> Yah, you can drop this one and take the next revision after all comments have
> been addressed.

Cool, I removed the series.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow
  2026-01-13  1:21   ` Andrey Konovalov
@ 2026-01-14 16:52     ` Maciej Wieczor-Retman
  2026-01-15  3:57       ` Andrey Konovalov
  0 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-14 16:52 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: Maciej Wieczor-Retman, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Vincenzo Frascino, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	kasan-dev, linux-kernel, linux-mm

On 2026-01-13 at 02:21:22 +0100, Andrey Konovalov wrote:
>On Mon, Jan 12, 2026 at 6:28 PM Maciej Wieczor-Retman
><m.wieczorretman@pm.me> wrote:
>>
>> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
...
>>
>>         /*
>> -        * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift
>> +        * For Generic KASAN and Software Tag-Based mode on the x86
>> +        * architecture, kasan_mem_to_shadow() uses the logical right shift
>>          * and never overflows with the chosen KASAN_SHADOW_OFFSET values (on
>>          * both x86 and arm64). Thus, the possible shadow addresses (even for
>>          * bogus pointers) belong to a single contiguous region that is the
>>          * result of kasan_mem_to_shadow() applied to the whole address space.
>>          */
>> -       if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
>> +       if (IS_ENABLED(CONFIG_KASAN_GENERIC) || IS_ENABLED(CONFIG_X86_64)) {
>
>Not a functionality but just a code organization related concern:
>
>Here, we embed the CONFIG_X86_64 special case in the core KASAN code,
>but the __kasan_mem_to_shadow definition to use the logical shift
>exists in the x86-64 arch code, and it just copy-pastes one of the
>cases from the core kasan_mem_to_shadow definition.
>
>Should we just move the x86-64 special case to the core KASAN code too
>then? I.e., change the kasan_mem_to_shadow definition in
>include/linux/kasan.h to check for IS_ENABLED(CONFIG_X86_64)).
>
>And we could also add a comment there explaining how using the logical
>shift for SW_TAGS benefits some architectures (just arm64 for now, but
>riscv in the future as well). And put your comment about why it's not
>worth it for x86 there as well.
>
>I don't have a strong preference, just an idea.
>
>Any thoughts?

I'm a fan of trying to keep as much arch code in the arch directories.

How about before putting a call here instead like:

	if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
			return;
	}

	arch_kasan_non_canonical_hook()
There would be the generic non-arch part above (and anything shared that might
make sense here in the future) and all the arch related code would be hidden in
the per-arch helper.

So then we could move the part below:
	if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && IS_ENABLED(CONFIG_ARM64)) {
		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0xFFULL << 56)) ||
		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
			return;
	}
to /arch/arm64.

For x86 we'd need to duplicate the generic part into
arch_kasan_non_canonical_hook() call in /arch/x86. That seems quiet tidy to me,
granted the duplication isn't great but it would keep the non-arch part as
shared as possible. What do you think?

>
>>                 if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
>>                     addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
>>                         return;
>
>There's also a comment lower in the function that needs to be updated
>to mention Software Tag-Based mode on arm64 specifically.

Okay, I'll add that in

>
>
>
>
>> --
>> 2.52.0
>>
>>

-- 
Kind regards
Maciej Wieczór-Retman

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow
  2026-01-14 16:52     ` Maciej Wieczor-Retman
@ 2026-01-15  3:57       ` Andrey Konovalov
  2026-01-15 16:43         ` Maciej Wieczor-Retman
  0 siblings, 1 reply; 53+ messages in thread
From: Andrey Konovalov @ 2026-01-15  3:57 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: Maciej Wieczor-Retman, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Vincenzo Frascino, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	kasan-dev, linux-kernel, linux-mm

On Wed, Jan 14, 2026 at 5:52 PM Maciej Wieczor-Retman
<maciej.wieczor-retman@intel.com> wrote:
>
> I'm a fan of trying to keep as much arch code in the arch directories.
>
> How about before putting a call here instead like:
>
>         if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
>                 if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
>                     addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
>                         return;
>         }
>
>         arch_kasan_non_canonical_hook()
> There would be the generic non-arch part above (and anything shared that might
> make sense here in the future) and all the arch related code would be hidden in
> the per-arch helper.
>
> So then we could move the part below:
>         if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && IS_ENABLED(CONFIG_ARM64)) {
>                 if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0xFFULL << 56)) ||
>                     addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
>                         return;
>         }
> to /arch/arm64.
>
> For x86 we'd need to duplicate the generic part into
> arch_kasan_non_canonical_hook() call in /arch/x86. That seems quiet tidy to me,
> granted the duplication isn't great but it would keep the non-arch part as
> shared as possible. What do you think?

Sounds good to me too, thanks!

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow
  2026-01-15  3:57       ` Andrey Konovalov
@ 2026-01-15 16:43         ` Maciej Wieczor-Retman
  2026-01-17  1:21           ` Andrey Konovalov
  0 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-15 16:43 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: Maciej Wieczor-Retman, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Vincenzo Frascino, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	kasan-dev, linux-kernel, linux-mm

On 2026-01-15 at 04:57:15 +0100, Andrey Konovalov wrote:
>On Wed, Jan 14, 2026 at 5:52 PM Maciej Wieczor-Retman
><maciej.wieczor-retman@intel.com> wrote:
>>
>> I'm a fan of trying to keep as much arch code in the arch directories.
>>
>> How about before putting a call here instead like:
>>
>>         if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
>>                 if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
>>                     addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
>>                         return;
>>         }
>>
>>         arch_kasan_non_canonical_hook()
>> There would be the generic non-arch part above (and anything shared that might
>> make sense here in the future) and all the arch related code would be hidden in
>> the per-arch helper.
>>
>> So then we could move the part below:
>>         if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && IS_ENABLED(CONFIG_ARM64)) {
>>                 if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0xFFULL << 56)) ||
>>                     addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
>>                         return;
>>         }
>> to /arch/arm64.
>>
>> For x86 we'd need to duplicate the generic part into
>> arch_kasan_non_canonical_hook() call in /arch/x86. That seems quiet tidy to me,
>> granted the duplication isn't great but it would keep the non-arch part as
>> shared as possible. What do you think?
>
>Sounds good to me too, thanks!

x86 was easy to do because the kasan_mem_to_shadow() was already in the
asm/kasan.h. arm64 took a bit more changes since I had to write the
arch_kasan_non_canonical_hook in a separate file that would import the
linux/kasan.h header in order to use kasan_mem_to_shadow(). Anyway below are the
relevant bits from the patch - does that look okay? Or would you prefer some
different names/placements?

diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h
index b167e9d3da91..16b1f2ca3ea8 100644
--- a/arch/arm64/include/asm/kasan.h
+++ b/arch/arm64/include/asm/kasan.h
@@ -17,6 +17,8 @@
 
 asmlinkage void kasan_early_init(void);
 void kasan_init(void);
+bool __arch_kasan_non_canonical_hook(unsigned long addr);
+#define arch_kasan_non_canonical_hook(addr) __arch_kasan_non_canonical_hook(addr)
 
 #else
 static inline void kasan_init(void) { }

diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
index c26489cf96cd..a122ea67eced 100644
--- a/arch/arm64/mm/Makefile
+++ b/arch/arm64/mm/Makefile
@@ -15,4 +15,6 @@ obj-$(CONFIG_ARM64_GCS)		+= gcs.o
 KASAN_SANITIZE_physaddr.o	+= n
 
 obj-$(CONFIG_KASAN)		+= kasan_init.o
+obj-$(CONFIG_KASAN)		+= kasan.o
 KASAN_SANITIZE_kasan_init.o	:= n
+KASAN_SANITIZE_kasan.o		:= n
diff --git a/arch/arm64/mm/kasan.c b/arch/arm64/mm/kasan.c
new file mode 100644
index 000000000000..b94d5fb480ca
--- /dev/null
+++ b/arch/arm64/mm/kasan.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * This file contains ARM64 specific KASAN code.
+ */
+
+#include <linux/kasan.h>
+
+bool __arch_kasan_non_canonical_hook(unsigned long addr) {
+	/*
+	 * For Software Tag-Based KASAN, kasan_mem_to_shadow() uses the
+	 * arithmetic shift. Normally, this would make checking for a possible
+	 * shadow address complicated, as the shadow address computation
+	 * operation would overflow only for some memory addresses. However, due
+	 * to the chosen KASAN_SHADOW_OFFSET values and the fact the
+	 * kasan_mem_to_shadow() only operates on pointers with the tag reset,
+	 * the overflow always happens.
+	 *
+	 * For arm64, the top byte of the pointer gets reset to 0xFF. Thus, the
+	 * possible shadow addresses belong to a region that is the result of
+	 * kasan_mem_to_shadow() applied to the memory range
+	 * [0xFF000000000000, 0xFFFFFFFFFFFFFFFF]. Despite the overflow, the
+	 * resulting possible shadow region is contiguous, as the overflow
+	 * happens for both 0xFF000000000000 and 0xFFFFFFFFFFFFFFFF.
+	 */
+	if (IS_ENABLED(CONFIG_KASAN_SW_TAGS)) {
+		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0xFFULL << 56)) ||
+		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
+			return true;
+	}
+	return false;
+}
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 9c6ac4b62eb9..146eecae4e9c 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
...
@@ -403,6 +409,13 @@ static __always_inline bool kasan_check_byte(const void *addr)
 	return true;
 }
 
+#ifndef arch_kasan_non_canonical_hook
+static inline bool arch_kasan_non_canonical_hook(unsigned long addr)
+{
+	return false;
+}
+#endif
+
 #else /* CONFIG_KASAN */
 
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 62c01b4527eb..1c4893729ff6 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -642,10 +642,19 @@ void kasan_non_canonical_hook(unsigned long addr)
 	const char *bug_type;
 
 	/*
-	 * All addresses that came as a result of the memory-to-shadow mapping
-	 * (even for bogus pointers) must be >= KASAN_SHADOW_OFFSET.
+	 * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift
+	 * and never overflows with the chosen KASAN_SHADOW_OFFSET values. Thus,
+	 * the possible shadow addresses (even for bogus pointers) belong to a
+	 * single contiguous region that is the result of kasan_mem_to_shadow()
+	 * applied to the whole address space.
 	 */
-	if (addr < KASAN_SHADOW_OFFSET)
+	if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
+		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
+		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
+			return;
+	}
+
+	if(arch_kasan_non_canonical_hook(addr))
 		return;

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 01/14] kasan: sw_tags: Use arithmetic shift for shadow computation
  2026-01-12 17:27 ` [PATCH v8 01/14] kasan: sw_tags: Use arithmetic shift for shadow computation Maciej Wieczor-Retman
@ 2026-01-15 22:42   ` Andrey Ryabinin
  2026-01-16 13:11     ` Maciej Wieczor-Retman
  0 siblings, 1 reply; 53+ messages in thread
From: Andrey Ryabinin @ 2026-01-15 22:42 UTC (permalink / raw)
  To: Maciej Wieczor-Retman, Catalin Marinas, Will Deacon,
	Jonathan Corbet, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Andrew Morton, Jan Kiszka,
	Kieran Bingham, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt
  Cc: Samuel Holland, Maciej Wieczor-Retman, linux-arm-kernel,
	linux-doc, linux-kernel, kasan-dev, linux-mm, llvm



On 1/12/26 6:27 PM, Maciej Wieczor-Retman wrote:
  
> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> index 62c01b4527eb..b5beb1b10bd2 100644
> --- a/mm/kasan/report.c
> +++ b/mm/kasan/report.c
> @@ -642,11 +642,39 @@ void kasan_non_canonical_hook(unsigned long addr)
>  	const char *bug_type;
>  
>  	/*
> -	 * All addresses that came as a result of the memory-to-shadow mapping
> -	 * (even for bogus pointers) must be >= KASAN_SHADOW_OFFSET.
> +	 * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift
> +	 * and never overflows with the chosen KASAN_SHADOW_OFFSET values (on
> +	 * both x86 and arm64). Thus, the possible shadow addresses (even for
> +	 * bogus pointers) belong to a single contiguous region that is the
> +	 * result of kasan_mem_to_shadow() applied to the whole address space.
>  	 */
> -	if (addr < KASAN_SHADOW_OFFSET)
> -		return;
> +	if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
> +		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
> +		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
> +			return;
> +	}
> +
> +	/*
> +	 * For Software Tag-Based KASAN, kasan_mem_to_shadow() uses the
> +	 * arithmetic shift. Normally, this would make checking for a possible
> +	 * shadow address complicated, as the shadow address computation
> +	 * operation would overflow only for some memory addresses. However, due
> +	 * to the chosen KASAN_SHADOW_OFFSET values and the fact the
> +	 * kasan_mem_to_shadow() only operates on pointers with the tag reset,
> +	 * the overflow always happens.
> +	 *
> +	 * For arm64, the top byte of the pointer gets reset to 0xFF. Thus, the
> +	 * possible shadow addresses belong to a region that is the result of
> +	 * kasan_mem_to_shadow() applied to the memory range
> +	 * [0xFF000000000000, 0xFFFFFFFFFFFFFFFF]. Despite the overflow, the
                  ^ Missing couple 00 here

> +	 * resulting possible shadow region is contiguous, as the overflow
> +	 * happens for both 0xFF000000000000 and 0xFFFFFFFFFFFFFFFF.
                                  ^ same as above

> +	 */
> +	if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && IS_ENABLED(CONFIG_ARM64)) {
> +		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0xFFULL << 56)) ||

This will not work for inline mode because compiler uses logical shift.
Consider NULL-ptr derefernce. Compiler will calculate shadow address for 0 as:
      (((0x0 | 0xffULL) << 56) >> 4)+0xffff800000000000ULL = 0x0fef8000....0
Which is less than ((0xFF00...00LL) >> 4) +  0xffff800000000000ULL = 0xffff800...0
So we will bail out here.
Perhaps we could do addr |= 0xFFLL to fix this

> +		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
> +			return;
> +	}
>  
>  	orig_addr = (unsigned long)kasan_shadow_to_mem((void *)addr);
>  

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 01/14] kasan: sw_tags: Use arithmetic shift for shadow computation
  2026-01-15 22:42   ` Andrey Ryabinin
@ 2026-01-16 13:11     ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-16 13:11 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: Catalin Marinas, Will Deacon, Jonathan Corbet,
	Alexander Potapenko, Andrey Konovalov, Dmitry Vyukov,
	Vincenzo Frascino, Andrew Morton, Jan Kiszka, Kieran Bingham,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Samuel Holland, Maciej Wieczor-Retman, linux-arm-kernel,
	linux-doc, linux-kernel, kasan-dev, linux-mm, llvm

Thanks for looking at the patches :)

On 2026-01-15 at 23:42:02 +0100, Andrey Ryabinin wrote:
>
>
>On 1/12/26 6:27 PM, Maciej Wieczor-Retman wrote:
>  
>> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
>> index 62c01b4527eb..b5beb1b10bd2 100644
>> --- a/mm/kasan/report.c
>> +++ b/mm/kasan/report.c
>> @@ -642,11 +642,39 @@ void kasan_non_canonical_hook(unsigned long addr)
>>  	const char *bug_type;
>>  
>>  	/*
>> -	 * All addresses that came as a result of the memory-to-shadow mapping
>> -	 * (even for bogus pointers) must be >= KASAN_SHADOW_OFFSET.
>> +	 * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift
>> +	 * and never overflows with the chosen KASAN_SHADOW_OFFSET values (on
>> +	 * both x86 and arm64). Thus, the possible shadow addresses (even for
>> +	 * bogus pointers) belong to a single contiguous region that is the
>> +	 * result of kasan_mem_to_shadow() applied to the whole address space.
>>  	 */
>> -	if (addr < KASAN_SHADOW_OFFSET)
>> -		return;
>> +	if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
>> +		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
>> +		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
>> +			return;
>> +	}
>> +
>> +	/*
>> +	 * For Software Tag-Based KASAN, kasan_mem_to_shadow() uses the
>> +	 * arithmetic shift. Normally, this would make checking for a possible
>> +	 * shadow address complicated, as the shadow address computation
>> +	 * operation would overflow only for some memory addresses. However, due
>> +	 * to the chosen KASAN_SHADOW_OFFSET values and the fact the
>> +	 * kasan_mem_to_shadow() only operates on pointers with the tag reset,
>> +	 * the overflow always happens.
>> +	 *
>> +	 * For arm64, the top byte of the pointer gets reset to 0xFF. Thus, the
>> +	 * possible shadow addresses belong to a region that is the result of
>> +	 * kasan_mem_to_shadow() applied to the memory range
>> +	 * [0xFF000000000000, 0xFFFFFFFFFFFFFFFF]. Despite the overflow, the
>                  ^ Missing couple 00 here
>
>> +	 * resulting possible shadow region is contiguous, as the overflow
>> +	 * happens for both 0xFF000000000000 and 0xFFFFFFFFFFFFFFFF.
>                                  ^ same as above

Hah, right, thank you!

>
>> +	 */
>> +	if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && IS_ENABLED(CONFIG_ARM64)) {
>> +		if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0xFFULL << 56)) ||
>
>This will not work for inline mode because compiler uses logical shift.
>Consider NULL-ptr derefernce. Compiler will calculate shadow address for 0 as:
>      (((0x0 | 0xffULL) << 56) >> 4)+0xffff800000000000ULL = 0x0fef8000....0
>Which is less than ((0xFF00...00LL) >> 4) +  0xffff800000000000ULL = 0xffff800...0
>So we will bail out here.
>Perhaps we could do addr |= 0xFFLL to fix this

I suppose it should work; tried it in a python script by shoving various
addresses into this check. Pushing addresses through a logical shift
memory_to_shadow normally would return early as you noticed, and after 'addr |=
0xFFLL' it seems to work as expected. And I didn't really catch any incorrect
address slipping by this scheme either. Thanks, I'll correct it.

>
>> +		    addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
>> +			return;
>> +	}
>>  
>>  	orig_addr = (unsigned long)kasan_shadow_to_mem((void *)addr);
>>  

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 02/14] kasan: arm64: x86: Make special tags arch specific
  2026-01-12 17:27 ` [PATCH v8 02/14] kasan: arm64: x86: Make special tags arch specific Maciej Wieczor-Retman
  2026-01-13  1:21   ` Andrey Konovalov
@ 2026-01-16 13:32   ` Andrey Ryabinin
  1 sibling, 0 replies; 53+ messages in thread
From: Andrey Ryabinin @ 2026-01-16 13:32 UTC (permalink / raw)
  To: Maciej Wieczor-Retman, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Catalin Marinas, Will Deacon,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko
  Cc: Samuel Holland, Maciej Wieczor-Retman, linux-kernel, kasan-dev,
	linux-arm-kernel, linux-mm

On 1/12/26 6:27 PM, Maciej Wieczor-Retman wrote:
> From: Samuel Holland <samuel.holland@sifive.com>
> 
> KASAN's tag-based mode defines multiple special tag values. They're
> reserved for:
> - Native kernel value. On arm64 it's 0xFF and it causes an early return
>   in the tag checking function.
> - Invalid value. 0xFE marks an area as freed / unallocated. It's also
>   the value that is used to initialize regions of shadow memory.
> - Min and max values. 0xFD is the highest value that can be randomly
>   generated for a new tag. 0 is the minimal value with the exception of
>   arm64's hardware mode where it is equal to 0xF0.
> 
> Metadata macro is also defined:
> - Tag width equal to 8.
> 
> Tag-based mode on x86 is going to use 4 bit wide tags so all the above
> values need to be changed accordingly.
> 
> Make tag width and native kernel tag arch specific for x86 and arm64.
> 
> Base the invalid tag value and the max value on the native kernel tag
> since they follow the same pattern on both mentioned architectures.
> 
> Also generalize KASAN_SHADOW_INIT and 0xff used in various
> page_kasan_tag* helpers.
> 
> Give KASAN_TAG_MIN the default value of zero, and move the special value
> for hw_tags arm64 to its arch specific kasan-tags.h.
> 
> 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>
> Acked-by: Will Deacon <will@kernel.org> (for the arm part)
> ---

Reviewed-by: Andrey Ryabinin <ryabinin.a.a@gmail.com>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 03/14] kasan: Fix inline mode for x86 tag-based mode
  2026-01-12 17:27 ` [PATCH v8 03/14] kasan: Fix inline mode for x86 tag-based mode Maciej Wieczor-Retman
@ 2026-01-16 13:33   ` Andrey Ryabinin
  0 siblings, 0 replies; 53+ messages in thread
From: Andrey Ryabinin @ 2026-01-16 13:33 UTC (permalink / raw)
  To: Maciej Wieczor-Retman, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Nathan Chancellor,
	Nicolas Schier, Nick Desaulniers, Bill Wendling, Justin Stitt
  Cc: Maciej Wieczor-Retman, kasan-dev, linux-kbuild, linux-kernel,
	llvm



On 1/12/26 6:27 PM, Maciej Wieczor-Retman wrote:
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> 
> The LLVM compiler uses hwasan-instrument-with-calls parameter to setup
> inline or outline mode in tag-based KASAN. If zeroed, it means the
> instrumentation implementation will be pasted into each relevant
> location along with KASAN related constants during compilation. If set
> to one all function instrumentation will be done with function calls
> instead.
> 
> The default hwasan-instrument-with-calls value for the x86 architecture
> in the compiler is "1", which is not true for other architectures.
> Because of this, enabling inline mode in software tag-based KASAN
> doesn't work on x86 as the kernel script doesn't zero out the parameter
> and always sets up the outline mode.
> 
> Explicitly zero out hwasan-instrument-with-calls when enabling inline
> mode in tag-based KASAN.
> 
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
> Reviewed-by: Alexander Potapenko <glider@google.com>
> ---

Reviewed-by: Andrey Ryabinin <ryabinin.a.a@gmail.com>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 04/14] x86/kasan: Add arch specific kasan functions
  2026-01-12 17:27 ` [PATCH v8 04/14] x86/kasan: Add arch specific kasan functions Maciej Wieczor-Retman
  2026-01-13  1:21   ` Andrey Konovalov
@ 2026-01-16 13:35   ` Andrey Ryabinin
  1 sibling, 0 replies; 53+ messages in thread
From: Andrey Ryabinin @ 2026-01-16 13:35 UTC (permalink / raw)
  To: Maciej Wieczor-Retman, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Axel Rasmussen, Yuanchu Xie, Wei Xu
  Cc: Maciej Wieczor-Retman, kasan-dev, linux-kernel, linux-mm



On 1/12/26 6:27 PM, Maciej Wieczor-Retman wrote:
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> 
> KASAN's software tag-based mode needs multiple macros/functions to
> handle tag and pointer interactions - to set, retrieve and reset tags
> from the top bits of a pointer.
> 
> Mimic functions currently used by arm64 but change the tag's position to
> bits [60:57] in the pointer.
> 
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> ---

Reviewed-by: Andrey Ryabinin <ryabinin.a.a@gmail.com>


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 08/14] x86/kasan: KASAN raw shadow memory PTE init
  2026-01-12 17:28 ` [PATCH v8 08/14] x86/kasan: KASAN raw shadow memory PTE init Maciej Wieczor-Retman
@ 2026-01-16 13:36   ` Andrey Ryabinin
  0 siblings, 0 replies; 53+ messages in thread
From: Andrey Ryabinin @ 2026-01-16 13:36 UTC (permalink / raw)
  To: Maciej Wieczor-Retman, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Dave Hansen, Andy Lutomirski,
	Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	x86, H. Peter Anvin
  Cc: Maciej Wieczor-Retman, kasan-dev, linux-kernel



On 1/12/26 6:28 PM, Maciej Wieczor-Retman wrote:
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> 
> In KASAN's generic mode the default value in shadow memory is zero.
> During initialization of shadow memory pages they are allocated and
> zeroed.
> 
> In KASAN's tag-based mode the default tag for the arm64 architecture is
> 0xFE which corresponds to any memory that should not be accessed. On x86
> (where tags are 4-bit wide instead of 8-bit wide) that tag is 0xE so
> during the initializations all the bytes in shadow memory pages should
> be filled with it.
> 
> Use memblock_alloc_try_nid_raw() instead of memblock_alloc_try_nid() to
> avoid zeroing out the memory so it can be set with the KASAN invalid
> tag.
> 
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> Reviewed-by: Alexander Potapenko <glider@google.com>
> ---

Reviewed-by: Andrey Ryabinin <ryabinin.a.a@gmail.com>


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition
  2026-01-12 17:28 ` [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition Maciej Wieczor-Retman
@ 2026-01-16 14:25   ` Andrey Ryabinin
  2026-01-16 14:57     ` Sean Christopherson
  0 siblings, 1 reply; 53+ messages in thread
From: Andrey Ryabinin @ 2026-01-16 14:25 UTC (permalink / raw)
  To: Maciej Wieczor-Retman, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin
  Cc: Maciej Wieczor-Retman, Alexander Potapenko, linux-kernel,
	Paolo Bonzini, Sean Christopherson, kvm



On 1/12/26 6:28 PM, Maciej Wieczor-Retman wrote:
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> 
> For an address to be canonical it has to have its top bits equal to each
> other. The number of bits depends on the paging level and whether
> they're supposed to be ones or zeroes depends on whether the address
> points to kernel or user space.
> 
> With Linear Address Masking (LAM) enabled, the definition of linear
> address canonicality is modified. Not all of the previously required
> bits need to be equal, only the first and last from the previously equal
> bitmask. So for example a 5-level paging kernel address needs to have
> bits [63] and [56] set.
> 
> Change the canonical checking function to use bit masks instead of bit
> shifts.
> 
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> Acked-by: Alexander Potapenko <glider@google.com>
> ---
> Changelog v7:
> - Add Alexander's acked-by tag.
> - Add parentheses around vaddr_bits as suggested by checkpatch.
> - Apply the bitmasks to the __canonical_address() function which is used
>   in kvm code.
> 
> Changelog v6:
> - Use bitmasks to check both kernel and userspace addresses in the
>   __is_canonical_address() (Dave Hansen and Samuel Holland).
> 
> Changelog v4:
> - Add patch to the series.
> 
>  arch/x86/include/asm/page.h | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
> index bcf5cad3da36..b7940fa49e64 100644
> --- a/arch/x86/include/asm/page.h
> +++ b/arch/x86/include/asm/page.h
> @@ -82,9 +82,22 @@ static __always_inline void *pfn_to_kaddr(unsigned long pfn)
>  	return __va(pfn << PAGE_SHIFT);
>  }
>  
> +#ifdef CONFIG_KASAN_SW_TAGS
> +#define CANONICAL_MASK(vaddr_bits) (BIT_ULL(63) | BIT_ULL((vaddr_bits) - 1))

why is the choice of CANONICAL_MASK() gated at compile time? Shouldn’t this be a
runtime decision based on whether LAM is enabled or not on the running system?
 
> +#else
> +#define CANONICAL_MASK(vaddr_bits) GENMASK_ULL(63, vaddr_bits)
> +#endif
> +
> +/*
> + * To make an address canonical either set or clear the bits defined by the
> + * CANONICAL_MASK(). Clear the bits for userspace addresses if the top address
> + * bit is a zero. Set the bits for kernel addresses if the top address bit is a
> + * one.
> + */
>  static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)

+Cc KVM

This is used extensively in KVM code. As far as I can tell, it may be used to determine
whether a guest virtual address is canonical or not. If that’s the case, the result should
depend on whether LAM is enabled for the guest, not the host (and certainly not a host's compile-time option).

>  {
> -	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
> +	return (vaddr & BIT_ULL(63)) ? vaddr | CANONICAL_MASK(vaddr_bits) :
> +				       vaddr & ~CANONICAL_MASK(vaddr_bits);
>  }
>  
>  static __always_inline u64 __is_canonical_address(u64 vaddr, u8 vaddr_bits)


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition
  2026-01-16 14:25   ` Andrey Ryabinin
@ 2026-01-16 14:57     ` Sean Christopherson
  2026-01-16 15:56       ` Maciej Wieczor-Retman
  0 siblings, 1 reply; 53+ messages in thread
From: Sean Christopherson @ 2026-01-16 14:57 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: Maciej Wieczor-Retman, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	Maciej Wieczor-Retman, Alexander Potapenko, linux-kernel,
	Paolo Bonzini, kvm

On Fri, Jan 16, 2026, Andrey Ryabinin wrote:
> On 1/12/26 6:28 PM, Maciej Wieczor-Retman wrote:
> > diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
> > index bcf5cad3da36..b7940fa49e64 100644
> > --- a/arch/x86/include/asm/page.h
> > +++ b/arch/x86/include/asm/page.h
> > @@ -82,9 +82,22 @@ static __always_inline void *pfn_to_kaddr(unsigned long pfn)
> >  	return __va(pfn << PAGE_SHIFT);
> >  }
> >  
> > +#ifdef CONFIG_KASAN_SW_TAGS
> > +#define CANONICAL_MASK(vaddr_bits) (BIT_ULL(63) | BIT_ULL((vaddr_bits) - 1))
> 
> why is the choice of CANONICAL_MASK() gated at compile time? Shouldn’t this be a
> runtime decision based on whether LAM is enabled or not on the running system?
>  
> > +#else
> > +#define CANONICAL_MASK(vaddr_bits) GENMASK_ULL(63, vaddr_bits)
> > +#endif
> > +
> > +/*
> > + * To make an address canonical either set or clear the bits defined by the
> > + * CANONICAL_MASK(). Clear the bits for userspace addresses if the top address
> > + * bit is a zero. Set the bits for kernel addresses if the top address bit is a
> > + * one.
> > + */
> >  static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
> 
> +Cc KVM

Thanks!

> This is used extensively in KVM code. As far as I can tell, it may be used to
> determine whether a guest virtual address is canonical or not.

Yep, KVM uses this both to check canonical addresses and to force a canonical
address (Intel and AMD disagree on the MSR_IA32_SYSENTER_{EIP,ESP} semantics in
64-bit mode) for guest addresses.  This change will break KVM badly if KASAN_SW_TAGS=y.

> case, the result should depend on whether LAM is enabled for the guest, not
> the host (and certainly not a host's compile-time option).

Ya, KVM could roll its own versions, but IMO these super low level helpers should
do exactly what they say.  E.g. at a glance, I'm not sure pt_event_addr_filters_sync()
should be subjected to KASAN_SW_TAGS either.  If that's true, then AFAICT the
_only_ code that wants the LAM-aware behavior is copy_from_kernel_nofault_allowed(),
so maybe just handle it there?  Not sure that's a great long-term maintenance
story either though.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition
  2026-01-16 14:57     ` Sean Christopherson
@ 2026-01-16 15:56       ` Maciej Wieczor-Retman
  2026-01-16 17:00         ` Sean Christopherson
  0 siblings, 1 reply; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-16 15:56 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Andrey Ryabinin, Maciej Wieczor-Retman, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	Alexander Potapenko, linux-kernel, Paolo Bonzini, kvm

On 2026-01-16 at 06:57:04 -0800, Sean Christopherson wrote:
>On Fri, Jan 16, 2026, Andrey Ryabinin wrote:
>> On 1/12/26 6:28 PM, Maciej Wieczor-Retman wrote:
>> > diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
>> > index bcf5cad3da36..b7940fa49e64 100644
>> > --- a/arch/x86/include/asm/page.h
>> > +++ b/arch/x86/include/asm/page.h
>> > @@ -82,9 +82,22 @@ static __always_inline void *pfn_to_kaddr(unsigned long pfn)
>> >  	return __va(pfn << PAGE_SHIFT);
>> >  }
>> >
>> > +#ifdef CONFIG_KASAN_SW_TAGS
>> > +#define CANONICAL_MASK(vaddr_bits) (BIT_ULL(63) | BIT_ULL((vaddr_bits) - 1))
>>
>> why is the choice of CANONICAL_MASK() gated at compile time? Shouldn’t this be a
>> runtime decision based on whether LAM is enabled or not on the running system?

What would be appropriate for KVM? Instead of using #ifdefs checking
if(cpu_feature_enabled(X86_FEATURE_LAM))?

>>
>> > +#else
>> > +#define CANONICAL_MASK(vaddr_bits) GENMASK_ULL(63, vaddr_bits)
>> > +#endif
>> > +
>> > +/*
>> > + * To make an address canonical either set or clear the bits defined by the
>> > + * CANONICAL_MASK(). Clear the bits for userspace addresses if the top address
>> > + * bit is a zero. Set the bits for kernel addresses if the top address bit is a
>> > + * one.
>> > + */
>> >  static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
>>
>> +Cc KVM
>
>Thanks!
>
>> This is used extensively in KVM code. As far as I can tell, it may be used to
>> determine whether a guest virtual address is canonical or not.
>
>Yep, KVM uses this both to check canonical addresses and to force a canonical
>address (Intel and AMD disagree on the MSR_IA32_SYSENTER_{EIP,ESP} semantics in
>64-bit mode) for guest addresses.  This change will break KVM badly if KASAN_SW_TAGS=y.

Oh, thanks! That's good to know.

>
>> case, the result should depend on whether LAM is enabled for the guest, not
>> the host (and certainly not a host's compile-time option).
>
>Ya, KVM could roll its own versions, but IMO these super low level helpers should
>do exactly what they say.  E.g. at a glance, I'm not sure pt_event_addr_filters_sync()
>should be subjected to KASAN_SW_TAGS either.  If that's true, then AFAICT the
>_only_ code that wants the LAM-aware behavior is copy_from_kernel_nofault_allowed(),
>so maybe just handle it there?  Not sure that's a great long-term maintenance
>story either though.

Yes, longterm it's probably best to just get it right in here.

-- 
Kind regards
Maciej Wieczór-Retman

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition
  2026-01-16 15:56       ` Maciej Wieczor-Retman
@ 2026-01-16 17:00         ` Sean Christopherson
  2026-01-16 17:09           ` Maciej Wieczor-Retman
  0 siblings, 1 reply; 53+ messages in thread
From: Sean Christopherson @ 2026-01-16 17:00 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: Andrey Ryabinin, Maciej Wieczor-Retman, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	Alexander Potapenko, linux-kernel, Paolo Bonzini, kvm

On Fri, Jan 16, 2026, Maciej Wieczor-Retman wrote:
> On 2026-01-16 at 06:57:04 -0800, Sean Christopherson wrote:
> >On Fri, Jan 16, 2026, Andrey Ryabinin wrote:
> >> On 1/12/26 6:28 PM, Maciej Wieczor-Retman wrote:
> >> > diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
> >> > index bcf5cad3da36..b7940fa49e64 100644
> >> > --- a/arch/x86/include/asm/page.h
> >> > +++ b/arch/x86/include/asm/page.h
> >> > @@ -82,9 +82,22 @@ static __always_inline void *pfn_to_kaddr(unsigned long pfn)
> >> >  	return __va(pfn << PAGE_SHIFT);
> >> >  }
> >> >
> >> > +#ifdef CONFIG_KASAN_SW_TAGS
> >> > +#define CANONICAL_MASK(vaddr_bits) (BIT_ULL(63) | BIT_ULL((vaddr_bits) - 1))
> >>
> >> why is the choice of CANONICAL_MASK() gated at compile time? Shouldn’t this be a
> >> runtime decision based on whether LAM is enabled or not on the running system?
> 
> What would be appropriate for KVM? Instead of using #ifdefs checking
> if(cpu_feature_enabled(X86_FEATURE_LAM))?

None of the above.  Practically speaking, the kernel APIs simply can't automatically
handle the checks, because they are dependent on guest virtual CPU state, _and_
on the exact operation.  E.g. LAM doesn't apply to inputs to TLB invalidation
instructions like INVVPID and INVPCID.

By the time KVM invokes __is_canonical_address(), KVM has already done the necessary
LAM unmasking.  E.g. having KVM pass in a flag saying it doesn't need LAM masking
would be rather silly.

> >> > +#else
> >> > +#define CANONICAL_MASK(vaddr_bits) GENMASK_ULL(63, vaddr_bits)
> >> > +#endif
> >> > +
> >> > +/*
> >> > + * To make an address canonical either set or clear the bits defined by the
> >> > + * CANONICAL_MASK(). Clear the bits for userspace addresses if the top address
> >> > + * bit is a zero. Set the bits for kernel addresses if the top address bit is a
> >> > + * one.
> >> > + */
> >> >  static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
> >>
> >> +Cc KVM
> >
> >Thanks!
> >
> >> This is used extensively in KVM code. As far as I can tell, it may be used to
> >> determine whether a guest virtual address is canonical or not.
> >
> >Yep, KVM uses this both to check canonical addresses and to force a canonical
> >address (Intel and AMD disagree on the MSR_IA32_SYSENTER_{EIP,ESP} semantics in
> >64-bit mode) for guest addresses.  This change will break KVM badly if KASAN_SW_TAGS=y.
> 
> Oh, thanks! That's good to know.
> 
> >
> >> case, the result should depend on whether LAM is enabled for the guest, not
> >> the host (and certainly not a host's compile-time option).
> >
> >Ya, KVM could roll its own versions, but IMO these super low level helpers should
> >do exactly what they say.  E.g. at a glance, I'm not sure pt_event_addr_filters_sync()
> >should be subjected to KASAN_SW_TAGS either.  If that's true, then AFAICT the
> >_only_ code that wants the LAM-aware behavior is copy_from_kernel_nofault_allowed(),
> >so maybe just handle it there?  Not sure that's a great long-term maintenance
> >story either though.
> 
> Yes, longterm it's probably best to just get it right in here.

As above, I don't think that's feasible, because the context of both the current
(virtual) CPU and the usage matters.  In other words, making __canonical_address()
itself LAM-aware feels wrong.

Actually, the kernel already has to deal with masking LAM bits for userspace
addresses, and this series needs to unmask kernel address in other flows that
effectively consume virtual addresses in software, so why not just do something
similar for copy_from_kernel_nofault_allowed()?

diff --git a/arch/x86/mm/maccess.c b/arch/x86/mm/maccess.c
index 42115ac079cf..0b3c96f8902a 100644
--- a/arch/x86/mm/maccess.c
+++ b/arch/x86/mm/maccess.c
@@ -33,7 +33,8 @@ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
        if (!boot_cpu_data.x86_virt_bits)
                return true;
 
-       return __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
+       return __is_canonical_address(__tag_reset(vaddr),
+                                     boot_cpu_data.x86_virt_bits);
 }
 #else
 bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition
  2026-01-16 17:00         ` Sean Christopherson
@ 2026-01-16 17:09           ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-16 17:09 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Maciej Wieczor-Retman, Andrey Ryabinin, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	Alexander Potapenko, linux-kernel, Paolo Bonzini, kvm

On 2026-01-16 at 09:00:42 -0800, Sean Christopherson wrote:
>On Fri, Jan 16, 2026, Maciej Wieczor-Retman wrote:
>> On 2026-01-16 at 06:57:04 -0800, Sean Christopherson wrote:
>> >On Fri, Jan 16, 2026, Andrey Ryabinin wrote:
>> >> On 1/12/26 6:28 PM, Maciej Wieczor-Retman wrote:
>> >> > diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
>> >> > index bcf5cad3da36..b7940fa49e64 100644
>> >> > --- a/arch/x86/include/asm/page.h
>> >> > +++ b/arch/x86/include/asm/page.h
>> >> > @@ -82,9 +82,22 @@ static __always_inline void *pfn_to_kaddr(unsigned long pfn)
>> >> >  	return __va(pfn << PAGE_SHIFT);
>> >> >  }
>> >> >
>> >> > +#ifdef CONFIG_KASAN_SW_TAGS
>> >> > +#define CANONICAL_MASK(vaddr_bits) (BIT_ULL(63) | BIT_ULL((vaddr_bits) - 1))
>> >>
>> >> why is the choice of CANONICAL_MASK() gated at compile time? Shouldn’t this be a
>> >> runtime decision based on whether LAM is enabled or not on the running system?
>>
>> What would be appropriate for KVM? Instead of using #ifdefs checking
>> if(cpu_feature_enabled(X86_FEATURE_LAM))?
>
>None of the above.  Practically speaking, the kernel APIs simply can't automatically
>handle the checks, because they are dependent on guest virtual CPU state, _and_
>on the exact operation.  E.g. LAM doesn't apply to inputs to TLB invalidation
>instructions like INVVPID and INVPCID.
>
>By the time KVM invokes __is_canonical_address(), KVM has already done the necessary
>LAM unmasking.  E.g. having KVM pass in a flag saying it doesn't need LAM masking
>would be rather silly.

Oh good, then I'll leave this function alone and try to work it out differently.
Thanks!

>
>> >> > +#else
>> >> > +#define CANONICAL_MASK(vaddr_bits) GENMASK_ULL(63, vaddr_bits)
>> >> > +#endif
>> >> > +
>> >> > +/*
>> >> > + * To make an address canonical either set or clear the bits defined by the
>> >> > + * CANONICAL_MASK(). Clear the bits for userspace addresses if the top address
>> >> > + * bit is a zero. Set the bits for kernel addresses if the top address bit is a
>> >> > + * one.
>> >> > + */
>> >> >  static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
>> >>
>> >> +Cc KVM
>> >
>> >Thanks!
>> >
>> >> This is used extensively in KVM code. As far as I can tell, it may be used to
>> >> determine whether a guest virtual address is canonical or not.
>> >
>> >Yep, KVM uses this both to check canonical addresses and to force a canonical
>> >address (Intel and AMD disagree on the MSR_IA32_SYSENTER_{EIP,ESP} semantics in
>> >64-bit mode) for guest addresses.  This change will break KVM badly if KASAN_SW_TAGS=y.
>>
>> Oh, thanks! That's good to know.
>>
>> >
>> >> case, the result should depend on whether LAM is enabled for the guest, not
>> >> the host (and certainly not a host's compile-time option).
>> >
>> >Ya, KVM could roll its own versions, but IMO these super low level helpers should
>> >do exactly what they say.  E.g. at a glance, I'm not sure pt_event_addr_filters_sync()
>> >should be subjected to KASAN_SW_TAGS either.  If that's true, then AFAICT the
>> >_only_ code that wants the LAM-aware behavior is copy_from_kernel_nofault_allowed(),
>> >so maybe just handle it there?  Not sure that's a great long-term maintenance
>> >story either though.
>>
>> Yes, longterm it's probably best to just get it right in here.
>
>As above, I don't think that's feasible, because the context of both the current
>(virtual) CPU and the usage matters.  In other words, making __canonical_address()
>itself LAM-aware feels wrong.
>
>Actually, the kernel already has to deal with masking LAM bits for userspace
>addresses, and this series needs to unmask kernel address in other flows that
>effectively consume virtual addresses in software, so why not just do something
>similar for copy_from_kernel_nofault_allowed()?
>
>diff --git a/arch/x86/mm/maccess.c b/arch/x86/mm/maccess.c
>index 42115ac079cf..0b3c96f8902a 100644
>--- a/arch/x86/mm/maccess.c
>+++ b/arch/x86/mm/maccess.c
>@@ -33,7 +33,8 @@ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
>        if (!boot_cpu_data.x86_virt_bits)
>                return true;
>
>-       return __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
>+       return __is_canonical_address(__tag_reset(vaddr),
>+                                     boot_cpu_data.x86_virt_bits);
> }
> #else
> bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)

Thanks! I'll try that :)

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow
  2026-01-15 16:43         ` Maciej Wieczor-Retman
@ 2026-01-17  1:21           ` Andrey Konovalov
  2026-01-17  6:53             ` Maciej Wieczór-Retman
  2026-01-19 11:40             ` Maciej Wieczor-Retman
  0 siblings, 2 replies; 53+ messages in thread
From: Andrey Konovalov @ 2026-01-17  1:21 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: Maciej Wieczor-Retman, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Vincenzo Frascino, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	kasan-dev, linux-kernel, linux-mm

On Thu, Jan 15, 2026 at 5:43 PM Maciej Wieczor-Retman
<m.wieczorretman@pm.me> wrote:
>
> x86 was easy to do because the kasan_mem_to_shadow() was already in the
> asm/kasan.h. arm64 took a bit more changes since I had to write the
> arch_kasan_non_canonical_hook in a separate file that would import the
> linux/kasan.h header in order to use kasan_mem_to_shadow(). Anyway below are the
> relevant bits from the patch - does that look okay? Or would you prefer some
> different names/placements?

One comment below, otherwise looks fine to me, thanks!

>
> diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h
> index b167e9d3da91..16b1f2ca3ea8 100644
> --- a/arch/arm64/include/asm/kasan.h
> +++ b/arch/arm64/include/asm/kasan.h
> @@ -17,6 +17,8 @@
>
>  asmlinkage void kasan_early_init(void);
>  void kasan_init(void);
> +bool __arch_kasan_non_canonical_hook(unsigned long addr);
> +#define arch_kasan_non_canonical_hook(addr) __arch_kasan_non_canonical_hook(addr)
>
>  #else
>  static inline void kasan_init(void) { }
>
> diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
> index c26489cf96cd..a122ea67eced 100644
> --- a/arch/arm64/mm/Makefile
> +++ b/arch/arm64/mm/Makefile
> @@ -15,4 +15,6 @@ obj-$(CONFIG_ARM64_GCS)               += gcs.o
>  KASAN_SANITIZE_physaddr.o      += n
>
>  obj-$(CONFIG_KASAN)            += kasan_init.o
> +obj-$(CONFIG_KASAN)            += kasan.o
>  KASAN_SANITIZE_kasan_init.o    := n
> +KASAN_SANITIZE_kasan.o         := n
> diff --git a/arch/arm64/mm/kasan.c b/arch/arm64/mm/kasan.c
> new file mode 100644
> index 000000000000..b94d5fb480ca
> --- /dev/null
> +++ b/arch/arm64/mm/kasan.c
> @@ -0,0 +1,31 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * This file contains ARM64 specific KASAN code.
> + */
> +
> +#include <linux/kasan.h>
> +
> +bool __arch_kasan_non_canonical_hook(unsigned long addr) {
> +       /*
> +        * For Software Tag-Based KASAN, kasan_mem_to_shadow() uses the
> +        * arithmetic shift. Normally, this would make checking for a possible
> +        * shadow address complicated, as the shadow address computation
> +        * operation would overflow only for some memory addresses. However, due
> +        * to the chosen KASAN_SHADOW_OFFSET values and the fact the
> +        * kasan_mem_to_shadow() only operates on pointers with the tag reset,
> +        * the overflow always happens.
> +        *
> +        * For arm64, the top byte of the pointer gets reset to 0xFF. Thus, the
> +        * possible shadow addresses belong to a region that is the result of
> +        * kasan_mem_to_shadow() applied to the memory range
> +        * [0xFF000000000000, 0xFFFFFFFFFFFFFFFF]. Despite the overflow, the
> +        * resulting possible shadow region is contiguous, as the overflow
> +        * happens for both 0xFF000000000000 and 0xFFFFFFFFFFFFFFFF.
> +        */
> +       if (IS_ENABLED(CONFIG_KASAN_SW_TAGS)) {
> +               if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0xFFULL << 56)) ||
> +                   addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
> +                       return true;
> +       }
> +       return false;
> +}
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index 9c6ac4b62eb9..146eecae4e9c 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> ...
> @@ -403,6 +409,13 @@ static __always_inline bool kasan_check_byte(const void *addr)
>         return true;
>  }
>
> +#ifndef arch_kasan_non_canonical_hook
> +static inline bool arch_kasan_non_canonical_hook(unsigned long addr)
> +{
> +       return false;
> +}
> +#endif

Let's put this next to kasan_non_canonical_hook declaration.

> +
>  #else /* CONFIG_KASAN */
>
> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> index 62c01b4527eb..1c4893729ff6 100644
> --- a/mm/kasan/report.c
> +++ b/mm/kasan/report.c
> @@ -642,10 +642,19 @@ void kasan_non_canonical_hook(unsigned long addr)
>         const char *bug_type;
>
>         /*
> -        * All addresses that came as a result of the memory-to-shadow mapping
> -        * (even for bogus pointers) must be >= KASAN_SHADOW_OFFSET.
> +        * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift
> +        * and never overflows with the chosen KASAN_SHADOW_OFFSET values. Thus,
> +        * the possible shadow addresses (even for bogus pointers) belong to a
> +        * single contiguous region that is the result of kasan_mem_to_shadow()
> +        * applied to the whole address space.
>          */
> -       if (addr < KASAN_SHADOW_OFFSET)
> +       if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
> +               if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0ULL)) ||
> +                   addr > (unsigned long)kasan_mem_to_shadow((void *)(~0ULL)))
> +                       return;
> +       }
> +
> +       if(arch_kasan_non_canonical_hook(addr))
>                 return;
>
> --
> Kind regards
> Maciej Wieczór-Retman
>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow
  2026-01-17  1:21           ` Andrey Konovalov
@ 2026-01-17  6:53             ` Maciej Wieczór-Retman
  2026-01-19 11:40             ` Maciej Wieczor-Retman
  1 sibling, 0 replies; 53+ messages in thread
From: Maciej Wieczór-Retman @ 2026-01-17  6:53 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: Maciej Wieczor-Retman, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Vincenzo Frascino, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	kasan-dev, linux-kernel, linux-mm

On 2026-01-17 at 02:21:31 +0100, Andrey Konovalov wrote:
>On Thu, Jan 15, 2026 at 5:43 PM Maciej Wieczor-Retman
><m.wieczorretman@pm.me> wrote:
>>
>> x86 was easy to do because the kasan_mem_to_shadow() was already in the
>> asm/kasan.h. arm64 took a bit more changes since I had to write the
>> arch_kasan_non_canonical_hook in a separate file that would import the
>> linux/kasan.h header in order to use kasan_mem_to_shadow(). Anyway below are the
>> relevant bits from the patch - does that look okay? Or would you prefer some
>> different names/placements?
>
>One comment below, otherwise looks fine to me, thanks!
>
...
>> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
>> index 9c6ac4b62eb9..146eecae4e9c 100644
>> --- a/include/linux/kasan.h
>> +++ b/include/linux/kasan.h
>> ...
>> @@ -403,6 +409,13 @@ static __always_inline bool kasan_check_byte(const void *addr)
>>         return true;
>>  }
>>
>> +#ifndef arch_kasan_non_canonical_hook
>> +static inline bool arch_kasan_non_canonical_hook(unsigned long addr)
>> +{
>> +       return false;
>> +}
>> +#endif
>
>Let's put this next to kasan_non_canonical_hook declaration.
>

Sure, will do! Thank :)

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow
  2026-01-17  1:21           ` Andrey Konovalov
  2026-01-17  6:53             ` Maciej Wieczór-Retman
@ 2026-01-19 11:40             ` Maciej Wieczor-Retman
  1 sibling, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-19 11:40 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: Maciej Wieczor-Retman, Andrey Ryabinin, Alexander Potapenko,
	Dmitry Vyukov, Vincenzo Frascino, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Andrew Morton,
	kasan-dev, linux-kernel, linux-mm

On 2026-01-17 at 02:21:31 +0100, Andrey Konovalov wrote:
>On Thu, Jan 15, 2026 at 5:43 PM Maciej Wieczor-Retman
><m.wieczorretman@pm.me> wrote:
>> +#ifndef arch_kasan_non_canonical_hook
>> +static inline bool arch_kasan_non_canonical_hook(unsigned long addr)
>> +{
>> +       return false;
>> +}
>> +#endif
>
>Let's put this next to kasan_non_canonical_hook declaration.

Just occured to me that, as opposed to to kasan_non_canonical_hook(),
arch_kasan_non_canonical_hook() is only used internally in mm/kasan/report.c so
I should toss it into mm/kasan/kasan.h instead.

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
                   ` (15 preceding siblings ...)
  2026-01-13  1:44 ` Andrey Konovalov
@ 2026-01-19 16:33 ` Andrey Ryabinin
  2026-01-19 19:43   ` Maciej Wieczor-Retman
  16 siblings, 1 reply; 53+ messages in thread
From: Andrey Ryabinin @ 2026-01-19 16:33 UTC (permalink / raw)
  To: Maciej Wieczor-Retman, corbet, morbo, rppt, lorenzo.stoakes,
	ubizjak, mingo, vincenzo.frascino, maciej.wieczor-retman, maz,
	catalin.marinas, yeoreum.yun, will, jackmanb, samuel.holland,
	glider, osandov, nsc, luto, jpoimboe, akpm, Liam.Howlett, kees,
	jan.kiszka, thomas.lendacky, jeremy.linton, dvyukov,
	axelrasmussen, leitao, bigeasy, peterz, mark.rutland, urezki,
	brgerst, hpa, mhocko, andreyknvl, weixugc, kbingham, vbabka,
	nathan, trintaeoitogc, samitolvanen, tglx, thuth, surenb,
	anshuman.khandual, smostafa, yuanchu, ada.coupriediaz,
	dave.hansen, kas, nick.desaulniers+lkml, david, bp, ardb,
	justinstitt
  Cc: linux-kernel, linux-mm, kasan-dev, llvm, linux-arm-kernel,
	linux-doc, linux-kbuild, x86



On 1/12/26 6:26 PM, 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.
> 


It appears that GCC nominally supports this, but in practice it does not work.
Here is a minimal reproducer: https://godbolt.org/z/s85e11T5r

As far as I understand, calling a function through a tagged pointer is not
supported by the hardware, so GCC attempts to clear the tag before the call.
This behavior seems to be inherited from the userspace implementation of HWASan (-fsanitize=hwaddress).

I have filed a GCC bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123696

For the kernel, we probably do not want this masking at all, as effectively 99.9–100%
of function pointer calls are expected to be untagged anyway.

Clang does not appear to do this, not even for userspace.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-19 16:33 ` Andrey Ryabinin
@ 2026-01-19 19:43   ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-19 19:43 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: corbet, morbo, rppt, lorenzo.stoakes, ubizjak, mingo,
	vincenzo.frascino, maciej.wieczor-retman, maz, catalin.marinas,
	yeoreum.yun, will, jackmanb, samuel.holland, glider, osandov, nsc,
	luto, jpoimboe, akpm, Liam.Howlett, kees, jan.kiszka,
	thomas.lendacky, jeremy.linton, dvyukov, axelrasmussen, leitao,
	bigeasy, peterz, mark.rutland, urezki, brgerst, hpa, mhocko,
	andreyknvl, weixugc, kbingham, vbabka, nathan, trintaeoitogc,
	samitolvanen, tglx, thuth, surenb, anshuman.khandual, smostafa,
	yuanchu, ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml,
	david, bp, ardb, justinstitt, linux-kernel, linux-mm, kasan-dev,
	llvm, linux-arm-kernel, linux-doc, linux-kbuild, x86

On 2026-01-19 at 17:33:35 +0100, Andrey Ryabinin wrote:
>On 1/12/26 6:26 PM, 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.
>>
>
>It appears that GCC nominally supports this, but in practice it does not work.
>Here is a minimal reproducer: https://godbolt.org/z/s85e11T5r
>
>As far as I understand, calling a function through a tagged pointer is not
>supported by the hardware, so GCC attempts to clear the tag before the call.
>This behavior seems to be inherited from the userspace implementation of HWASan (-fsanitize=hwaddress).
>
>I have filed a GCC bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123696
>
>For the kernel, we probably do not want this masking at all, as effectively 99.9–100%
>of function pointer calls are expected to be untagged anyway.
>
>Clang does not appear to do this, not even for userspace.

Cool, thanks, nice to know why the kernel didn't start with gcc.

I'm going to check in on the bug report every now and then and once it gets
resolved I'll test if everything works as expected on both compilers.

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86
  2026-01-13 17:34     ` Andrew Morton
@ 2026-01-22 17:25       ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 53+ messages in thread
From: Maciej Wieczor-Retman @ 2026-01-22 17:25 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Borislav Petkov, corbet, morbo, rppt, lorenzo.stoakes, ubizjak,
	mingo, vincenzo.frascino, maciej.wieczor-retman, maz,
	catalin.marinas, yeoreum.yun, will, jackmanb, samuel.holland,
	glider, osandov, nsc, luto, jpoimboe, Liam.Howlett, kees,
	jan.kiszka, thomas.lendacky, jeremy.linton, dvyukov,
	axelrasmussen, leitao, ryabinin.a.a, bigeasy, peterz,
	mark.rutland, urezki, brgerst, hpa, mhocko, andreyknvl, weixugc,
	kbingham, vbabka, nathan, trintaeoitogc, samitolvanen, tglx,
	thuth, surenb, anshuman.khandual, smostafa, yuanchu,
	ada.coupriediaz, dave.hansen, kas, nick.desaulniers+lkml, david,
	ardb, justinstitt, linux-kernel, linux-mm, kasan-dev, llvm,
	linux-arm-kernel, linux-doc, linux-kbuild, x86

On 2026-01-13 at 09:34:00 -0800, Andrew Morton wrote:
>On Tue, 13 Jan 2026 12:47:05 +0100 Borislav Petkov <bp@alien8.de> wrote:
>
>> On Mon, Jan 12, 2026 at 10:29:57AM -0800, Andrew Morton wrote:
>> > The review process seems to be proceeding OK so I'll add this to
>> > mm.git's mm-new branch, which is not included in linux-next.  I'll aim
>> > to hold it there for a week while people check the patches over and
>> > send out their acks (please).  Then I hope I can move it into mm.git's
>> > mm-unstable branch where it will receive linux-next exposure.
>> 
>> Yah, you can drop this one and take the next revision after all comments have
>> been addressed.
>
>Cool, I removed the series.

I sent v9 with (I hope) all comments addressed:
https://lore.kernel.org/all/cover.1768845098.git.m.wieczorretman@pm.me/

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2026-01-22 17:26 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-12 17:26 [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Maciej Wieczor-Retman
2026-01-12 17:27 ` [PATCH v8 01/14] kasan: sw_tags: Use arithmetic shift for shadow computation Maciej Wieczor-Retman
2026-01-15 22:42   ` Andrey Ryabinin
2026-01-16 13:11     ` Maciej Wieczor-Retman
2026-01-12 17:27 ` [PATCH v8 02/14] kasan: arm64: x86: Make special tags arch specific Maciej Wieczor-Retman
2026-01-13  1:21   ` Andrey Konovalov
2026-01-13 17:32     ` Maciej Wieczor-Retman
2026-01-16 13:32   ` Andrey Ryabinin
2026-01-12 17:27 ` [PATCH v8 03/14] kasan: Fix inline mode for x86 tag-based mode Maciej Wieczor-Retman
2026-01-16 13:33   ` Andrey Ryabinin
2026-01-12 17:27 ` [PATCH v8 04/14] x86/kasan: Add arch specific kasan functions Maciej Wieczor-Retman
2026-01-13  1:21   ` Andrey Konovalov
2026-01-13 16:12     ` Maciej Wieczor-Retman
2026-01-16 13:35   ` Andrey Ryabinin
2026-01-12 17:27 ` [PATCH v8 05/14] x86/mm: Reset tag for virtual to physical address conversions Maciej Wieczor-Retman
2026-01-12 17:27 ` [PATCH v8 06/14] mm/execmem: Untag addresses in EXECMEM_ROX related pointer arithmetic Maciej Wieczor-Retman
2026-01-12 17:27 ` [PATCH v8 07/14] x86/mm: Physical address comparisons in fill_p*d/pte Maciej Wieczor-Retman
2026-01-12 17:28 ` [PATCH v8 08/14] x86/kasan: KASAN raw shadow memory PTE init Maciej Wieczor-Retman
2026-01-16 13:36   ` Andrey Ryabinin
2026-01-12 17:28 ` [PATCH v8 09/14] x86/mm: LAM compatible non-canonical definition Maciej Wieczor-Retman
2026-01-16 14:25   ` Andrey Ryabinin
2026-01-16 14:57     ` Sean Christopherson
2026-01-16 15:56       ` Maciej Wieczor-Retman
2026-01-16 17:00         ` Sean Christopherson
2026-01-16 17:09           ` Maciej Wieczor-Retman
2026-01-12 17:28 ` [PATCH v8 10/14] x86/mm: LAM initialization Maciej Wieczor-Retman
2026-01-12 17:28 ` [PATCH v8 11/14] x86: Minimal SLAB alignment Maciej Wieczor-Retman
2026-01-12 17:28 ` [PATCH v8 12/14] arm64: Unify software tag-based KASAN inline recovery path Maciej Wieczor-Retman
2026-01-12 17:28 ` [PATCH v8 13/14] x86/kasan: Logical bit shift for kasan_mem_to_shadow Maciej Wieczor-Retman
2026-01-13  1:21   ` Andrey Konovalov
2026-01-14 16:52     ` Maciej Wieczor-Retman
2026-01-15  3:57       ` Andrey Konovalov
2026-01-15 16:43         ` Maciej Wieczor-Retman
2026-01-17  1:21           ` Andrey Konovalov
2026-01-17  6:53             ` Maciej Wieczór-Retman
2026-01-19 11:40             ` Maciej Wieczor-Retman
2026-01-12 17:28 ` [PATCH v8 14/14] x86/kasan: Make software tag-based kasan available Maciej Wieczor-Retman
2026-01-13  1:21   ` Andrey Konovalov
2026-01-13 15:31     ` Maciej Wieczor-Retman
2026-01-13 11:45   ` Borislav Petkov
2026-01-13 16:00     ` Maciej Wieczor-Retman
2026-01-13 16:10       ` Borislav Petkov
2026-01-12 18:29 ` [PATCH v8 00/14] kasan: x86: arm64: KASAN tag-based mode for x86 Andrew Morton
2026-01-12 20:08   ` Maciej Wieczór-Retman
2026-01-12 20:53     ` Andrew Morton
2026-01-13  1:47       ` Andrey Konovalov
2026-01-12 20:27   ` Dave Hansen
2026-01-13 11:47   ` Borislav Petkov
2026-01-13 17:34     ` Andrew Morton
2026-01-22 17:25       ` Maciej Wieczor-Retman
2026-01-13  1:44 ` Andrey Konovalov
2026-01-19 16:33 ` Andrey Ryabinin
2026-01-19 19:43   ` Maciej Wieczor-Retman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox