Skip to content

Commit 94b7cc0

Browse files
Yang Shitorvalds
authored andcommitted
mm: shmem: disable interrupt when acquiring info->lock in userfaultfd_copy path
Syzbot reported the below lockdep splat: WARNING: possible irq lock inversion dependency detected 5.6.0-rc7-syzkaller #0 Not tainted -------------------------------------------------------- syz-executor.0/10317 just changed the state of lock: ffff888021d16568 (&(&info->lock)->rlock){+.+.}, at: spin_lock include/linux/spinlock.h:338 [inline] ffff888021d16568 (&(&info->lock)->rlock){+.+.}, at: shmem_mfill_atomic_pte+0x1012/0x21c0 mm/shmem.c:2407 but this lock was taken by another, SOFTIRQ-safe lock in the past: (&(&xa->xa_lock)->rlock#5){..-.} and interrupts could create inverse lock ordering between them. other info that might help us debug this: Possible interrupt unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&(&info->lock)->rlock); local_irq_disable(); lock(&(&xa->xa_lock)->rlock#5); lock(&(&info->lock)->rlock); <Interrupt> lock(&(&xa->xa_lock)->rlock#5); *** DEADLOCK *** The full report is quite lengthy, please see: https://lore.kernel.org/linux-mm/[email protected]/T/#m813b412c5f78e25ca8c6c7734886ed4de43f241d It is because CPU 0 held info->lock with IRQ enabled in userfaultfd_copy path, then CPU 1 is splitting a THP which held xa_lock and info->lock in IRQ disabled context at the same time. If softirq comes in to acquire xa_lock, the deadlock would be triggered. The fix is to acquire/release info->lock with *_irq version instead of plain spin_{lock,unlock} to make it softirq safe. Fixes: 4c27fe4 ("userfaultfd: shmem: add shmem_mcopy_atomic_pte for userfaultfd support") Reported-by: [email protected] Signed-off-by: Yang Shi <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Tested-by: [email protected] Acked-by: Hugh Dickins <[email protected]> Cc: Andrea Arcangeli <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent ea0dfeb commit 94b7cc0

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

mm/shmem.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2402,11 +2402,11 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
24022402

24032403
lru_cache_add_anon(page);
24042404

2405-
spin_lock(&info->lock);
2405+
spin_lock_irq(&info->lock);
24062406
info->alloced++;
24072407
inode->i_blocks += BLOCKS_PER_PAGE;
24082408
shmem_recalc_inode(inode);
2409-
spin_unlock(&info->lock);
2409+
spin_unlock_irq(&info->lock);
24102410

24112411
inc_mm_counter(dst_mm, mm_counter_file(page));
24122412
page_add_file_rmap(page, false);

0 commit comments

Comments
 (0)