diff mbox series

block: Zero block driver state before reopening

Message ID 20250310104858.28221-1-kwolf@redhat.com (mailing list archive)
State New
Headers show
Series block: Zero block driver state before reopening | expand

Commit Message

Kevin Wolf March 10, 2025, 10:48 a.m. UTC
Block drivers assume in their .bdrv_open() implementation that their
state in bs->opaque has been zeroed; it is initially allocated with
g_malloc0() in bdrv_open_driver().

bdrv_snapshot_goto() needs to make sure that it is zeroed again before
calling drv->bdrv_open() to avoid that block drivers use stale values.

One symptom of this bug is VMDK running into a double free when the user
tries to apply an internal snapshot like 'qemu-img snapshot -a test
test.vmdk'. This should be a graceful error because VMDK doesn't support
internal snapshots.

==25507== Invalid free() / delete / delete[] / realloc()
==25507==    at 0x484B347: realloc (vg_replace_malloc.c:1801)
==25507==    by 0x54B592A: g_realloc (gmem.c:171)
==25507==    by 0x1B221D: vmdk_add_extent (../block/vmdk.c:570)
==25507==    by 0x1B1084: vmdk_open_sparse (../block/vmdk.c:1059)
==25507==    by 0x1AF3D8: vmdk_open (../block/vmdk.c:1371)
==25507==    by 0x1A2AE0: bdrv_snapshot_goto (../block/snapshot.c:299)
==25507==    by 0x205C77: img_snapshot (../qemu-img.c:3500)
==25507==    by 0x58FA087: (below main) (libc_start_call_main.h:58)
==25507==  Address 0x832f3e0 is 0 bytes inside a block of size 272 free'd
==25507==    at 0x4846B83: free (vg_replace_malloc.c:989)
==25507==    by 0x54AEAC4: g_free (gmem.c:208)
==25507==    by 0x1AF629: vmdk_close (../block/vmdk.c:2889)
==25507==    by 0x1A2A9C: bdrv_snapshot_goto (../block/snapshot.c:290)
==25507==    by 0x205C77: img_snapshot (../qemu-img.c:3500)
==25507==    by 0x58FA087: (below main) (libc_start_call_main.h:58)

This error was discovered by fuzzing qemu-img.

Cc: qemu-stable@nongnu.org
Reported-by: Denis Rastyogin <gerben@altlinux.org>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/snapshot.c | 1 +
 1 file changed, 1 insertion(+)

Comments

Kevin Wolf March 10, 2025, 11:18 a.m. UTC | #1
Am 10.03.2025 um 11:48 hat Kevin Wolf geschrieben:
> Block drivers assume in their .bdrv_open() implementation that their
> state in bs->opaque has been zeroed; it is initially allocated with
> g_malloc0() in bdrv_open_driver().
> 
> bdrv_snapshot_goto() needs to make sure that it is zeroed again before
> calling drv->bdrv_open() to avoid that block drivers use stale values.
> 
> One symptom of this bug is VMDK running into a double free when the user
> tries to apply an internal snapshot like 'qemu-img snapshot -a test
> test.vmdk'. This should be a graceful error because VMDK doesn't support
> internal snapshots.
> 
> ==25507== Invalid free() / delete / delete[] / realloc()
> ==25507==    at 0x484B347: realloc (vg_replace_malloc.c:1801)
> ==25507==    by 0x54B592A: g_realloc (gmem.c:171)
> ==25507==    by 0x1B221D: vmdk_add_extent (../block/vmdk.c:570)
> ==25507==    by 0x1B1084: vmdk_open_sparse (../block/vmdk.c:1059)
> ==25507==    by 0x1AF3D8: vmdk_open (../block/vmdk.c:1371)
> ==25507==    by 0x1A2AE0: bdrv_snapshot_goto (../block/snapshot.c:299)
> ==25507==    by 0x205C77: img_snapshot (../qemu-img.c:3500)
> ==25507==    by 0x58FA087: (below main) (libc_start_call_main.h:58)
> ==25507==  Address 0x832f3e0 is 0 bytes inside a block of size 272 free'd
> ==25507==    at 0x4846B83: free (vg_replace_malloc.c:989)
> ==25507==    by 0x54AEAC4: g_free (gmem.c:208)
> ==25507==    by 0x1AF629: vmdk_close (../block/vmdk.c:2889)
> ==25507==    by 0x1A2A9C: bdrv_snapshot_goto (../block/snapshot.c:290)
> ==25507==    by 0x205C77: img_snapshot (../qemu-img.c:3500)
> ==25507==    by 0x58FA087: (below main) (libc_start_call_main.h:58)
> 
> This error was discovered by fuzzing qemu-img.
> 
> Cc: qemu-stable@nongnu.org
> Reported-by: Denis Rastyogin <gerben@altlinux.org>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>

Forgot these two lines, which I'll add while applying:

Closes: https://gitlab.com/qemu-project/qemu/-/issues/2853
Closes: https://gitlab.com/qemu-project/qemu/-/issues/2851

Kevin
diff mbox series

Patch

diff --git a/block/snapshot.c b/block/snapshot.c
index 9c44780e96..22567f1fb9 100644
--- a/block/snapshot.c
+++ b/block/snapshot.c
@@ -296,6 +296,7 @@  int bdrv_snapshot_goto(BlockDriverState *bs,
         bdrv_graph_wrunlock();
 
         ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
+        memset(bs->opaque, 0, drv->instance_size);
         open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
         qobject_unref(options);
         if (open_ret < 0) {