From 48b4d932d6fafa03f8ef5c8ecf0e77cd1e91c9eb Mon Sep 17 00:00:00 2001 From: Yun Zhou Date: Tue, 2 Jun 2026 02:55:43 +0800 Subject: [PATCH] ublk: fix null-ptr-deref in ublk_queue_cmd ublk_queue_cmd() dereferences ios[tag].cmd without NULL check. The cmd pointer can be NULL when ublk_cancel_cmd() races with IO dispatch during server teardown: CPU0 (partition scan work) CPU1 (io_uring cancel callback) ublk_queue_rq() ublk_prep_req() -> OK check canceling -> false ublk_start_cancel() quiesce, set canceling, unquiesce ublk_cancel_cmd() io->cmd = NULL ublk_queue_cmd() cmd = ios[tag].cmd -> NULL ublk_get_uring_cmd_pdu(cmd) -> null-ptr-deref The race window exists because ublk_cancel_cmd() can execute between the canceling flag check and the cmd dereference in ublk_queue_cmd(). This cannot be closed with simple synchronization since blk_mq_quiesce_queue only waits for in-flight dispatches, not requests already past the canceling check. Fix by checking cmd for NULL before dereferencing. When NULL, abort the request via __ublk_abort_rq() which handles both recovery (requeue) and non-recovery (end with IOERR) cases. Fixes: 71f28f3136af ("ublk_drv: add io_uring based userspace block driver") Reported-by: syzbot+415b9ec753cd2a196087@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=415b9ec753cd2a196087 Signed-off-by: Yun Zhou --- drivers/block/ublk_drv.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 6c041eaebdb91..656e0d4e92bbf 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -2090,8 +2090,14 @@ static void ublk_batch_queue_cmd(struct ublk_queue *ubq, struct request *rq, boo static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq) { struct io_uring_cmd *cmd = ubq->ios[rq->tag].cmd; - struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); + struct ublk_uring_cmd_pdu *pdu; + + if (unlikely(!cmd)) { + __ublk_abort_rq(ubq, rq); + return; + } + pdu = ublk_get_uring_cmd_pdu(cmd); pdu->req = rq; io_uring_cmd_complete_in_task(cmd, ublk_cmd_tw_cb); }