From nobody Sat Jul 25 16:49:27 2026 Received: from canpmsgout07.his.huawei.com (canpmsgout07.his.huawei.com [113.46.200.222]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FA742F0661 for ; Thu, 16 Jul 2026 01:42:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.222 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784166178; cv=none; b=tigmlHwWFthYqWHVj6pckkm2zH6ZLjAyaRrA9Zpb9ZPw+xI+RIQTKMdbkvteEoYmKXbMcC78eK0Dl/Rf9U7oPJP22sEbi6+1zDPqNdpDWEvGXA4ozAPlHh+snWYSELNMWe2eOuhyXMmDHRHKO3J8SpU4436fuqEnilzF9L3Z8AA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784166178; c=relaxed/simple; bh=4uDCwaHKQNs+isT5l+37jh5ZTJVFIoEXAc3yTOdlqGg=; h=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type; b=TisUZvXTb+DQ+ZT2rf58XMk5R0zMF8aPnMUsY07LNNTzEwq+f1VZNk6Iup+4nqncFpPT+qh3X4Y8PNxXIOUcur9rYxL5MKhKgHcbAqjwU+7CPkQUEYmx7hb0BWG/qiyDmKobv47mZYHxtGgHzbtERwlWjZoprS1P6/CmPGs+Puc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=ftree1wa; arc=none smtp.client-ip=113.46.200.222 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="ftree1wa" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=0YLltPeizTaHD27Fn9ffDythfCLu2l1zT8h2w1jiMvo=; b=ftree1watZKga8gU6wNb3X37dDAZx5DBaRpXyIo8dK0PIG+r09OhTLrWbAP+EFMyiLl/mhOg9 wvg47lyIbLvIW25CzZlR/ByYnfIQdNM0i837uVWZP+z0naeGcDqad6oLoyLkpVWq/iwXfJUX62J QYVKNY6oWx7GuSbjyXwVDFc= Received: from mail.maildlp.com (unknown [172.19.163.127]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4h0wXv2KqQzLlXT; Thu, 16 Jul 2026 09:33:19 +0800 (CST) Received: from kwepemj100009.china.huawei.com (unknown [7.202.194.3]) by mail.maildlp.com (Postfix) with ESMTPS id 14F3940572; Thu, 16 Jul 2026 09:42:38 +0800 (CST) Received: from DESKTOP-A37P9LK.huawei.com (10.67.109.17) by kwepemj100009.china.huawei.com (7.202.194.3) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Thu, 16 Jul 2026 09:42:37 +0800 From: Xie Yuanbin To: , , , , , , , , , , , CC: , , , , , , Xie Yuanbin Subject: [PATCH v4] ARM: mm: acquire mmap write lock around show_pte() for user faults Date: Thu, 16 Jul 2026 09:40:22 +0800 Message-ID: <20260716014022.2823-1-xieyuanbin1@huawei.com> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemj100009.china.huawei.com (7.202.194.3) Content-Type: text/plain; charset="utf-8" When CONFIG_DEBUG_USER=3Dy, and cmdline "user_debug=3D31" is set, a user fault may trigger show_pte() without any lock. If another thread in the same process concurrently calls munmap(), the page table pages may be freed while show_pte() is still traversing them, causing a use-after-free in show_pte(). If CONFIG_ARM_LPAE=3Dy, this may cause a kernel panic if the pages table of PMD are freed when show_pte() is running. Acquire mmap_write_lock() around show_pte() for user faults to fix the contention. For user faults, additionally restrict that show_pte() is called only when the addr is a user-space address (addr < TASK_SIZE). This is because the lock of tsk->mm only protects the virtual memory of user address space, furthermore, dumping the page tables of a kernel-space address for user faults is unnecessary and may have security implications. Keep everything unchanged for kernel faults, because the kernel is already in the "oops" state, acquiring a lock may risk a deadlock. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Fixes: 6d021b724481 ("ARM: dump pgd, pmd and pte states on unhandled data a= bort faults") Depends-on: <20260629123349.134224-1-xieyuanbin1@huawei.com> Depends-on: 59e4f3b45b96 ("ARM: ensure interrupts are enabled in __do_user_= fault()") Cc: Russell King Suggested-by: Lorenzo Stoakes Co-developed-by: Qi Xi Signed-off-by: Qi Xi Signed-off-by: Xie Yuanbin Acked-by: Lorenzo Stoakes (ARM) Reviewed-by: Linus Walleij --- For __do_user_fault(), it must be a user fault, so the judgement of user_mode(regs) can be omitted. For do_DataAbort(), it may be a user fault or a kernel fault. If it is a kernel fault, it must be a kernel oops, the kernel will die soon. Also, a user program may be constructed to trigger do_DataAbort()->show_pte(), as described in this mail: Link: https://lore.kernel.org/20260625100031.25088-1-xieyuanbin1@huawei.com For user faults, it is safe to acquire mmap_write_lock(), because we never return to user with mmap lock held or pagefault disabled. Note that, due to the lack of ARMv4T for testing, this patch does not fix the issue in baddataabort()->show_pte(). V3->V4: - Keep nothing change for kernel faults. - Change mmap read lock to write lock. - Restrict that show_pte() is called only when the addr is a user-space address (addr < TASK_SIZE). arch/arm/mm/fault.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index c68677503532..0a09d4ff7718 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -174,21 +174,25 @@ __do_user_fault(unsigned long addr, unsigned int fsr,= unsigned int sig, struct task_struct *tsk =3D current; =20 local_irq_enable(); =20 #ifdef CONFIG_DEBUG_USER if (((user_debug & UDBG_SEGV) && (sig =3D=3D SIGSEGV)) || ((user_debug & UDBG_BUS) && (sig =3D=3D SIGBUS))) { pr_err("8<--- cut here ---\n"); pr_err("%s: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n", tsk->comm, sig, addr, fsr); - show_pte(KERN_ERR, tsk->mm, addr); + if (likely(addr < TASK_SIZE)) { + mmap_write_lock(tsk->mm); + show_pte(KERN_ERR, tsk->mm, addr); + mmap_write_unlock(tsk->mm); + } show_regs(regs); } #endif #ifndef CONFIG_KUSER_HELPERS if ((sig =3D=3D SIGSEGV) && ((addr & PAGE_MASK) =3D=3D 0xffff0000)) printk_ratelimited(KERN_DEBUG "%s: CONFIG_KUSER_HELPERS disabled at 0x%08lx\n", tsk->comm, addr); #endif =20 @@ -632,21 +636,29 @@ do_DataAbort(unsigned long addr, unsigned int fsr, st= ruct pt_regs *regs) =20 if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) return; =20 if (likely(user_mode(regs))) local_irq_enable(); =20 pr_alert("8<--- cut here ---\n"); pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n", inf->name, fsr, addr); - show_pte(KERN_ALERT, current->mm, addr); + if (likely(user_mode(regs))) { + if (addr < TASK_SIZE) { + mmap_write_lock(current->mm); + show_pte(KERN_ALERT, current->mm, addr); + mmap_write_unlock(current->mm); + } + } else { + show_pte(KERN_ALERT, current->mm, addr); + } =20 arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr, fsr, 0); } =20 void __init hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_= regs *), int sig, int code, const char *name) { if (nr < 0 || nr >=3D ARRAY_SIZE(ifsr_info)) --=20 2.53.0