Unverified Commit 08ce2fee authored by Szymon Wilczek's avatar Szymon Wilczek Committed by Konstantin Komarov
Browse files

ntfs3: fix circular locking dependency in run_unpack_ex



Syzbot reported a circular locking dependency between wnd->rw_lock
(sbi->used.bitmap) and ni->file.run_lock.

The deadlock scenario:
1. ntfs_extend_mft() takes ni->file.run_lock then wnd->rw_lock.
2. run_unpack_ex() takes wnd->rw_lock then tries to acquire
   ni->file.run_lock inside ntfs_refresh_zone().

This creates an AB-BA deadlock.

Fix this by using down_read_trylock() instead of down_read() when
acquiring run_lock in run_unpack_ex(). If the lock is contended,
skip ntfs_refresh_zone() - the MFT zone will be refreshed on the
next MFT operation. This breaks the circular dependency since we
never block waiting for run_lock while holding wnd->rw_lock.

Reported-by: default avatar <syzbot+d27edf9f96ae85939222@syzkaller.appspotmail.com>
Tested-by: default avatar <syzbot+d27edf9f96ae85939222@syzkaller.appspotmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=d27edf9f96ae85939222


Signed-off-by: default avatarSzymon Wilczek <swilczek.lx@gmail.com>
Signed-off-by: default avatarKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
parent 099ef9ab
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -1131,12 +1131,15 @@ int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
			struct rw_semaphore *lock =
				is_mounted(sbi) ? &sbi->mft.ni->file.run_lock :
						  NULL;
			if (lock)
				down_read(lock);
			if (lock) {
				if (down_read_trylock(lock)) {
					ntfs_refresh_zone(sbi);
			if (lock)
					up_read(lock);
				}
			} else {
				ntfs_refresh_zone(sbi);
			}
		}
		up_write(&wnd->rw_lock);
		if (err)
			return err;