summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2005-09-20 17:52:13 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-09-20 17:52:13 +0100
commit840ff6a4f6174d7fe19c206b5f36ff64123a2f45 (patch)
tree1b66816135fad5a97d5ea0862b95341278f4227f
parent5fe10ab19046d84f3fd243436cbd5fa01019e809 (diff)
downloadop-kernel-dev-840ff6a4f6174d7fe19c206b5f36ff64123a2f45.zip
op-kernel-dev-840ff6a4f6174d7fe19c206b5f36ff64123a2f45.tar.gz
[ARM] Prevent deadlock in page fault handler
As per x86, we may deadlock while trying to get the mmap semaphore. Implement the same fix, which allows (eg) recursive faults to cause an oops instead of deadlocking. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mm/fault.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 0b6c4db..4a884ba 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -233,7 +233,17 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
if (in_interrupt() || !mm)
goto no_context;
- down_read(&mm->mmap_sem);
+ /*
+ * As per x86, we may deadlock here. However, since the kernel only
+ * validly references user space from well defined areas of the code,
+ * we can bug out early if this is from code which shouldn't.
+ */
+ if (!down_read_trylock(&mm->mmap_sem)) {
+ if (!user_mode(regs) && !search_exception_tables(regs->ARM_pc))
+ goto no_context;
+ down_read(&mm->mmap_sem);
+ }
+
fault = __do_page_fault(mm, addr, fsr, tsk);
up_read(&mm->mmap_sem);
OpenPOWER on IntegriCloud