Christophe Leroy <christophe.leroy@xxxxxx> writes:
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 400f2d0d42f8..3d506589236c 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -356,8 +348,22 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
* between the last mapped region and the stack will
* expand the stack rather than segfaulting.
*/
- if (address + 2048 < uregs->gpr[1] && !store_updates_sp(inst))
- goto bad_area;
+ if (address + 2048 < uregs->gpr[1]) {
+ if (!inst) {
That looks like it could lead to an infinite loop, if the instruction
that caused the fault has been overwritten with NULL by another thread.
Or did I miss something? (I only read the diff)
+ /*
+ * We want to do this outside mmap_sem, because
+ * reading code around nip can result in fault,
+ * which will cause a deadlock when called with
+ * mmap_sem held
+ */
+ up_read(&mm->mmap_sem);
+ __get_user(inst,
+ (unsigned int __user *)regs->nip);
+ if (!store_updates_sp(inst))
+ goto bad_area_nosemaphore;
+ goto retry;
+ }
cheers