From: Stefan Hajnoczi Date: Mon, 21 Nov 2022 21:19:23 +0000 (-0500) Subject: block-backend: avoid bdrv_unregister_buf() NULL pointer deref X-Git-Tag: qemu-xen-4.18.0-rc5~404 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=7103895123d580bbe93e341241d200e75d8996a1;p=qemu-xen.git block-backend: avoid bdrv_unregister_buf() NULL pointer deref bdrv_*() APIs expect a valid BlockDriverState. Calling them with bs=NULL leads to undefined behavior. Jonathan Cameron reported this following NULL pointer dereference when a VM with a virtio-blk device and a memory-backend-file object is terminated: 1. qemu_cleanup() closes all drives, setting blk->root to NULL 2. qemu_cleanup() calls user_creatable_cleanup(), which results in a RAM block notifier callback because the memory-backend-file is destroyed. 3. blk_unregister_buf() is called by virtio-blk's BlockRamRegistrar notifier callback and undefined behavior occurs. Fixes: baf422684d73 ("virtio-blk: use BDRV_REQ_REGISTERED_BUF optimization hint") Co-authored-by: Jonathan Cameron Reviewed-by: Kevin Wolf Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Stefan Hajnoczi Message-Id: <20221121211923.1993171-1-stefanha@redhat.com> --- diff --git a/block/block-backend.c b/block/block-backend.c index b48c91f4e1..d98a96ff37 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -2576,14 +2576,25 @@ static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter) bool blk_register_buf(BlockBackend *blk, void *host, size_t size, Error **errp) { + BlockDriverState *bs = blk_bs(blk); + GLOBAL_STATE_CODE(); - return bdrv_register_buf(blk_bs(blk), host, size, errp); + + if (bs) { + return bdrv_register_buf(bs, host, size, errp); + } + return true; } void blk_unregister_buf(BlockBackend *blk, void *host, size_t size) { + BlockDriverState *bs = blk_bs(blk); + GLOBAL_STATE_CODE(); - bdrv_unregister_buf(blk_bs(blk), host, size); + + if (bs) { + bdrv_unregister_buf(bs, host, size); + } } int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,