]> git.proxmox.com Git - mirror_qemu.git/commit - block/block-backend.c
block-backend: prevent dangling BDS pointers across aio_poll()
authorStefan Hajnoczi <stefanha@redhat.com>
Tue, 11 Jan 2022 15:36:12 +0000 (15:36 +0000)
committerKevin Wolf <kwolf@redhat.com>
Fri, 14 Jan 2022 11:03:16 +0000 (12:03 +0100)
commit1e3552dbd28359d35967b7c28dc86cde1bc29205
tree113197d7b02bbfb8dea6951c41864c43267f83bc
parentbb01ea7311004b4a87b510446be689afb7f040ee
block-backend: prevent dangling BDS pointers across aio_poll()

The BlockBackend root child can change when aio_poll() is invoked. This
happens when a temporary filter node is removed upon blockjob
completion, for example.

Functions in block/block-backend.c must be aware of this when using a
blk_bs() pointer across aio_poll() because the BlockDriverState refcnt
may reach 0, resulting in a stale pointer.

One example is scsi_device_purge_requests(), which calls blk_drain() to
wait for in-flight requests to cancel. If the backup blockjob is active,
then the BlockBackend root child is a temporary filter BDS owned by the
blockjob. The blockjob can complete during bdrv_drained_begin() and the
last reference to the BDS is released when the temporary filter node is
removed. This results in a use-after-free when blk_drain() calls
bdrv_drained_end(bs) on the dangling pointer.

Explicitly hold a reference to bs across block APIs that invoke
aio_poll().

Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2021778
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2036178
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20220111153613.25453-2-stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
block/block-backend.c