Skip to content

Commit 8741d07

Browse files
Ming Leiaxboe
authored andcommitted
ublk: make sure ubq->canceling is set when queue is frozen
Now ublk driver depends on `ubq->canceling` for deciding if the request can be dispatched via uring_cmd & io_uring_cmd_complete_in_task(). Once ubq->canceling is set, the uring_cmd can be done via ublk_cancel_cmd() and io_uring_cmd_done(). So set ubq->canceling when queue is frozen, this way makes sure that the flag can be observed from ublk_queue_rq() reliably, and avoids use-after-free on uring_cmd. Fixes: 216c8f5 ("ublk: replace monitor with cancelable uring_cmd") Signed-off-by: Ming Lei <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 0449173 commit 8741d07

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

drivers/block/ublk_drv.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,17 +1446,27 @@ static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq)
14461446
}
14471447
}
14481448

1449+
/* Must be called when queue is frozen */
1450+
static bool ublk_mark_queue_canceling(struct ublk_queue *ubq)
1451+
{
1452+
bool canceled;
1453+
1454+
spin_lock(&ubq->cancel_lock);
1455+
canceled = ubq->canceling;
1456+
if (!canceled)
1457+
ubq->canceling = true;
1458+
spin_unlock(&ubq->cancel_lock);
1459+
1460+
return canceled;
1461+
}
1462+
14491463
static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq)
14501464
{
1465+
bool was_canceled = ubq->canceling;
14511466
struct gendisk *disk;
14521467

1453-
spin_lock(&ubq->cancel_lock);
1454-
if (ubq->canceling) {
1455-
spin_unlock(&ubq->cancel_lock);
1468+
if (was_canceled)
14561469
return false;
1457-
}
1458-
ubq->canceling = true;
1459-
spin_unlock(&ubq->cancel_lock);
14601470

14611471
spin_lock(&ub->lock);
14621472
disk = ub->ub_disk;
@@ -1468,14 +1478,23 @@ static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq)
14681478
if (!disk)
14691479
return false;
14701480

1471-
/* Now we are serialized with ublk_queue_rq() */
1481+
/*
1482+
* Now we are serialized with ublk_queue_rq()
1483+
*
1484+
* Make sure that ubq->canceling is set when queue is frozen,
1485+
* because ublk_queue_rq() has to rely on this flag for avoiding to
1486+
* touch completed uring_cmd
1487+
*/
14721488
blk_mq_quiesce_queue(disk->queue);
1473-
/* abort queue is for making forward progress */
1474-
ublk_abort_queue(ub, ubq);
1489+
was_canceled = ublk_mark_queue_canceling(ubq);
1490+
if (!was_canceled) {
1491+
/* abort queue is for making forward progress */
1492+
ublk_abort_queue(ub, ubq);
1493+
}
14751494
blk_mq_unquiesce_queue(disk->queue);
14761495
put_device(disk_to_dev(disk));
14771496

1478-
return true;
1497+
return !was_canceled;
14791498
}
14801499

14811500
static void ublk_cancel_cmd(struct ublk_queue *ubq, struct ublk_io *io,

0 commit comments

Comments
 (0)