Skip to content

Commit f40139f

Browse files
Ming Leiaxboe
authored andcommitted
ublk: fix race between io_uring_cmd_complete_in_task and ublk_cancel_cmd
ublk_cancel_cmd() calls io_uring_cmd_done() to complete uring_cmd, but we may have scheduled task work via io_uring_cmd_complete_in_task() for dispatching request, then kernel crash can be triggered. Fix it by not trying to canceling the command if ublk block request is started. Fixes: 216c8f5 ("ublk: replace monitor with cancelable uring_cmd") Reported-by: Jared Holzman <jholzman@nvidia.com> Tested-by: Jared Holzman <jholzman@nvidia.com> Closes: https://lore.kernel.org/linux-block/d2179120-171b-47ba-b664-23242981ef19@nvidia.com/ Signed-off-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20250425013742.1079549-3-ming.lei@redhat.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent d6aa0c1 commit f40139f

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

drivers/block/ublk_drv.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,14 +1683,31 @@ static void ublk_start_cancel(struct ublk_queue *ubq)
16831683
ublk_put_disk(disk);
16841684
}
16851685

1686-
static void ublk_cancel_cmd(struct ublk_queue *ubq, struct ublk_io *io,
1686+
static void ublk_cancel_cmd(struct ublk_queue *ubq, unsigned tag,
16871687
unsigned int issue_flags)
16881688
{
1689+
struct ublk_io *io = &ubq->ios[tag];
1690+
struct ublk_device *ub = ubq->dev;
1691+
struct request *req;
16891692
bool done;
16901693

16911694
if (!(io->flags & UBLK_IO_FLAG_ACTIVE))
16921695
return;
16931696

1697+
/*
1698+
* Don't try to cancel this command if the request is started for
1699+
* avoiding race between io_uring_cmd_done() and
1700+
* io_uring_cmd_complete_in_task().
1701+
*
1702+
* Either the started request will be aborted via __ublk_abort_rq(),
1703+
* then this uring_cmd is canceled next time, or it will be done in
1704+
* task work function ublk_dispatch_req() because io_uring guarantees
1705+
* that ublk_dispatch_req() is always called
1706+
*/
1707+
req = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], tag);
1708+
if (req && blk_mq_request_started(req))
1709+
return;
1710+
16941711
spin_lock(&ubq->cancel_lock);
16951712
done = !!(io->flags & UBLK_IO_FLAG_CANCELED);
16961713
if (!done)
@@ -1722,7 +1739,6 @@ static void ublk_uring_cmd_cancel_fn(struct io_uring_cmd *cmd,
17221739
struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
17231740
struct ublk_queue *ubq = pdu->ubq;
17241741
struct task_struct *task;
1725-
struct ublk_io *io;
17261742

17271743
if (WARN_ON_ONCE(!ubq))
17281744
return;
@@ -1737,9 +1753,8 @@ static void ublk_uring_cmd_cancel_fn(struct io_uring_cmd *cmd,
17371753
if (!ubq->canceling)
17381754
ublk_start_cancel(ubq);
17391755

1740-
io = &ubq->ios[pdu->tag];
1741-
WARN_ON_ONCE(io->cmd != cmd);
1742-
ublk_cancel_cmd(ubq, io, issue_flags);
1756+
WARN_ON_ONCE(ubq->ios[pdu->tag].cmd != cmd);
1757+
ublk_cancel_cmd(ubq, pdu->tag, issue_flags);
17431758
}
17441759

17451760
static inline bool ublk_queue_ready(struct ublk_queue *ubq)
@@ -1752,7 +1767,7 @@ static void ublk_cancel_queue(struct ublk_queue *ubq)
17521767
int i;
17531768

17541769
for (i = 0; i < ubq->q_depth; i++)
1755-
ublk_cancel_cmd(ubq, &ubq->ios[i], IO_URING_F_UNLOCKED);
1770+
ublk_cancel_cmd(ubq, i, IO_URING_F_UNLOCKED);
17561771
}
17571772

17581773
/* Cancel all pending commands, must be called after del_gendisk() returns */

0 commit comments

Comments
 (0)