Skip to content

Commit 312ca40

Browse files
kevmwMichael Tokarev
authored andcommitted
qcow2: Don't open data_file with BDRV_O_NO_IO
One use case for 'qemu-img info' is verifying that untrusted images don't reference an unwanted external file, be it as a backing file or an external data file. To make sure that calling 'qemu-img info' can't already have undesired side effects with a malicious image, just don't open the data file at all with BDRV_O_NO_IO. If nothing ever tries to do I/O, we don't need to have it open. This changes the output of iotests case 061, which used 'qemu-img info' to show that opening an image with an invalid data file fails. After this patch, it succeeds. Replace this part of the test with a qemu-io call, but keep the final 'qemu-img info' to show that the invalid data file is correctly displayed in the output. Fixes: CVE-2024-4467 Cc: [email protected] Signed-off-by: Kevin Wolf <[email protected]> Reviewed-by: Eric Blake <[email protected]> Reviewed-by: Stefan Hajnoczi <[email protected]> Reviewed-by: Hanna Czenczek <[email protected]> (cherry picked from commit bd385a5) Signed-off-by: Michael Tokarev <[email protected]>
1 parent 68473fd commit 312ca40

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

block/qcow2.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1636,7 +1636,22 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
16361636
goto fail;
16371637
}
16381638

1639-
if (open_data_file) {
1639+
if (open_data_file && (flags & BDRV_O_NO_IO)) {
1640+
/*
1641+
* Don't open the data file for 'qemu-img info' so that it can be used
1642+
* to verify that an untrusted qcow2 image doesn't refer to external
1643+
* files.
1644+
*
1645+
* Note: This still makes has_data_file() return true.
1646+
*/
1647+
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
1648+
s->data_file = NULL;
1649+
} else {
1650+
s->data_file = bs->file;
1651+
}
1652+
qdict_extract_subqdict(options, NULL, "data-file.");
1653+
qdict_del(options, "data-file");
1654+
} else if (open_data_file) {
16401655
/* Open external data file */
16411656
bdrv_graph_co_rdunlock();
16421657
s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs,

tests/qemu-iotests/061

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
326326
echo
327327
_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
328328
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
329-
_img_info --format-specific
329+
$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
330+
$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
330331
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
331332

332333
echo
333334
$QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG"
334-
_img_info --format-specific
335+
$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
336+
$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
335337
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
336338

337339
echo

tests/qemu-iotests/061.out

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
545545
qemu-img: data-file can only be set for images that use an external data file
546546

547547
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data
548-
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory
548+
qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory
549+
read 4096/4096 bytes at offset 0
550+
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
549551
image: TEST_DIR/t.IMGFMT
550552
file format: IMGFMT
551553
virtual size: 64 MiB (67108864 bytes)
@@ -560,7 +562,9 @@ Format specific information:
560562
corrupt: false
561563
extended l2: false
562564

563-
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image
565+
qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image
566+
read 4096/4096 bytes at offset 0
567+
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
564568
image: TEST_DIR/t.IMGFMT
565569
file format: IMGFMT
566570
virtual size: 64 MiB (67108864 bytes)

0 commit comments

Comments
 (0)