mm: fix double mmap_sem unlock on MMF_UNSTABLE enforced SIGBUS
[linux-2.6-microblaze.git] / mm / memory.c
index e158f7a..c717b5b 100644 (file)
@@ -3910,8 +3910,18 @@ int handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
         * further.
         */
        if (unlikely((current->flags & PF_KTHREAD) && !(ret & VM_FAULT_ERROR)
-                               && test_bit(MMF_UNSTABLE, &vma->vm_mm->flags)))
+                               && test_bit(MMF_UNSTABLE, &vma->vm_mm->flags))) {
+
+               /*
+                * We are going to enforce SIGBUS but the PF path might have
+                * dropped the mmap_sem already so take it again so that
+                * we do not break expectations of all arch specific PF paths
+                * and g-u-p
+                */
+               if (ret & VM_FAULT_RETRY)
+                       down_read(&vma->vm_mm->mmap_sem);
                ret = VM_FAULT_SIGBUS;
+       }
 
        return ret;
 }