mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 15:40:03 +02:00
ARM: 9485/1: mm: acquire mmap write lock around show_pte() for user faults
When CONFIG_DEBUG_USER=y, and cmdline "user_debug=31" 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=y, 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.
Co-developed-by: Qi Xi <xiqi2@huawei.com>
Fixes: 6d021b7244 ("ARM: dump pgd, pmd and pte states on unhandled data abort faults")
Link: https://lore.kernel.org/20260716014022.2823-1-xieyuanbin1@huawei.com
Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Qi Xi <xiqi2@huawei.com>
Signed-off-by: Xie Yuanbin <xieyuanbin1@huawei.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
This commit is contained in:
parent
e79ca91165
commit
1039bffd6a
|
|
@ -181,7 +181,11 @@ __do_user_fault(unsigned long addr, unsigned int fsr, unsigned int sig,
|
|||
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
|
||||
|
|
@ -639,7 +643,15 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
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);
|
||||
}
|
||||
|
||||
arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr,
|
||||
fsr, 0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user