From b0958b1397fb5ffdb995c0ccc74349841929c08d Mon Sep 17 00:00:00 2001 From: Zhao Gongyi Date: Mon, 2 Nov 2026 01:10:30 +0800 Subject: [PATCH] arm64: mm: validate /dev/mem mmap ranges without overflow An arm64 syzkaller reproducer creates a FUSE character device with major:minor 1:1, so opening it uses the /dev/mem file operations. It maps one page from offset 0xfffffffffffff000 at user address zero. The next openat() with a NULL pathname triggers a synchronous external abort (SEA, ESR 0x96000010) in strncpy_from_user() via do_getname(), panicking the kernel. valid_mmap_phys_addr_range() checks the exclusive end by adding the mapping size to the starting address. For this offset, the sum wraps to zero and passes the PHYS_MASK test, allowing an out-of-range PFN to reach remap_pfn_range(). The inclusive-end overflow check in mmap_mem_prepare() does not catch it because the end is ULONG_MAX. Reject starting PFNs outside PHYS_MASK and compare the inclusive length against the remaining physical range without overflowing. This also allows mappings that end exactly at PHYS_MASK, which the old check incorrectly rejects. Fixes: 1d18c47c735e ("arm64: MMU fault handling and page table management") Cc: stable@vger.kernel.org Signed-off-by: Zhao Gongyi [catalin.marinas@arm.com: changed the check to look more like __access_ok()] Signed-off-by: Catalin Marinas --- arch/arm64/mm/mmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c index 32e0771d6477..e212270d4e09 100644 --- a/arch/arm64/mm/mmap.c +++ b/arch/arm64/mm/mmap.c @@ -61,7 +61,9 @@ int valid_phys_addr_range(phys_addr_t addr, size_t size) */ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) { - return !(((pfn << PAGE_SHIFT) + size) & ~PHYS_MASK); + const phys_addr_t limit = PHYS_MASK + 1; + + return size <= limit && pfn <= (limit - size) >> PAGE_SHIFT; } static int __init adjust_protection_map(void)