Thread (13 messages) read the whole thread 13 messages, 3 authors, 2026-02-18

Re: [PATCH v3] arm64: mm: fix pass user prot to ioremap_prot in generic_access_phys

From: Jinjiang Tu <hidden>
Date: 2026-02-05 07:23:49
Also in: linux-mm

在 2026/2/3 17:23, Will Deacon 写道:
On Tue, Feb 03, 2026 at 11:38:15AM +0800, Jinjiang Tu wrote:
quoted
在 2026/2/2 22:55, Will Deacon 写道:
quoted
On Fri, Jan 30, 2026 at 03:38:07PM +0800, Jinjiang Tu wrote:
quoted
Here is a syzkaller error log:
    [0000000020ffc000] pgd=080000010598d403, p4d=080000010598d403, pud=0800000125ddb403,
                       pmd=080000007833c403, pte=01608000007fcfcf
    Unable to handle kernel read from unreadable memory at virtual address ffff80008ea89000
    KASAN: probably user-memory-access in range [0x0000000475448000-0x0000000475448007]
    Mem abort info:
      ESR = 0x000000009600000f
      EC = 0x25: DABT (current EL), IL = 32 bits
      SET = 0, FnV = 0
      EA = 0, S1PTW = 0
      FSC = 0x0f: level 3 permission fault
    Data abort info:
      ISV = 0, ISS = 0x0000000f, ISS2 = 0x00000000
      CM = 0, WnR = 0, TnD = 0, TagAccess = 0
      GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
    swapper pgtable: 4k pages, 48-bit VAs, pgdp=00000001244aa000
    [ffff80008ea89000] pgd=100000013ffff403, p4d=100000013ffff403, pud=100000013fffe403,
		     pmd=100000010a453403, pte=01608000007fcfcf
    Internal error: Oops: 000000009600000f [#1] SMP
    Modules linked in: team
    CPU: 1 PID: 10840 Comm: syz.9.83 Kdump: loaded Tainted: G
    Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
    pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
    pc : __memcpy_fromio+0x80/0xf8
    lr : generic_access_phys+0x20c/0x2b8
    sp : ffff8000a0507960
    x29: ffff8000a0507960 x28: 1ffff000140a0f44 x27: ffff00003833cfe0
    x26: 0000000000000000 x25: 0000000000001000 x24: 0010000000000001
    x23: ffff80008ea89000 x22: ffff00004ea63000 x21: 0000000000001000
    x20: ffff80008ea89000 x19: ffff00004ea62000 x18: 0000000000000000
    x17: 0000000000000000 x16: 0000000000000000 x15: ffff8000806f1e3c
    x14: ffff8000806f1d44 x13: 0000000041b58ab3 x12: ffff7000140a0f23
    x11: 1ffff000140a0f22 x10: ffff7000140a0f22 x9 : ffff800080579d24
    x8 : 0000000000000004 x7 : 0000000000000003 x6 : 0000000000000001
    x5 : ffff8000a0507910 x4 : ffff7000140a0f22 x3 : dfff800000000000
    x2 : 0000000000001000 x1 : ffff80008ea89000 x0 : ffff00004ea62000
    Call trace:
      __memcpy_fromio+0x80/0xf8
      generic_access_phys+0x20c/0x2b8
      __access_remote_vm+0x46c/0x5b8
      access_remote_vm+0x18/0x30
      environ_read+0x238/0x3e8
      vfs_read+0xe4/0x2b0
      ksys_read+0xcc/0x178
      __arm64_sys_read+0x4c/0x68
      invoke_syscall+0x68/0x1a0
      el0_svc_common.constprop.0+0x11c/0x150
      do_el0_svc+0x38/0x50
      el0_svc+0x50/0x258
      el0t_64_sync_handler+0xc0/0xc8
      el0t_64_sync+0x1a4/0x1a8
    Code: 91002339 aa1403f7 8b190276 d503201f (f94002f8)

The local syzkaller first maps I/O address from /dev/mem to userspace,
overiding the stack vma with MAP_FIXED flag. As a result, when reading
/proc/$pid/environ, generic_access_phys() is called to access the region,
which triggers a PAN permission-check fault and causes a kernel access
fault.

The root cause is that generic_access_phys() passes a user pte to
ioremap_prot(), the user pte sets PTE_USER and PTE_NG bits.  Consequently,
any subsequent kernel-mode access to the remapped address raises a fault.

To fix it, define arch_mk_kernel_prot() to convert user prot to kernel
prot for arm64, and call arch_mk_kernel_prot() in generic_access_phys(),
so that a user prot is passed to ioremap_prot().

Fixes: 893dea9ccd08 ("arm64: Add HAVE_IOREMAP_PROT support")
Signed-off-by: Zeng Heng <redacted>
Signed-off-by: Jinjiang Tu <redacted>
---
Changes in v3:
   * arch_mk_kernel_prot() always grant read/write permissions.

   arch/arm64/include/asm/io.h |  8 ++++++++
   mm/memory.c                 | 12 +++++++++++-
   2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 83e03abbb2ca..fe3040d59119 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -267,6 +267,14 @@ int arm64_ioremap_prot_hook_register(const ioremap_prot_hook_t hook);
   #define ioremap_prot ioremap_prot
+#define arch_mk_kernel_prot arch_mk_kernel_prot
+static inline pgprot_t arch_mk_kernel_prot(pgprot_t user_prot)
+{
+	ptdesc_t mem_type = pgprot_val(user_prot) & PTE_ATTRINDX_MASK;
+
+	return __pgprot_modify(PAGE_KERNEL, PTE_ATTRINDX_MASK, mem_type);
+}
Do we really need another arch helper here?
For arc, powerpc, ioremap_prot() simply copy the user pte prot to the kernel page table too.
So maybe we should fix for the two archs too, and we should define a arch helper here.
But I'm not familiar with them.
My point is that we already have the helper: ioremap_prot(). Just fix
that for arm64 and cc the other arch maintainers if you're not sure how
to fix it for them. What we don't need to do is add an additional helper.
ioremap_prot() may be called outside of arch/arm64 in the future, and I think
most of the cases will not pass a user prot to ioremap_prot().

generic_access_phys() is a special case, so I want to limit the modification to
generic_access_phys() only.

Thanks.
Will
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help