>From 0145358ae24581b7af36261caee0c6dbe22cce0c Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 15 May 2019 11:45:10 +0200 Subject: [PATCH] loop: Don't change loop device under exclusive opener Loop module allows calling LOOP_SET_FD while there are other openers of the loop device. Even exclusive ones. This can lead to weird consequences such as kernel deadlocks like: mount_bdev() lo_ioctl() udf_fill_super() udf_load_vrs() sb_set_blocksize() - sets desired block size B udf_tread() sb_bread() __bread_gfp(bdev, block, B) loop_set_fd() set_blocksize() - now __getblk_slow() indefinitely loops because B != bdev block size Fix the problem by disallowing LOOP_SET_FD ioctl when there are exclusive openers of a loop device. [Deliberately chosen not to CC stable as a user with priviledges to trigger this race has other means of taking the system down and this has a potential of breaking some weird userspace setup] Reported-by: syzbot+10007d66ca02b08f0e60@syzkaller.appspotmail.com Signed-off-by: Jan Kara --- drivers/block/loop.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 102d79575895..9dcf8bb60c4e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -952,6 +952,9 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, error = -EBUSY; if (lo->lo_state != Lo_unbound) goto out_unlock; + /* Avoid changing loop device under an exclusive opener... */ + if (!(mode & FMODE_EXCL) && bdev->bd_holders > 0) + goto out_unlock; error = loop_validate_file(file, bdev); if (error) -- 2.16.4