diff options
| author | Vijay Anusuri <vanusuri@mvista.com> | 2024-09-06 14:56:27 +0530 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2024-09-16 06:09:56 -0700 |
| commit | d0429def9e227ef70e97739c33387c88a70b2bde (patch) | |
| tree | d3b912a98d4880e8ecf7d271c5644f66c57d14b7 /meta | |
| parent | bfbf6d481d4d9d21fd624528c8a61ccc64fadc4c (diff) | |
| download | poky-d0429def9e227ef70e97739c33387c88a70b2bde.tar.gz | |
qemu: Backport fix for CVE-2024-4467
A flaw was found in the QEMU disk image utility (qemu-img) 'info' command. A specially crafted image file containing a `json:{}` value describing block devices in QMP could cause the qemu-img process on the host to consume large amounts of memory or CPU time, leading to denial of service or read/write to an existing external file.
Reference:
https://nvd.nist.gov/vuln/detail/CVE-2024-4467
Upstream commits:
https://gitlab.com/qemu-project/qemu/-/commit/bd385a5298d7062668e804d73944d52aec9549f1
https://gitlab.com/qemu-project/qemu/-/commit/2eb42a728d27a43fdcad5f37d3f65706ce6deba5
https://gitlab.com/qemu-project/qemu/-/commit/7e1110664ecbc4826f3c978ccb06b6c1bce823e6
https://gitlab.com/qemu-project/qemu/-/commit/83930780325b144a5908c45b3957b9b6457b3831
https://gitlab.com/qemu-project/qemu/-/commit/7ead946998610657d38d1a505d5f25300d4ca613
(From OE-Core rev: c23ad8c89c3dd5b6004677cd0b534e22a293134d)
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta')
| -rw-r--r-- | meta/recipes-devtools/qemu/qemu.inc | 5 | ||||
| -rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch | 214 | ||||
| -rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch | 73 | ||||
| -rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch | 76 | ||||
| -rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch | 571 | ||||
| -rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch | 265 |
6 files changed, 1204 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc index 4684e44524..6ff3c2f9bc 100644 --- a/meta/recipes-devtools/qemu/qemu.inc +++ b/meta/recipes-devtools/qemu/qemu.inc | |||
| @@ -113,6 +113,11 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \ | |||
| 113 | file://CVE-2024-7409-0002.patch \ | 113 | file://CVE-2024-7409-0002.patch \ |
| 114 | file://CVE-2024-7409-0003.patch \ | 114 | file://CVE-2024-7409-0003.patch \ |
| 115 | file://CVE-2024-7409-0004.patch \ | 115 | file://CVE-2024-7409-0004.patch \ |
| 116 | file://CVE-2024-4467-0001.patch \ | ||
| 117 | file://CVE-2024-4467-0002.patch \ | ||
| 118 | file://CVE-2024-4467-0003.patch \ | ||
| 119 | file://CVE-2024-4467-0004.patch \ | ||
| 120 | file://CVE-2024-4467-0005.patch \ | ||
| 116 | " | 121 | " |
| 117 | UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" | 122 | UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" |
| 118 | 123 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch new file mode 100644 index 0000000000..f7c6e7aaab --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch | |||
| @@ -0,0 +1,214 @@ | |||
| 1 | From 5cdbc87ab24a8cc4cf926158ec429d43d8a45f15 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jon Maloy <jmaloy@redhat.com> | ||
| 3 | Date: Wed, 5 Jun 2024 19:56:51 -0400 | ||
| 4 | Subject: [PATCH 1/5] qcow2: Don't open data_file with BDRV_O_NO_IO | ||
| 5 | MIME-Version: 1.0 | ||
| 6 | Content-Type: text/plain; charset=UTF-8 | ||
| 7 | Content-Transfer-Encoding: 8bit | ||
| 8 | |||
| 9 | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||
| 10 | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||
| 11 | RH-Jira: RHEL-35616 | ||
| 12 | RH-CVE: CVE-2024-4467 | ||
| 13 | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||
| 14 | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 15 | RH-Commit: [1/5] 2e72d21c14d86645cf68eec78f49d5cc5d77581f | ||
| 16 | |||
| 17 | Conflicts: qcow2_do_open(): missing boolean ´open_data_file'. | ||
| 18 | We assume it to be true. | ||
| 19 | |||
| 20 | commit f9843ce5c519901654a7d8ba43ee95ce25ca13c2 | ||
| 21 | Author: Kevin Wolf <kwolf@redhat.com> | ||
| 22 | Date: Thu Apr 11 15:06:01 2024 +0200 | ||
| 23 | |||
| 24 | qcow2: Don't open data_file with BDRV_O_NO_IO | ||
| 25 | |||
| 26 | One use case for 'qemu-img info' is verifying that untrusted images | ||
| 27 | don't reference an unwanted external file, be it as a backing file or an | ||
| 28 | external data file. To make sure that calling 'qemu-img info' can't | ||
| 29 | already have undesired side effects with a malicious image, just don't | ||
| 30 | open the data file at all with BDRV_O_NO_IO. If nothing ever tries to do | ||
| 31 | I/O, we don't need to have it open. | ||
| 32 | |||
| 33 | This changes the output of iotests case 061, which used 'qemu-img info' | ||
| 34 | to show that opening an image with an invalid data file fails. After | ||
| 35 | this patch, it succeeds. Replace this part of the test with a qemu-io | ||
| 36 | call, but keep the final 'qemu-img info' to show that the invalid data | ||
| 37 | file is correctly displayed in the output. | ||
| 38 | |||
| 39 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
| 40 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
| 41 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 42 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 43 | Upstream: N/A, embargoed | ||
| 44 | Signed-off-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 45 | |||
| 46 | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||
| 47 | |||
| 48 | Upstream-Status: Backport [import from rhel8 qemu-kvm-6.2.0-50.module+el8.10.0+22027+db0a70a4.src.rpm | ||
| 49 | Upstream commit https://gitlab.com/qemu-project/qemu/-/commit/bd385a5298d7062668e804d73944d52aec9549f1] | ||
| 50 | CVE: CVE-2024-4467 | ||
| 51 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
| 52 | --- | ||
| 53 | block/qcow2.c | 87 +++++++++++++++++++++++--------------- | ||
| 54 | tests/qemu-iotests/061 | 6 ++- | ||
| 55 | tests/qemu-iotests/061.out | 8 +++- | ||
| 56 | 3 files changed, 62 insertions(+), 39 deletions(-) | ||
| 57 | |||
| 58 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
| 59 | index d509016756..6ee1919612 100644 | ||
| 60 | --- a/block/qcow2.c | ||
| 61 | +++ b/block/qcow2.c | ||
| 62 | @@ -1613,50 +1613,67 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, | ||
| 63 | goto fail; | ||
| 64 | } | ||
| 65 | |||
| 66 | - /* Open external data file */ | ||
| 67 | - s->data_file = bdrv_open_child(NULL, options, "data-file", bs, | ||
| 68 | - &child_of_bds, BDRV_CHILD_DATA, | ||
| 69 | - true, errp); | ||
| 70 | - if (*errp) { | ||
| 71 | - ret = -EINVAL; | ||
| 72 | - goto fail; | ||
| 73 | - } | ||
| 74 | + if (flags & BDRV_O_NO_IO) { | ||
| 75 | + /* | ||
| 76 | + * Don't open the data file for 'qemu-img info' so that it can be used | ||
| 77 | + * to verify that an untrusted qcow2 image doesn't refer to external | ||
| 78 | + * files. | ||
| 79 | + * | ||
| 80 | + * Note: This still makes has_data_file() return true. | ||
| 81 | + */ | ||
| 82 | + if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { | ||
| 83 | + s->data_file = NULL; | ||
| 84 | + } else { | ||
| 85 | + s->data_file = bs->file; | ||
| 86 | + } | ||
| 87 | + qdict_extract_subqdict(options, NULL, "data-file."); | ||
| 88 | + qdict_del(options, "data-file"); | ||
| 89 | + } else { | ||
| 90 | + /* Open external data file */ | ||
| 91 | + s->data_file = bdrv_open_child(NULL, options, "data-file", bs, | ||
| 92 | + &child_of_bds, BDRV_CHILD_DATA, | ||
| 93 | + true, errp); | ||
| 94 | + if (*errp) { | ||
| 95 | + ret = -EINVAL; | ||
| 96 | + goto fail; | ||
| 97 | + } | ||
| 98 | |||
| 99 | - if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { | ||
| 100 | - if (!s->data_file && s->image_data_file) { | ||
| 101 | - s->data_file = bdrv_open_child(s->image_data_file, options, | ||
| 102 | - "data-file", bs, &child_of_bds, | ||
| 103 | - BDRV_CHILD_DATA, false, errp); | ||
| 104 | + if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { | ||
| 105 | + if (!s->data_file && s->image_data_file) { | ||
| 106 | + s->data_file = bdrv_open_child(s->image_data_file, options, | ||
| 107 | + "data-file", bs, &child_of_bds, | ||
| 108 | + BDRV_CHILD_DATA, false, errp); | ||
| 109 | + if (!s->data_file) { | ||
| 110 | + ret = -EINVAL; | ||
| 111 | + goto fail; | ||
| 112 | + } | ||
| 113 | + } | ||
| 114 | if (!s->data_file) { | ||
| 115 | + error_setg(errp, "'data-file' is required for this image"); | ||
| 116 | ret = -EINVAL; | ||
| 117 | goto fail; | ||
| 118 | } | ||
| 119 | - } | ||
| 120 | - if (!s->data_file) { | ||
| 121 | - error_setg(errp, "'data-file' is required for this image"); | ||
| 122 | - ret = -EINVAL; | ||
| 123 | - goto fail; | ||
| 124 | - } | ||
| 125 | |||
| 126 | - /* No data here */ | ||
| 127 | - bs->file->role &= ~BDRV_CHILD_DATA; | ||
| 128 | + /* No data here */ | ||
| 129 | + bs->file->role &= ~BDRV_CHILD_DATA; | ||
| 130 | |||
| 131 | - /* Must succeed because we have given up permissions if anything */ | ||
| 132 | - bdrv_child_refresh_perms(bs, bs->file, &error_abort); | ||
| 133 | - } else { | ||
| 134 | - if (s->data_file) { | ||
| 135 | - error_setg(errp, "'data-file' can only be set for images with an " | ||
| 136 | - "external data file"); | ||
| 137 | - ret = -EINVAL; | ||
| 138 | - goto fail; | ||
| 139 | - } | ||
| 140 | + /* Must succeed because we have given up permissions if anything */ | ||
| 141 | + bdrv_child_refresh_perms(bs, bs->file, &error_abort); | ||
| 142 | + } else { | ||
| 143 | + if (s->data_file) { | ||
| 144 | + error_setg(errp, "'data-file' can only be set for images with an " | ||
| 145 | + "external data file"); | ||
| 146 | + ret = -EINVAL; | ||
| 147 | + goto fail; | ||
| 148 | + } | ||
| 149 | |||
| 150 | - s->data_file = bs->file; | ||
| 151 | + s->data_file = bs->file; | ||
| 152 | |||
| 153 | - if (data_file_is_raw(bs)) { | ||
| 154 | - error_setg(errp, "data-file-raw requires a data file"); | ||
| 155 | - ret = -EINVAL; | ||
| 156 | - goto fail; | ||
| 157 | + if (data_file_is_raw(bs)) { | ||
| 158 | + error_setg(errp, "data-file-raw requires a data file"); | ||
| 159 | + ret = -EINVAL; | ||
| 160 | + goto fail; | ||
| 161 | + } | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 | ||
| 166 | index 9507c223bd..6a5bd47efc 100755 | ||
| 167 | --- a/tests/qemu-iotests/061 | ||
| 168 | +++ b/tests/qemu-iotests/061 | ||
| 169 | @@ -322,12 +322,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" | ||
| 170 | echo | ||
| 171 | _make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M | ||
| 172 | $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" | ||
| 173 | -_img_info --format-specific | ||
| 174 | +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt | ||
| 175 | +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io | ||
| 176 | TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts | ||
| 177 | |||
| 178 | echo | ||
| 179 | $QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" | ||
| 180 | -_img_info --format-specific | ||
| 181 | +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt | ||
| 182 | +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io | ||
| 183 | TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts | ||
| 184 | |||
| 185 | echo | ||
| 186 | diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out | ||
| 187 | index 7ecbd4dea8..99b2307a23 100644 | ||
| 188 | --- a/tests/qemu-iotests/061.out | ||
| 189 | +++ b/tests/qemu-iotests/061.out | ||
| 190 | @@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
| 191 | qemu-img: data-file can only be set for images that use an external data file | ||
| 192 | |||
| 193 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data | ||
| 194 | -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory | ||
| 195 | +qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory | ||
| 196 | +read 4096/4096 bytes at offset 0 | ||
| 197 | +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
| 198 | image: TEST_DIR/t.IMGFMT | ||
| 199 | file format: IMGFMT | ||
| 200 | virtual size: 64 MiB (67108864 bytes) | ||
| 201 | @@ -560,7 +562,9 @@ Format specific information: | ||
| 202 | corrupt: false | ||
| 203 | extended l2: false | ||
| 204 | |||
| 205 | -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image | ||
| 206 | +qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image | ||
| 207 | +read 4096/4096 bytes at offset 0 | ||
| 208 | +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
| 209 | image: TEST_DIR/t.IMGFMT | ||
| 210 | file format: IMGFMT | ||
| 211 | virtual size: 64 MiB (67108864 bytes) | ||
| 212 | -- | ||
| 213 | 2.39.3 | ||
| 214 | |||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch new file mode 100644 index 0000000000..901ca7036d --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | From 3cb587f460ec432f329fb83df034bbb7e79e17aa Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jon Maloy <jmaloy@redhat.com> | ||
| 3 | Date: Wed, 5 Jun 2024 19:56:51 -0400 | ||
| 4 | Subject: [PATCH 2/5] iotests/244: Don't store data-file with protocol in image | ||
| 5 | |||
| 6 | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||
| 7 | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||
| 8 | RH-Jira: RHEL-35616 | ||
| 9 | RH-CVE: CVE-2024-4467 | ||
| 10 | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||
| 11 | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 12 | RH-Commit: [2/5] a422cfdba938e1bd857008ccbbddc695011ae0ff | ||
| 13 | |||
| 14 | commit 92e00dab8be1570b13172353d77d2af44cb4e22b | ||
| 15 | Author: Kevin Wolf <kwolf@redhat.com> | ||
| 16 | Date: Thu Apr 25 14:49:40 2024 +0200 | ||
| 17 | |||
| 18 | iotests/244: Don't store data-file with protocol in image | ||
| 19 | |||
| 20 | We want to disable filename parsing for data files because it's too easy | ||
| 21 | to abuse in malicious image files. Make the test ready for the change by | ||
| 22 | passing the data file explicitly in command line options. | ||
| 23 | |||
| 24 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
| 25 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
| 26 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 27 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 28 | Upstream: N/A, embargoed | ||
| 29 | Signed-off-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 30 | |||
| 31 | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||
| 32 | |||
| 33 | Upstream-Status: Backport [import from rhel8 qemu-kvm-6.2.0-50.module+el8.10.0+22027+db0a70a4.src.rpm | ||
| 34 | Upstream commit https://gitlab.com/qemu-project/qemu/-/commit/2eb42a728d27a43fdcad5f37d3f65706ce6deba5] | ||
| 35 | CVE: CVE-2024-4467 | ||
| 36 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
| 37 | --- | ||
| 38 | tests/qemu-iotests/244 | 19 ++++++++++++++++--- | ||
| 39 | 1 file changed, 16 insertions(+), 3 deletions(-) | ||
| 40 | |||
| 41 | diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244 | ||
| 42 | index 3e61fa25bb..bb9cc6512f 100755 | ||
| 43 | --- a/tests/qemu-iotests/244 | ||
| 44 | +++ b/tests/qemu-iotests/244 | ||
| 45 | @@ -215,9 +215,22 @@ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" | ||
| 46 | $QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" | ||
| 47 | |||
| 48 | # blkdebug doesn't support copy offloading, so this tests the error path | ||
| 49 | -$QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG" | ||
| 50 | -$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" | ||
| 51 | -$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" | ||
| 52 | +test_img_with_blkdebug="json:{ | ||
| 53 | + 'driver': 'qcow2', | ||
| 54 | + 'file': { | ||
| 55 | + 'driver': 'file', | ||
| 56 | + 'filename': '$TEST_IMG' | ||
| 57 | + }, | ||
| 58 | + 'data-file': { | ||
| 59 | + 'driver': 'blkdebug', | ||
| 60 | + 'image': { | ||
| 61 | + 'driver': 'file', | ||
| 62 | + 'filename': '$TEST_IMG.data' | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | +}" | ||
| 66 | +$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$test_img_with_blkdebug" | ||
| 67 | +$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$test_img_with_blkdebug" | ||
| 68 | |||
| 69 | echo | ||
| 70 | echo "=== Flushing should flush the data file ===" | ||
| 71 | -- | ||
| 72 | 2.39.3 | ||
| 73 | |||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch new file mode 100644 index 0000000000..89b4bbea5b --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | From 59a84673079f9763e9507733e308442397aba703 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jon Maloy <jmaloy@redhat.com> | ||
| 3 | Date: Wed, 5 Jun 2024 19:56:51 -0400 | ||
| 4 | Subject: [PATCH 3/5] iotests/270: Don't store data-file with json: prefix in | ||
| 5 | image | ||
| 6 | |||
| 7 | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||
| 8 | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||
| 9 | RH-Jira: RHEL-35616 | ||
| 10 | RH-CVE: CVE-2024-4467 | ||
| 11 | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||
| 12 | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 13 | RH-Commit: [3/5] ac08690fd3ea3af6e24b2f6a8beedcfe469917a8 | ||
| 14 | |||
| 15 | commit 705bcc2819ce8e0f8b9d660a93bc48de26413aec | ||
| 16 | Author: Kevin Wolf <kwolf@redhat.com> | ||
| 17 | Date: Thu Apr 25 14:49:40 2024 +0200 | ||
| 18 | |||
| 19 | iotests/270: Don't store data-file with json: prefix in image | ||
| 20 | |||
| 21 | We want to disable filename parsing for data files because it's too easy | ||
| 22 | to abuse in malicious image files. Make the test ready for the change by | ||
| 23 | passing the data file explicitly in command line options. | ||
| 24 | |||
| 25 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
| 26 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
| 27 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 28 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 29 | Upstream: N/A, embargoed | ||
| 30 | Signed-off-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 31 | |||
| 32 | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||
| 33 | |||
| 34 | Upstream-Status: Backport [import from rhel8 qemu-kvm-6.2.0-50.module+el8.10.0+22027+db0a70a4.src.rpm | ||
| 35 | Upstream commit https://gitlab.com/qemu-project/qemu/-/commit/7e1110664ecbc4826f3c978ccb06b6c1bce823e6] | ||
| 36 | CVE: CVE-2024-4467 | ||
| 37 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
| 38 | --- | ||
| 39 | tests/qemu-iotests/270 | 14 +++++++++++--- | ||
| 40 | 1 file changed, 11 insertions(+), 3 deletions(-) | ||
| 41 | |||
| 42 | diff --git a/tests/qemu-iotests/270 b/tests/qemu-iotests/270 | ||
| 43 | index 74352342db..c37b674aa2 100755 | ||
| 44 | --- a/tests/qemu-iotests/270 | ||
| 45 | +++ b/tests/qemu-iotests/270 | ||
| 46 | @@ -60,8 +60,16 @@ _make_test_img -o cluster_size=2M,data_file="$TEST_IMG.orig" \ | ||
| 47 | # "write" 2G of data without using any space. | ||
| 48 | # (qemu-img create does not like it, though, because null-co does not | ||
| 49 | # support image creation.) | ||
| 50 | -$QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ | ||
| 51 | - "$TEST_IMG" | ||
| 52 | +test_img_with_null_data="json:{ | ||
| 53 | + 'driver': '$IMGFMT', | ||
| 54 | + 'file': { | ||
| 55 | + 'filename': '$TEST_IMG' | ||
| 56 | + }, | ||
| 57 | + 'data-file': { | ||
| 58 | + 'driver': 'null-co', | ||
| 59 | + 'size':'4294967296' | ||
| 60 | + } | ||
| 61 | +}" | ||
| 62 | |||
| 63 | # This gives us a range of: | ||
| 64 | # 2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31 | ||
| 65 | @@ -74,7 +82,7 @@ $QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ | ||
| 66 | # on L2 boundaries, we need large L2 tables; hence the cluster size of | ||
| 67 | # 2 MB. (Anything from 256 kB should work, though, because then one L2 | ||
| 68 | # table covers 8 GB.) | ||
| 69 | -$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$TEST_IMG" | _filter_qemu_io | ||
| 70 | +$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$test_img_with_null_data" | _filter_qemu_io | ||
| 71 | |||
| 72 | _check_test_img | ||
| 73 | |||
| 74 | -- | ||
| 75 | 2.39.3 | ||
| 76 | |||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch new file mode 100644 index 0000000000..9fc653cbcb --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch | |||
| @@ -0,0 +1,571 @@ | |||
| 1 | From 996680dd6d5afd51918e600126dbfed4dfe89e05 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jon Maloy <jmaloy@redhat.com> | ||
| 3 | Date: Sun, 9 Jun 2024 23:08:39 -0400 | ||
| 4 | Subject: [PATCH 4/5] block: introduce bdrv_open_file_child() helper | ||
| 5 | |||
| 6 | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||
| 7 | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||
| 8 | RH-Jira: RHEL-35616 | ||
| 9 | RH-CVE: CVE-2024-4467 | ||
| 10 | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||
| 11 | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 12 | RH-Commit: [4/5] 9f582a9aff740eb9ec6f64bfec94854038d8545f | ||
| 13 | |||
| 14 | Conflicts: - copy-before-write.c::cbw_copy() is an older version than | ||
| 15 | upstream, but introduction of the new function is | ||
| 16 | straight-forward. | ||
| 17 | - include/block/block-global-state.h doesn't exist in this | ||
| 18 | code version. Adding the prototype to | ||
| 19 | include/block/block.h instead. | ||
| 20 | - struct BlockDriver has no field 'filtered_child_is_backing' | ||
| 21 | We remove the corresponding assert() in the new function. | ||
| 22 | |||
| 23 | commit 83930780325b144a5908c45b3957b9b6457b3831 | ||
| 24 | Author: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | ||
| 25 | Date: Tue Jul 26 23:11:21 2022 +0300 | ||
| 26 | |||
| 27 | block: introduce bdrv_open_file_child() helper | ||
| 28 | |||
| 29 | Almost all drivers call bdrv_open_child() similarly. Let's create a | ||
| 30 | helper for this. | ||
| 31 | |||
| 32 | The only not updated drivers that call bdrv_open_child() to set | ||
| 33 | bs->file are raw-format and snapshot-access: | ||
| 34 | raw-format sometimes want to have filtered child but | ||
| 35 | don't set drv->is_filter to true. | ||
| 36 | snapshot-access wants only DATA | PRIMARY | ||
| 37 | |||
| 38 | Possibly we should implement drv->is_filter_func() handler, to consider | ||
| 39 | raw-format as filter when it works as filter.. But it's another story. | ||
| 40 | |||
| 41 | Note also, that we decrease assignments to bs->file in code: it helps | ||
| 42 | us restrict modifying this field in further commit. | ||
| 43 | |||
| 44 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | ||
| 45 | Reviewed-by: Hanna Reitz <hreitz@redhat.com> | ||
| 46 | Message-Id: <20220726201134.924743-3-vsementsov@yandex-team.ru> | ||
| 47 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
| 48 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
| 49 | |||
| 50 | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||
| 51 | |||
| 52 | Upstream-Status: Backport [import from rhel8 qemu-kvm-6.2.0-50.module+el8.10.0+22027+db0a70a4.src.rpm | ||
| 53 | Upstream commit https://gitlab.com/qemu-project/qemu/-/commit/83930780325b144a5908c45b3957b9b6457b3831] | ||
| 54 | CVE: CVE-2024-4467 | ||
| 55 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
| 56 | --- | ||
| 57 | block.c | 18 ++++++++++++++++++ | ||
| 58 | block/blkdebug.c | 9 +++------ | ||
| 59 | block/blklogwrites.c | 7 ++----- | ||
| 60 | block/blkreplay.c | 7 ++----- | ||
| 61 | block/blkverify.c | 9 +++------ | ||
| 62 | block/bochs.c | 7 +++---- | ||
| 63 | block/cloop.c | 7 +++---- | ||
| 64 | block/copy-before-write.c | 9 ++++----- | ||
| 65 | block/copy-on-read.c | 9 ++++----- | ||
| 66 | block/crypto.c | 11 ++++++----- | ||
| 67 | block/dmg.c | 7 +++---- | ||
| 68 | block/filter-compress.c | 8 +++----- | ||
| 69 | block/parallels.c | 7 +++---- | ||
| 70 | block/preallocate.c | 9 ++++----- | ||
| 71 | block/qcow.c | 6 ++---- | ||
| 72 | block/qcow2.c | 8 ++++---- | ||
| 73 | block/qed.c | 8 ++++---- | ||
| 74 | block/replication.c | 8 +++----- | ||
| 75 | block/throttle.c | 8 +++----- | ||
| 76 | block/vdi.c | 7 +++---- | ||
| 77 | block/vhdx.c | 7 +++---- | ||
| 78 | block/vmdk.c | 7 +++---- | ||
| 79 | block/vpc.c | 7 +++---- | ||
| 80 | include/block/block.h | 3 +++ | ||
| 81 | 24 files changed, 92 insertions(+), 101 deletions(-) | ||
| 82 | |||
| 83 | diff --git a/block.c b/block.c | ||
| 84 | index 0ac5b163d2..889f878565 100644 | ||
| 85 | --- a/block.c | ||
| 86 | +++ b/block.c | ||
| 87 | @@ -3546,6 +3546,24 @@ BdrvChild *bdrv_open_child(const char *filename, | ||
| 88 | errp); | ||
| 89 | } | ||
| 90 | |||
| 91 | +/* | ||
| 92 | + * Wrapper on bdrv_open_child() for most popular case: open primary child of bs. | ||
| 93 | + */ | ||
| 94 | +int bdrv_open_file_child(const char *filename, | ||
| 95 | + QDict *options, const char *bdref_key, | ||
| 96 | + BlockDriverState *parent, Error **errp) | ||
| 97 | +{ | ||
| 98 | + BdrvChildRole role; | ||
| 99 | + | ||
| 100 | + role = parent->drv->is_filter ? | ||
| 101 | + (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE; | ||
| 102 | + | ||
| 103 | + parent->file = bdrv_open_child(filename, options, bdref_key, parent, | ||
| 104 | + &child_of_bds, role, false, errp); | ||
| 105 | + | ||
| 106 | + return parent->file ? 0 : -EINVAL; | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | /* | ||
| 110 | * TODO Future callers may need to specify parent/child_class in order for | ||
| 111 | * option inheritance to work. Existing callers use it for the root node. | ||
| 112 | diff --git a/block/blkdebug.c b/block/blkdebug.c | ||
| 113 | index bbf2948703..5fcfc8ac6f 100644 | ||
| 114 | --- a/block/blkdebug.c | ||
| 115 | +++ b/block/blkdebug.c | ||
| 116 | @@ -503,12 +503,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 117 | } | ||
| 118 | |||
| 119 | /* Open the image file */ | ||
| 120 | - bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image", | ||
| 121 | - bs, &child_of_bds, | ||
| 122 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 123 | - false, errp); | ||
| 124 | - if (!bs->file) { | ||
| 125 | - ret = -EINVAL; | ||
| 126 | + ret = bdrv_open_file_child(qemu_opt_get(opts, "x-image"), options, "image", | ||
| 127 | + bs, errp); | ||
| 128 | + if (ret < 0) { | ||
| 129 | goto out; | ||
| 130 | } | ||
| 131 | |||
| 132 | diff --git a/block/blklogwrites.c b/block/blklogwrites.c | ||
| 133 | index f7a251e91f..f66a617eb3 100644 | ||
| 134 | --- a/block/blklogwrites.c | ||
| 135 | +++ b/block/blklogwrites.c | ||
| 136 | @@ -155,11 +155,8 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 137 | } | ||
| 138 | |||
| 139 | /* Open the file */ | ||
| 140 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 141 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false, | ||
| 142 | - errp); | ||
| 143 | - if (!bs->file) { | ||
| 144 | - ret = -EINVAL; | ||
| 145 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 146 | + if (ret < 0) { | ||
| 147 | goto fail; | ||
| 148 | } | ||
| 149 | |||
| 150 | diff --git a/block/blkreplay.c b/block/blkreplay.c | ||
| 151 | index dcbe780ddb..76a0b8d12a 100644 | ||
| 152 | --- a/block/blkreplay.c | ||
| 153 | +++ b/block/blkreplay.c | ||
| 154 | @@ -26,11 +26,8 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 155 | int ret; | ||
| 156 | |||
| 157 | /* Open the image file */ | ||
| 158 | - bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds, | ||
| 159 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 160 | - false, errp); | ||
| 161 | - if (!bs->file) { | ||
| 162 | - ret = -EINVAL; | ||
| 163 | + ret = bdrv_open_file_child(NULL, options, "image", bs, errp); | ||
| 164 | + if (ret < 0) { | ||
| 165 | goto fail; | ||
| 166 | } | ||
| 167 | |||
| 168 | diff --git a/block/blkverify.c b/block/blkverify.c | ||
| 169 | index d1facf5ba9..920e891684 100644 | ||
| 170 | --- a/block/blkverify.c | ||
| 171 | +++ b/block/blkverify.c | ||
| 172 | @@ -121,12 +121,9 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 173 | } | ||
| 174 | |||
| 175 | /* Open the raw file */ | ||
| 176 | - bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw", | ||
| 177 | - bs, &child_of_bds, | ||
| 178 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 179 | - false, errp); | ||
| 180 | - if (!bs->file) { | ||
| 181 | - ret = -EINVAL; | ||
| 182 | + ret = bdrv_open_file_child(qemu_opt_get(opts, "x-raw"), options, "raw", | ||
| 183 | + bs, errp); | ||
| 184 | + if (ret < 0) { | ||
| 185 | goto fail; | ||
| 186 | } | ||
| 187 | |||
| 188 | diff --git a/block/bochs.c b/block/bochs.c | ||
| 189 | index 4d68658087..b2dc06bbfd 100644 | ||
| 190 | --- a/block/bochs.c | ||
| 191 | +++ b/block/bochs.c | ||
| 192 | @@ -110,10 +110,9 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 193 | return ret; | ||
| 194 | } | ||
| 195 | |||
| 196 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 197 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 198 | - if (!bs->file) { | ||
| 199 | - return -EINVAL; | ||
| 200 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 201 | + if (ret < 0) { | ||
| 202 | + return ret; | ||
| 203 | } | ||
| 204 | |||
| 205 | ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs)); | ||
| 206 | diff --git a/block/cloop.c b/block/cloop.c | ||
| 207 | index b8c6d0eccd..bee87da173 100644 | ||
| 208 | --- a/block/cloop.c | ||
| 209 | +++ b/block/cloop.c | ||
| 210 | @@ -71,10 +71,9 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 211 | return ret; | ||
| 212 | } | ||
| 213 | |||
| 214 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 215 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 216 | - if (!bs->file) { | ||
| 217 | - return -EINVAL; | ||
| 218 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 219 | + if (ret < 0) { | ||
| 220 | + return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | /* read header */ | ||
| 224 | diff --git a/block/copy-before-write.c b/block/copy-before-write.c | ||
| 225 | index c30a5ff8de..8aa2cb6a85 100644 | ||
| 226 | --- a/block/copy-before-write.c | ||
| 227 | +++ b/block/copy-before-write.c | ||
| 228 | @@ -150,12 +150,11 @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 229 | { | ||
| 230 | BDRVCopyBeforeWriteState *s = bs->opaque; | ||
| 231 | BdrvDirtyBitmap *copy_bitmap; | ||
| 232 | + int ret; | ||
| 233 | |||
| 234 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 235 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 236 | - false, errp); | ||
| 237 | - if (!bs->file) { | ||
| 238 | - return -EINVAL; | ||
| 239 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 240 | + if (ret < 0) { | ||
| 241 | + return ret; | ||
| 242 | } | ||
| 243 | |||
| 244 | s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds, | ||
| 245 | diff --git a/block/copy-on-read.c b/block/copy-on-read.c | ||
| 246 | index 1fc7fb3333..815ac1d835 100644 | ||
| 247 | --- a/block/copy-on-read.c | ||
| 248 | +++ b/block/copy-on-read.c | ||
| 249 | @@ -41,12 +41,11 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 250 | BDRVStateCOR *state = bs->opaque; | ||
| 251 | /* Find a bottom node name, if any */ | ||
| 252 | const char *bottom_node = qdict_get_try_str(options, "bottom"); | ||
| 253 | + int ret; | ||
| 254 | |||
| 255 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 256 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 257 | - false, errp); | ||
| 258 | - if (!bs->file) { | ||
| 259 | - return -EINVAL; | ||
| 260 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 261 | + if (ret < 0) { | ||
| 262 | + return ret; | ||
| 263 | } | ||
| 264 | |||
| 265 | bs->supported_read_flags = BDRV_REQ_PREFETCH; | ||
| 266 | diff --git a/block/crypto.c b/block/crypto.c | ||
| 267 | index c8ba4681e2..abfce39230 100644 | ||
| 268 | --- a/block/crypto.c | ||
| 269 | +++ b/block/crypto.c | ||
| 270 | @@ -260,15 +260,14 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, | ||
| 271 | { | ||
| 272 | BlockCrypto *crypto = bs->opaque; | ||
| 273 | QemuOpts *opts = NULL; | ||
| 274 | - int ret = -EINVAL; | ||
| 275 | + int ret; | ||
| 276 | QCryptoBlockOpenOptions *open_opts = NULL; | ||
| 277 | unsigned int cflags = 0; | ||
| 278 | QDict *cryptoopts = NULL; | ||
| 279 | |||
| 280 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 281 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 282 | - if (!bs->file) { | ||
| 283 | - return -EINVAL; | ||
| 284 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 285 | + if (ret < 0) { | ||
| 286 | + return ret; | ||
| 287 | } | ||
| 288 | |||
| 289 | bs->supported_write_flags = BDRV_REQ_FUA & | ||
| 290 | @@ -276,6 +275,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, | ||
| 291 | |||
| 292 | opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort); | ||
| 293 | if (!qemu_opts_absorb_qdict(opts, options, errp)) { | ||
| 294 | + ret = -EINVAL; | ||
| 295 | goto cleanup; | ||
| 296 | } | ||
| 297 | |||
| 298 | @@ -284,6 +284,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, | ||
| 299 | |||
| 300 | open_opts = block_crypto_open_opts_init(cryptoopts, errp); | ||
| 301 | if (!open_opts) { | ||
| 302 | + ret = -EINVAL; | ||
| 303 | goto cleanup; | ||
| 304 | } | ||
| 305 | |||
| 306 | diff --git a/block/dmg.c b/block/dmg.c | ||
| 307 | index 447901fbb8..38c363dd39 100644 | ||
| 308 | --- a/block/dmg.c | ||
| 309 | +++ b/block/dmg.c | ||
| 310 | @@ -439,10 +439,9 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 311 | return ret; | ||
| 312 | } | ||
| 313 | |||
| 314 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 315 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 316 | - if (!bs->file) { | ||
| 317 | - return -EINVAL; | ||
| 318 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 319 | + if (ret < 0) { | ||
| 320 | + return ret; | ||
| 321 | } | ||
| 322 | |||
| 323 | block_module_load_one("dmg-bz2"); | ||
| 324 | diff --git a/block/filter-compress.c b/block/filter-compress.c | ||
| 325 | index d5be538619..305716c86c 100644 | ||
| 326 | --- a/block/filter-compress.c | ||
| 327 | +++ b/block/filter-compress.c | ||
| 328 | @@ -30,11 +30,9 @@ | ||
| 329 | static int compress_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 330 | Error **errp) | ||
| 331 | { | ||
| 332 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 333 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 334 | - false, errp); | ||
| 335 | - if (!bs->file) { | ||
| 336 | - return -EINVAL; | ||
| 337 | + int ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 338 | + if (ret < 0) { | ||
| 339 | + return ret; | ||
| 340 | } | ||
| 341 | |||
| 342 | if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) { | ||
| 343 | diff --git a/block/parallels.c b/block/parallels.c | ||
| 344 | index 6ebad2a2bb..ed4debd899 100644 | ||
| 345 | --- a/block/parallels.c | ||
| 346 | +++ b/block/parallels.c | ||
| 347 | @@ -735,10 +735,9 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 348 | Error *local_err = NULL; | ||
| 349 | char *buf; | ||
| 350 | |||
| 351 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 352 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 353 | - if (!bs->file) { | ||
| 354 | - return -EINVAL; | ||
| 355 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 356 | + if (ret < 0) { | ||
| 357 | + return ret; | ||
| 358 | } | ||
| 359 | |||
| 360 | ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph)); | ||
| 361 | diff --git a/block/preallocate.c b/block/preallocate.c | ||
| 362 | index 1d4233f730..332408bdc9 100644 | ||
| 363 | --- a/block/preallocate.c | ||
| 364 | +++ b/block/preallocate.c | ||
| 365 | @@ -134,6 +134,7 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 366 | Error **errp) | ||
| 367 | { | ||
| 368 | BDRVPreallocateState *s = bs->opaque; | ||
| 369 | + int ret; | ||
| 370 | |||
| 371 | /* | ||
| 372 | * s->data_end and friends should be initialized on permission update. | ||
| 373 | @@ -141,11 +142,9 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 374 | */ | ||
| 375 | s->file_end = s->zero_start = s->data_end = -EINVAL; | ||
| 376 | |||
| 377 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 378 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 379 | - false, errp); | ||
| 380 | - if (!bs->file) { | ||
| 381 | - return -EINVAL; | ||
| 382 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 383 | + if (ret < 0) { | ||
| 384 | + return ret; | ||
| 385 | } | ||
| 386 | |||
| 387 | if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) { | ||
| 388 | diff --git a/block/qcow.c b/block/qcow.c | ||
| 389 | index c39940f33e..544a17261f 100644 | ||
| 390 | --- a/block/qcow.c | ||
| 391 | +++ b/block/qcow.c | ||
| 392 | @@ -120,10 +120,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 393 | qdict_extract_subqdict(options, &encryptopts, "encrypt."); | ||
| 394 | encryptfmt = qdict_get_try_str(encryptopts, "format"); | ||
| 395 | |||
| 396 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 397 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 398 | - if (!bs->file) { | ||
| 399 | - ret = -EINVAL; | ||
| 400 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 401 | + if (ret < 0) { | ||
| 402 | goto fail; | ||
| 403 | } | ||
| 404 | |||
| 405 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
| 406 | index 6ee1919612..29ea157e6b 100644 | ||
| 407 | --- a/block/qcow2.c | ||
| 408 | +++ b/block/qcow2.c | ||
| 409 | @@ -1907,11 +1907,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 410 | .errp = errp, | ||
| 411 | .ret = -EINPROGRESS | ||
| 412 | }; | ||
| 413 | + int ret; | ||
| 414 | |||
| 415 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 416 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 417 | - if (!bs->file) { | ||
| 418 | - return -EINVAL; | ||
| 419 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 420 | + if (ret < 0) { | ||
| 421 | + return ret; | ||
| 422 | } | ||
| 423 | |||
| 424 | /* Initialise locks */ | ||
| 425 | diff --git a/block/qed.c b/block/qed.c | ||
| 426 | index 558d3646c4..e3b06a3d00 100644 | ||
| 427 | --- a/block/qed.c | ||
| 428 | +++ b/block/qed.c | ||
| 429 | @@ -558,11 +558,11 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 430 | .errp = errp, | ||
| 431 | .ret = -EINPROGRESS | ||
| 432 | }; | ||
| 433 | + int ret; | ||
| 434 | |||
| 435 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 436 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 437 | - if (!bs->file) { | ||
| 438 | - return -EINVAL; | ||
| 439 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 440 | + if (ret < 0) { | ||
| 441 | + return ret; | ||
| 442 | } | ||
| 443 | |||
| 444 | bdrv_qed_init_state(bs); | ||
| 445 | diff --git a/block/replication.c b/block/replication.c | ||
| 446 | index 55c8f894aa..2f17397764 100644 | ||
| 447 | --- a/block/replication.c | ||
| 448 | +++ b/block/replication.c | ||
| 449 | @@ -88,11 +88,9 @@ static int replication_open(BlockDriverState *bs, QDict *options, | ||
| 450 | const char *mode; | ||
| 451 | const char *top_id; | ||
| 452 | |||
| 453 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 454 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 455 | - false, errp); | ||
| 456 | - if (!bs->file) { | ||
| 457 | - return -EINVAL; | ||
| 458 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 459 | + if (ret < 0) { | ||
| 460 | + return ret; | ||
| 461 | } | ||
| 462 | |||
| 463 | ret = -EINVAL; | ||
| 464 | diff --git a/block/throttle.c b/block/throttle.c | ||
| 465 | index 6e8d52fa24..4fb5798c27 100644 | ||
| 466 | --- a/block/throttle.c | ||
| 467 | +++ b/block/throttle.c | ||
| 468 | @@ -78,11 +78,9 @@ static int throttle_open(BlockDriverState *bs, QDict *options, | ||
| 469 | char *group; | ||
| 470 | int ret; | ||
| 471 | |||
| 472 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 473 | - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 474 | - false, errp); | ||
| 475 | - if (!bs->file) { | ||
| 476 | - return -EINVAL; | ||
| 477 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 478 | + if (ret < 0) { | ||
| 479 | + return ret; | ||
| 480 | } | ||
| 481 | bs->supported_write_flags = bs->file->bs->supported_write_flags | | ||
| 482 | BDRV_REQ_WRITE_UNCHANGED; | ||
| 483 | diff --git a/block/vdi.c b/block/vdi.c | ||
| 484 | index bdc58d726e..c50c0ed61f 100644 | ||
| 485 | --- a/block/vdi.c | ||
| 486 | +++ b/block/vdi.c | ||
| 487 | @@ -376,10 +376,9 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 488 | int ret; | ||
| 489 | QemuUUID uuid_link, uuid_parent; | ||
| 490 | |||
| 491 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 492 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 493 | - if (!bs->file) { | ||
| 494 | - return -EINVAL; | ||
| 495 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 496 | + if (ret < 0) { | ||
| 497 | + return ret; | ||
| 498 | } | ||
| 499 | |||
| 500 | logout("\n"); | ||
| 501 | diff --git a/block/vhdx.c b/block/vhdx.c | ||
| 502 | index 356ec4c455..e7d6d7509a 100644 | ||
| 503 | --- a/block/vhdx.c | ||
| 504 | +++ b/block/vhdx.c | ||
| 505 | @@ -996,10 +996,9 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 506 | uint64_t signature; | ||
| 507 | Error *local_err = NULL; | ||
| 508 | |||
| 509 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 510 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 511 | - if (!bs->file) { | ||
| 512 | - return -EINVAL; | ||
| 513 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 514 | + if (ret < 0) { | ||
| 515 | + return ret; | ||
| 516 | } | ||
| 517 | |||
| 518 | s->bat = NULL; | ||
| 519 | diff --git a/block/vmdk.c b/block/vmdk.c | ||
| 520 | index 0dfab6e941..7d7e56b36c 100644 | ||
| 521 | --- a/block/vmdk.c | ||
| 522 | +++ b/block/vmdk.c | ||
| 523 | @@ -1262,10 +1262,9 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 524 | BDRVVmdkState *s = bs->opaque; | ||
| 525 | uint32_t magic; | ||
| 526 | |||
| 527 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 528 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 529 | - if (!bs->file) { | ||
| 530 | - return -EINVAL; | ||
| 531 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 532 | + if (ret < 0) { | ||
| 533 | + return ret; | ||
| 534 | } | ||
| 535 | |||
| 536 | buf = vmdk_read_desc(bs->file, 0, errp); | ||
| 537 | diff --git a/block/vpc.c b/block/vpc.c | ||
| 538 | index 297a26262a..430cab1cbb 100644 | ||
| 539 | --- a/block/vpc.c | ||
| 540 | +++ b/block/vpc.c | ||
| 541 | @@ -232,10 +232,9 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 542 | int ret; | ||
| 543 | int64_t bs_size; | ||
| 544 | |||
| 545 | - bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, | ||
| 546 | - BDRV_CHILD_IMAGE, false, errp); | ||
| 547 | - if (!bs->file) { | ||
| 548 | - return -EINVAL; | ||
| 549 | + ret = bdrv_open_file_child(NULL, options, "file", bs, errp); | ||
| 550 | + if (ret < 0) { | ||
| 551 | + return ret; | ||
| 552 | } | ||
| 553 | |||
| 554 | opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort); | ||
| 555 | diff --git a/include/block/block.h b/include/block/block.h | ||
| 556 | index e5dd22b034..f885f113ef 100644 | ||
| 557 | --- a/include/block/block.h | ||
| 558 | +++ b/include/block/block.h | ||
| 559 | @@ -376,6 +376,9 @@ BdrvChild *bdrv_open_child(const char *filename, | ||
| 560 | const BdrvChildClass *child_class, | ||
| 561 | BdrvChildRole child_role, | ||
| 562 | bool allow_none, Error **errp); | ||
| 563 | +int bdrv_open_file_child(const char *filename, | ||
| 564 | + QDict *options, const char *bdref_key, | ||
| 565 | + BlockDriverState *parent, Error **errp); | ||
| 566 | BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp); | ||
| 567 | int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, | ||
| 568 | Error **errp); | ||
| 569 | -- | ||
| 570 | 2.39.3 | ||
| 571 | |||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch new file mode 100644 index 0000000000..94e03d8646 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch | |||
| @@ -0,0 +1,265 @@ | |||
| 1 | From c4ba1f1755031a0ac2f600ed8c17e7dcb6b2b857 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jon Maloy <jmaloy@redhat.com> | ||
| 3 | Date: Wed, 5 Jun 2024 19:56:51 -0400 | ||
| 4 | Subject: [PATCH 5/5] block: Parse filenames only when explicitly requested | ||
| 5 | |||
| 6 | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||
| 7 | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||
| 8 | RH-Jira: RHEL-35616 | ||
| 9 | RH-CVE: CVE-2024-4467 | ||
| 10 | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||
| 11 | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 12 | RH-Commit: [5/5] a3e197add64fc6950c4ac576e34d833dfae7ee34 | ||
| 13 | |||
| 14 | Conflicts: - brdv_open_child_common(): bdrv_graph_wrlock/unlock() | ||
| 15 | don't exist in this code version. We ignore them. | ||
| 16 | bdrv_open_inherit(): no_coroutine_fn/GRAPH_UNLOCKED | ||
| 17 | doesn't exist. We ignore it. | ||
| 18 | - Changes to bdrv_open_file_child() didn't apply cleanly, | ||
| 19 | but fixing it is straight-forward. | ||
| 20 | - GLOBAL_STATE_CODE() not present in this code. Ignoring it. | ||
| 21 | - bdrv_open_file_child(): Need to continue setting of | ||
| 22 | parent->file. | ||
| 23 | |||
| 24 | commit f44c2941d4419e60f16dea3e9adca164e75aa78d | ||
| 25 | Author: Kevin Wolf <kwolf@redhat.com> | ||
| 26 | Date: Thu Apr 25 14:56:02 2024 +0200 | ||
| 27 | |||
| 28 | block: Parse filenames only when explicitly requested | ||
| 29 | |||
| 30 | When handling image filenames from legacy options such as -drive or from | ||
| 31 | tools, these filenames are parsed for protocol prefixes, including for | ||
| 32 | the json:{} pseudo-protocol. | ||
| 33 | |||
| 34 | This behaviour is intended for filenames that come directly from the | ||
| 35 | command line and for backing files, which may come from the image file | ||
| 36 | itself. Higher level management tools generally take care to verify that | ||
| 37 | untrusted images don't contain a bad (or any) backing file reference; | ||
| 38 | 'qemu-img info' is a suitable tool for this. | ||
| 39 | |||
| 40 | However, for other files that can be referenced in images, such as | ||
| 41 | qcow2 data files or VMDK extents, the string from the image file is | ||
| 42 | usually not verified by management tools - and 'qemu-img info' wouldn't | ||
| 43 | be suitable because in contrast to backing files, it already opens these | ||
| 44 | other referenced files. So here the string should be interpreted as a | ||
| 45 | literal local filename. More complex configurations need to be specified | ||
| 46 | explicitly on the command line or in QMP. | ||
| 47 | |||
| 48 | This patch changes bdrv_open_inherit() so that it only parses filenames | ||
| 49 | if a new parameter parse_filename is true. It is set for the top level | ||
| 50 | in bdrv_open(), for the file child and for the backing file child. All | ||
| 51 | other callers pass false and disable filename parsing this way. | ||
| 52 | |||
| 53 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
| 54 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
| 55 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 56 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 57 | Upstream: N/A, embargoed | ||
| 58 | Signed-off-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 59 | |||
| 60 | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||
| 61 | |||
| 62 | Upstream-Status: Backport [import from rhel8 qemu-kvm-6.2.0-50.module+el8.10.0+22027+db0a70a4.src.rpm | ||
| 63 | Upstream commit https://gitlab.com/qemu-project/qemu/-/commit/7ead946998610657d38d1a505d5f25300d4ca613] | ||
| 64 | CVE: CVE-2024-4467 | ||
| 65 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
| 66 | --- | ||
| 67 | block.c | 81 +++++++++++++++++++++++++++++++++++++++------------------ | ||
| 68 | 1 file changed, 56 insertions(+), 25 deletions(-) | ||
| 69 | |||
| 70 | diff --git a/block.c b/block.c | ||
| 71 | index 889f878565..ddebf50efa 100644 | ||
| 72 | --- a/block.c | ||
| 73 | +++ b/block.c | ||
| 74 | @@ -82,6 +82,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, | ||
| 75 | BlockDriverState *parent, | ||
| 76 | const BdrvChildClass *child_class, | ||
| 77 | BdrvChildRole child_role, | ||
| 78 | + bool parse_filename, | ||
| 79 | Error **errp); | ||
| 80 | |||
| 81 | static bool bdrv_recurse_has_child(BlockDriverState *bs, | ||
| 82 | @@ -1926,7 +1927,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename, | ||
| 83 | * block driver has been specified explicitly. | ||
| 84 | */ | ||
| 85 | static int bdrv_fill_options(QDict **options, const char *filename, | ||
| 86 | - int *flags, Error **errp) | ||
| 87 | + int *flags, bool allow_parse_filename, | ||
| 88 | + Error **errp) | ||
| 89 | { | ||
| 90 | const char *drvname; | ||
| 91 | bool protocol = *flags & BDRV_O_PROTOCOL; | ||
| 92 | @@ -1966,7 +1968,7 @@ static int bdrv_fill_options(QDict **options, const char *filename, | ||
| 93 | if (protocol && filename) { | ||
| 94 | if (!qdict_haskey(*options, "filename")) { | ||
| 95 | qdict_put_str(*options, "filename", filename); | ||
| 96 | - parse_filename = true; | ||
| 97 | + parse_filename = allow_parse_filename; | ||
| 98 | } else { | ||
| 99 | error_setg(errp, "Can't specify 'file' and 'filename' options at " | ||
| 100 | "the same time"); | ||
| 101 | @@ -3439,7 +3441,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, | ||
| 102 | } | ||
| 103 | |||
| 104 | backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs, | ||
| 105 | - &child_of_bds, bdrv_backing_role(bs), errp); | ||
| 106 | + &child_of_bds, bdrv_backing_role(bs), true, | ||
| 107 | + errp); | ||
| 108 | if (!backing_hd) { | ||
| 109 | bs->open_flags |= BDRV_O_NO_BACKING; | ||
| 110 | error_prepend(errp, "Could not open backing file: "); | ||
| 111 | @@ -3472,7 +3475,8 @@ free_exit: | ||
| 112 | static BlockDriverState * | ||
| 113 | bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, | ||
| 114 | BlockDriverState *parent, const BdrvChildClass *child_class, | ||
| 115 | - BdrvChildRole child_role, bool allow_none, Error **errp) | ||
| 116 | + BdrvChildRole child_role, bool allow_none, | ||
| 117 | + bool parse_filename, Error **errp) | ||
| 118 | { | ||
| 119 | BlockDriverState *bs = NULL; | ||
| 120 | QDict *image_options; | ||
| 121 | @@ -3503,7 +3507,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, | ||
| 122 | } | ||
| 123 | |||
| 124 | bs = bdrv_open_inherit(filename, reference, image_options, 0, | ||
| 125 | - parent, child_class, child_role, errp); | ||
| 126 | + parent, child_class, child_role, parse_filename, | ||
| 127 | + errp); | ||
| 128 | if (!bs) { | ||
| 129 | goto done; | ||
| 130 | } | ||
| 131 | @@ -3513,6 +3518,29 @@ done: | ||
| 132 | return bs; | ||
| 133 | } | ||
| 134 | |||
| 135 | +static BdrvChild *bdrv_open_child_common(const char *filename, | ||
| 136 | + QDict *options, const char *bdref_key, | ||
| 137 | + BlockDriverState *parent, | ||
| 138 | + const BdrvChildClass *child_class, | ||
| 139 | + BdrvChildRole child_role, | ||
| 140 | + bool allow_none, bool parse_filename, | ||
| 141 | + Error **errp) | ||
| 142 | +{ | ||
| 143 | + BlockDriverState *bs; | ||
| 144 | + BdrvChild *child; | ||
| 145 | + | ||
| 146 | + bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, | ||
| 147 | + child_role, allow_none, parse_filename, errp); | ||
| 148 | + if (bs == NULL) { | ||
| 149 | + return NULL; | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, | ||
| 153 | + errp); | ||
| 154 | + | ||
| 155 | + return child; | ||
| 156 | +} | ||
| 157 | + | ||
| 158 | /* | ||
| 159 | * Opens a disk image whose options are given as BlockdevRef in another block | ||
| 160 | * device's options. | ||
| 161 | @@ -3534,20 +3562,17 @@ BdrvChild *bdrv_open_child(const char *filename, | ||
| 162 | BdrvChildRole child_role, | ||
| 163 | bool allow_none, Error **errp) | ||
| 164 | { | ||
| 165 | - BlockDriverState *bs; | ||
| 166 | - | ||
| 167 | - bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, | ||
| 168 | - child_role, allow_none, errp); | ||
| 169 | - if (bs == NULL) { | ||
| 170 | - return NULL; | ||
| 171 | - } | ||
| 172 | - | ||
| 173 | - return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, | ||
| 174 | - errp); | ||
| 175 | + return bdrv_open_child_common(filename, options, bdref_key, parent, | ||
| 176 | + child_class, child_role, allow_none, false, | ||
| 177 | + errp); | ||
| 178 | } | ||
| 179 | |||
| 180 | /* | ||
| 181 | - * Wrapper on bdrv_open_child() for most popular case: open primary child of bs. | ||
| 182 | + * This does mostly the same as bdrv_open_child(), but for opening the primary | ||
| 183 | + * child of a node. A notable difference from bdrv_open_child() is that it | ||
| 184 | + * enables filename parsing for protocol names (including json:). | ||
| 185 | + * | ||
| 186 | + * @parent can move to a different AioContext in this function. | ||
| 187 | */ | ||
| 188 | int bdrv_open_file_child(const char *filename, | ||
| 189 | QDict *options, const char *bdref_key, | ||
| 190 | @@ -3558,8 +3583,9 @@ int bdrv_open_file_child(const char *filename, | ||
| 191 | role = parent->drv->is_filter ? | ||
| 192 | (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE; | ||
| 193 | |||
| 194 | - parent->file = bdrv_open_child(filename, options, bdref_key, parent, | ||
| 195 | - &child_of_bds, role, false, errp); | ||
| 196 | + parent->file = bdrv_open_child_common(filename, options, bdref_key, parent, | ||
| 197 | + &child_of_bds, role, false, true, | ||
| 198 | + errp); | ||
| 199 | |||
| 200 | return parent->file ? 0 : -EINVAL; | ||
| 201 | } | ||
| 202 | @@ -3599,7 +3625,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) | ||
| 203 | |||
| 204 | } | ||
| 205 | |||
| 206 | - bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp); | ||
| 207 | + bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false, | ||
| 208 | + errp); | ||
| 209 | obj = NULL; | ||
| 210 | qobject_unref(obj); | ||
| 211 | visit_free(v); | ||
| 212 | @@ -3690,6 +3717,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, | ||
| 213 | BlockDriverState *parent, | ||
| 214 | const BdrvChildClass *child_class, | ||
| 215 | BdrvChildRole child_role, | ||
| 216 | + bool parse_filename, | ||
| 217 | Error **errp) | ||
| 218 | { | ||
| 219 | int ret; | ||
| 220 | @@ -3733,9 +3761,11 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, | ||
| 221 | } | ||
| 222 | |||
| 223 | /* json: syntax counts as explicit options, as if in the QDict */ | ||
| 224 | - parse_json_protocol(options, &filename, &local_err); | ||
| 225 | - if (local_err) { | ||
| 226 | - goto fail; | ||
| 227 | + if (parse_filename) { | ||
| 228 | + parse_json_protocol(options, &filename, &local_err); | ||
| 229 | + if (local_err) { | ||
| 230 | + goto fail; | ||
| 231 | + } | ||
| 232 | } | ||
| 233 | |||
| 234 | bs->explicit_options = qdict_clone_shallow(options); | ||
| 235 | @@ -3760,7 +3790,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, | ||
| 236 | parent->open_flags, parent->options); | ||
| 237 | } | ||
| 238 | |||
| 239 | - ret = bdrv_fill_options(&options, filename, &flags, &local_err); | ||
| 240 | + ret = bdrv_fill_options(&options, filename, &flags, parse_filename, | ||
| 241 | + &local_err); | ||
| 242 | if (ret < 0) { | ||
| 243 | goto fail; | ||
| 244 | } | ||
| 245 | @@ -3829,7 +3860,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, | ||
| 246 | |||
| 247 | file_bs = bdrv_open_child_bs(filename, options, "file", bs, | ||
| 248 | &child_of_bds, BDRV_CHILD_IMAGE, | ||
| 249 | - true, &local_err); | ||
| 250 | + true, true, &local_err); | ||
| 251 | if (local_err) { | ||
| 252 | goto fail; | ||
| 253 | } | ||
| 254 | @@ -3974,7 +4005,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference, | ||
| 255 | QDict *options, int flags, Error **errp) | ||
| 256 | { | ||
| 257 | return bdrv_open_inherit(filename, reference, options, flags, NULL, | ||
| 258 | - NULL, 0, errp); | ||
| 259 | + NULL, 0, true, errp); | ||
| 260 | } | ||
| 261 | |||
| 262 | /* Return true if the NULL-terminated @list contains @str */ | ||
| 263 | -- | ||
| 264 | 2.39.3 | ||
| 265 | |||
