[stable request] block: stop the timeout timer when releasing a never added disk

Chao Shi <[email protected]>
Newsgroups org.kernel.vger.linux-block,org.kernel.vger.stable
Message-ID <[email protected]>
Hi,

Please consider the following mainline commit for the stable trees:

  26cb8ebbfaf7 ("block: stop the timeout timer when releasing a never
  added disk")

It first appeared in v7.2-rc6 and shipped in v7.2.

Why it should be applied
------------------------

disk_release() undoes blk_mq_init_allocated_queue() for a disk whose
probe failed before add_disk(), but it only calls blk_mq_exit_queue().
Nothing there stops q->timeout, and that timer rolls forward: it stays
pending until it next expires, not until the last request completes.  So
if the driver issued any I/O before adding the disk, the request_queue
is freed while still linked into a timer wheel bucket.

That is a use-after-free.  With KASAN it is reported in
detach_if_pending(), enqueue_timer() or __run_timers(); without KASAN it
shows up as a general protection fault in the timer wheel, in a task
unrelated to the driver that leaked the timer.

  BUG: KASAN: slab-use-after-free in detach_if_pending+0x30c/0x340
  Write of size 8 at addr ffff888004d71310 by task kworker/u8:2/37
   __timer_delete_sync+0x156/0x240 kernel/time/timer.c:1621
   blk_sync_queue+0x22/0x40 block/blk-core.c:222
   nvme_sync_queues+0x100/0x150 drivers/nvme/host/core.c:5362
   nvme_reset_work+0x138/0x930 drivers/nvme/host/pci.c:3264

nvme reaches it because nvme_update_ns_info() submits Report Zones or
FDP io-mgmt-recv on ns->queue before the disk is added, so a later
failure lands in put_disk() with the timer still armed.

Which trees
-----------

All supported branches from 6.1.y up: 7.1.y, 6.18.y, 6.12.y, 6.6.y and
6.1.y.

The regression was introduced by 6f8191fdf41d ("block: simplify disk
shutdown"), which is v6.0, so 5.15.y and 5.10.y are not affected and
should be skipped.

Backport notes
--------------

The commit applies cleanly to all five branches (checked with
git apply --check against block/genhd.c from each branch), so no
backport is needed.  The two helpers it adds calls to, blk_sync_queue()
and blk_mq_cancel_work_sync(), are already called from block/genhd.c on
every one of those branches.

Thanks,
Chao
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.