Skip to content

Commit bdac616

Browse files
osandovaxboe
authored andcommitted
loop: fix LOOP_GET_STATUS lock imbalance
Commit 2d1d4c1 made loop_get_status() drop lo_ctx_mutex before returning, but the loop_get_status_old(), loop_get_status64(), and loop_get_status_compat() wrappers don't call loop_get_status() if the passed argument is NULL. The callers expect that the lock is dropped, so make sure we drop it in that case, too. Reported-by: syzbot+31e8daa8b3fc129e75f2@syzkaller.appspotmail.com Fixes: 2d1d4c1 ("loop: don't call into filesystem while holding lo_ctl_mutex") Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 1e047ea commit bdac616

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

drivers/block/loop.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,12 +1287,13 @@ static int
12871287
loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) {
12881288
struct loop_info info;
12891289
struct loop_info64 info64;
1290-
int err = 0;
1290+
int err;
12911291

1292-
if (!arg)
1293-
err = -EINVAL;
1294-
if (!err)
1295-
err = loop_get_status(lo, &info64);
1292+
if (!arg) {
1293+
mutex_unlock(&lo->lo_ctl_mutex);
1294+
return -EINVAL;
1295+
}
1296+
err = loop_get_status(lo, &info64);
12961297
if (!err)
12971298
err = loop_info64_to_old(&info64, &info);
12981299
if (!err && copy_to_user(arg, &info, sizeof(info)))
@@ -1304,12 +1305,13 @@ loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) {
13041305
static int
13051306
loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) {
13061307
struct loop_info64 info64;
1307-
int err = 0;
1308+
int err;
13081309

1309-
if (!arg)
1310-
err = -EINVAL;
1311-
if (!err)
1312-
err = loop_get_status(lo, &info64);
1310+
if (!arg) {
1311+
mutex_unlock(&lo->lo_ctl_mutex);
1312+
return -EINVAL;
1313+
}
1314+
err = loop_get_status(lo, &info64);
13131315
if (!err && copy_to_user(arg, &info64, sizeof(info64)))
13141316
err = -EFAULT;
13151317

@@ -1533,12 +1535,13 @@ loop_get_status_compat(struct loop_device *lo,
15331535
struct compat_loop_info __user *arg)
15341536
{
15351537
struct loop_info64 info64;
1536-
int err = 0;
1538+
int err;
15371539

1538-
if (!arg)
1539-
err = -EINVAL;
1540-
if (!err)
1541-
err = loop_get_status(lo, &info64);
1540+
if (!arg) {
1541+
mutex_unlock(&lo->lo_ctl_mutex);
1542+
return -EINVAL;
1543+
}
1544+
err = loop_get_status(lo, &info64);
15421545
if (!err)
15431546
err = loop_info64_to_compat(&info64, arg);
15441547
return err;

0 commit comments

Comments
 (0)