On Mon, Aug 25, 2025 at 10:27 PM Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx> wrote: > > 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. > - Max value. 0xFD is the highest value that can be randomly generated > for a new tag. > > 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 native kernel tag arch specific for x86 and arm64. > > Replace hardcoded kernel tag value and tag width with macros in KASAN's > non-arch specific code. > > Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx> > --- > 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 | 13 +++++++++++++ > arch/arm64/include/asm/kasan.h | 4 ---- > arch/x86/include/asm/kasan-tags.h | 9 +++++++++ > include/linux/kasan-tags.h | 10 +++++++++- > include/linux/kasan.h | 4 +++- > include/linux/mm.h | 6 +++--- > include/linux/mmzone.h | 1 - > include/linux/page-flags-layout.h | 9 +-------- > 9 files changed, 39 insertions(+), 19 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 fed6cd812d79..788532771832 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -13176,7 +13176,7 @@ L: kasan-dev@xxxxxxxxxxxxxxxx > 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..152465d03508 > --- /dev/null > +++ b/arch/arm64/include/asm/kasan-tags.h > @@ -0,0 +1,13 @@ > +/* 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 */ > + > +#define KASAN_TAG_WIDTH 8 > + > +#ifdef CONFIG_KASAN_HW_TAGS > +#define KASAN_TAG_MIN 0xF0 /* minimum value for random tags */ > +#endif > + > +#endif /* ASM_KASAN_TAGS_H */ > diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h > index 4ab419df8b93..d2841e0fb908 100644 > --- a/arch/arm64/include/asm/kasan.h > +++ b/arch/arm64/include/asm/kasan.h > @@ -7,10 +7,6 @@ > #include <linux/linkage.h> > #include <asm/memory.h> > > -#ifdef CONFIG_KASAN_HW_TAGS > -#define KASAN_TAG_MIN 0xF0 /* minimum value for random tags */ > -#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) > 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 e07c896f95d3..fe80fa8f3315 100644 > --- a/include/linux/kasan-tags.h > +++ b/include/linux/kasan-tags.h > @@ -2,7 +2,15 @@ > #ifndef _LINUX_KASAN_TAGS_H > #define _LINUX_KASAN_TAGS_H > > -#include <asm/kasan.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 > + > +#define KASAN_TAG_MASK ((1UL << KASAN_TAG_WIDTH) - 1) > > #ifndef KASAN_TAG_KERNEL > #define KASAN_TAG_KERNEL 0xFF /* native kernel pointers tag */ > diff --git a/include/linux/kasan.h b/include/linux/kasan.h > index b396feca714f..54481f8c30c5 100644 > --- a/include/linux/kasan.h > +++ b/include/linux/kasan.h > @@ -40,7 +40,9 @@ typedef unsigned int __bitwise kasan_vmalloc_flags_t; > > #ifdef CONFIG_KASAN_SW_TAGS > /* This matches KASAN_TAG_INVALID. */ > -#define KASAN_SHADOW_INIT 0xFE > +#ifndef KASAN_SHADOW_INIT Do we need this ifndef? > +#define KASAN_SHADOW_INIT KASAN_TAG_INVALID > +#endif > #else > #define KASAN_SHADOW_INIT 0 > #endif > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 1ae97a0b8ec7..bb494cb1d5af 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -1692,7 +1692,7 @@ static inline u8 page_kasan_tag(const struct page *page) > > if (kasan_enabled()) { > tag = (page->flags >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK; > - tag ^= 0xff; > + tag ^= KASAN_TAG_KERNEL; > } > > return tag; > @@ -1705,7 +1705,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); > do { > flags = old_flags; > @@ -1724,7 +1724,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/mmzone.h b/include/linux/mmzone.h > index 0c5da9141983..c139fb3d862d 100644 > --- a/include/linux/mmzone.h > +++ b/include/linux/mmzone.h > @@ -1166,7 +1166,6 @@ static inline bool zone_is_empty(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) So we cannot define this here because of include dependencies? Having this value defined here would look cleaner. Otherwise, let's add a comment here with a reference to where this value is defined. > #define ZONEID_MASK ((1UL << ZONEID_SHIFT) - 1) > > static inline enum zone_type page_zonenum(const struct page *page) > 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 This case is removed here but not added to arch/arm64/include/asm/kasan-tags.h. > -#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.50.1 >