Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

arm64: mm: Fix incomplete tag reset in change_memory_common()

Running KASAN KUnit tests with {HW,SW}_TAGS mode triggers a fault in
change_memory_common():

Call trace:
change_memory_common+0x168/0x210 (P)
set_memory_ro+0x20/0x48
vmalloc_helpers_tags+0xe8/0x338
kunit_try_run_case+0x74/0x188
kunit_generic_run_threadfn_adapter+0x30/0x70
kthread+0x11c/0x200
ret_from_fork+0x10/0x20
---[ end trace 0000000000000000 ]---
# vmalloc_helpers_tags: try faulted
not ok 67 vmalloc_helpers_tags

Commit a06494adb7ef ("arm64: mm: use untagged address to calculate page index")
fixed a KASAN warning in the BPF subsystem by adding kasan_reset_tag() to
the index calculation. In the execmem flow:

bpf_prog_pack_alloc()
-> bpf_jit_alloc_exec()
-> execmem_alloc()

The returned address from execmem_vmalloc/execmem_cache_alloc is passed
through kasan_reset_tag(), so start has no tag while area->addr still
retains the original tag. The fix correctly handled this case by resetting
the tag on area->addr:

(start - (unsigned long)kasan_reset_tag(area->addr)) >> PAGE_SHIFT

However, in normal vmalloc paths, both start and area->addr have matching
tags(or no tags). Resetting only area->addr causes a mismatch when
subtracting a tagged address from an untagged one, resulting in an
incorrect index.

Fix this by resetting tags on both addresses in the index calculation.
This ensures correct results regardless of the tag state of either address.

Tested with KASAN KUnit tests under CONFIG_KASAN_GENERIC,
CONFIG_KASAN_SW_TAGS, and CONFIG_KASAN_HW_TAGS - all pass. Also verified
the original BPF KASAN warning from [1] is still fixed.

[1] https://lore.kernel.org/all/20251118164115.GA3977565@ax162/

Fixes: a06494adb7ef ("arm64: mm: use untagged address to calculate page index")
Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Jiayuan Chen and committed by
Catalin Marinas
5fcd5513 c2803bd5

+4 -2
+4 -2
arch/arm64/mm/pageattr.c
··· 171 171 */ 172 172 area = find_vm_area((void *)addr); 173 173 if (!area || 174 - end > (unsigned long)kasan_reset_tag(area->addr) + area->size || 174 + ((unsigned long)kasan_reset_tag((void *)end) > 175 + (unsigned long)kasan_reset_tag(area->addr) + area->size) || 175 176 ((area->flags & (VM_ALLOC | VM_ALLOW_HUGE_VMAP)) != VM_ALLOC)) 176 177 return -EINVAL; 177 178 ··· 185 184 */ 186 185 if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY || 187 186 pgprot_val(clear_mask) == PTE_RDONLY)) { 188 - unsigned long idx = (start - (unsigned long)kasan_reset_tag(area->addr)) 187 + unsigned long idx = ((unsigned long)kasan_reset_tag((void *)start) - 188 + (unsigned long)kasan_reset_tag(area->addr)) 189 189 >> PAGE_SHIFT; 190 190 for (; numpages; idx++, numpages--) { 191 191 ret = __change_memory_common((u64)page_address(area->pages[idx]),