]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mm: fix vma_start_write_killable() signal handling
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 28 Nov 2025 04:00:58 +0000 (04:00 +0000)
committerAndrew Morton <akpm@linux-foundation.org>
Sat, 29 Nov 2025 18:41:11 +0000 (10:41 -0800)
If we get a signal, we need to restore the vm_refcnt.  We don't think that
the refcount can actually be decremented to zero here as it requires the
VMA to be detached, and the vma_mark_detached() uses TASK_UNINTERRUPTIBLE.
However, that's a bit subtle, so handle it as if the refcount was zero at
the start of this function.

Link: https://lkml.kernel.org/r/20251128040100.3022561-1-willy@infradead.org
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reported-by: syzbot+5b19bad23ac7f44bf8b8@syzkaller.appspotmail.com
Fixes: 2197bb60f890 ("mm: add vma_start_write_killable()")
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/mmap_lock.c

index e6e5570d1ec7b40eaf365640e29908b5684f33ea..7421b7ea80012146e73b647df4c6a06ca16c0d44 100644 (file)
@@ -74,6 +74,14 @@ static inline int __vma_enter_locked(struct vm_area_struct *vma,
                   refcount_read(&vma->vm_refcnt) == tgt_refcnt,
                   state);
        if (err) {
+               if (refcount_sub_and_test(VMA_LOCK_OFFSET, &vma->vm_refcnt)) {
+                       /*
+                        * The wait failed, but the last reader went away
+                        * as well.  Tell the caller the VMA is detached.
+                        */
+                       WARN_ON_ONCE(!detaching);
+                       err = 0;
+               }
                rwsem_release(&vma->vmlock_dep_map, _RET_IP_);
                return err;
        }