[PATCH v12 06/15] kasan: arm64: x86: Make page_to_virt() KASAN aware
Will Deacon
will at kernel.org
Mon May 18 04:56:51 PDT 2026
On Mon, Mar 30, 2026 at 02:33:43PM +0000, Maciej Wieczor-Retman wrote:
> From: Maciej Wieczor-Retman <maciej.wieczor-retman at intel.com>
>
> Special page_to_virt() implementation is needed if an architecture wants
> to enable KASAN software tag-based mode.
>
> Make page_to_virt() KASAN aware in arch-independent code so
> architectures implementing the software tag-based mode don't have to
> define their own implementations anymore. When KASAN is disabled or for
> architectures that don't implement the software tag-based mode
> page_to_virt() will be optimized to it's previous form.
>
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman at intel.com>
> ---
> Changelog v11:
> - Redo the patch to work on the page_to_virt macro. Split off changes
> about virt to phys conversion to an earlier patch.
> - Remove Alexander's acked-by due to bigger changes.
>
> 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/arm64/include/asm/memory.h | 5 -----
> include/linux/kasan.h | 10 ++++++++++
> include/linux/mm.h | 5 ++++-
> 3 files changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
> index 875c0bd0d85a..39dd0071d3ec 100644
> --- a/arch/arm64/include/asm/memory.h
> +++ b/arch/arm64/include/asm/memory.h
> @@ -411,11 +411,6 @@ static inline unsigned long virt_to_pfn(const void *kaddr)
> */
>
> #if defined(CONFIG_DEBUG_VIRTUAL)
> -#define page_to_virt(x) ({ \
> - __typeof__(x) __page = x; \
> - void *__addr = __va(page_to_phys(__page)); \
> - (void *)__tag_set((const void *)__addr, page_kasan_tag(__page));\
> -})
So here we're using '__page' to avoid multiple evaluations of 'x'...
> #define virt_to_page(x) pfn_to_page(virt_to_pfn(x))
> #else
> #define page_to_virt(x) ({ \
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index e18908f3ad6e..271c59e9f422 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -527,6 +527,11 @@ static inline void *kasan_reset_tag(const void *addr)
> return (void *)arch_kasan_reset_tag(addr);
> }
>
> +static inline void *kasan_set_tag(const void *addr, u8 tag)
> +{
> + return (void *)arch_kasan_set_tag(addr, tag);
> +}
> +
> /**
> * kasan_report - print a report about a bad memory access detected by KASAN
> * @addr: address of the bad access
> @@ -544,6 +549,11 @@ static inline void *kasan_reset_tag(const void *addr)
> return (void *)addr;
> }
>
> +static inline void *kasan_set_tag(const void *addr, u8 tag)
> +{
> + return (void *)addr;
> +}
> +
> #endif /* CONFIG_KASAN_SW_TAGS || CONFIG_KASAN_HW_TAGS*/
>
> #ifdef CONFIG_KASAN_HW_TAGS
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 09044934dda8..f234650a4edf 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -117,7 +117,10 @@ extern int mmap_rnd_compat_bits __read_mostly;
> #endif
>
> #ifndef page_to_virt
> -#define page_to_virt(x) __va(PFN_PHYS(page_to_pfn(x)))
> +#define page_to_virt(x) ({ \
> + void *__addr = __va(PFN_PHYS(page_to_pfn((struct page *)x))); \
> + kasan_set_tag(__addr, page_kasan_tag(x)); \
> +})
... but in the new code you're proposing, you evaluate 'x' twice.
Is there a reason not to take the arm64 code as-is?
Will
More information about the linux-arm-kernel
mailing list