mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
Block layer patches (CVE-2024-4467)
- Don't open qcow2 data files in 'qemu-img info' - Disallow protocol prefixes for qcow2 data files, VMDK extent files and other child nodes that are neither 'file' nor 'backing' -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmaEKQwRHGt3b2xmQHJl ZGhhdC5jb20ACgkQfwmycsiPL9YgMA/+OeQf0veFb02ZNqf907Etz8/DvnqbiWUN 0aT5z5x8ilZQIiEDbFtLKgF3A/WO7phyCKk1q1dbRNbc1ZaWFW7mTaJM2ew++EuB fq0mnskLt/GVSqTReO4od7flsssp3sEDxs74yuyNITIUqui4we9WK2lLRiAv3aco 2NbyNeMHJxIW+QlOO3R62i24yjQaLyg/YekmiIK8itQkpKuI80fiVgor5W3RR0P0 71AVSHC0Edv5eavmiRqmQ+pfSI8tlINsN1s5jvxge6XpVTaL8NHsgH3LVv1R3Qtx Uo9hp6lQboAfc4I06gf+fcsYSBRiGCwA/J+JsWusX4FLaaTNHLt5eJAEJhfZlioj wgTqpy2ImRu5lcuLjLWRu4cLapPLI6CSwf4/lG9/szmRA/1UtOKpquKeTuCwMl9Y XEVoNDzo7GpfSb7YONo7fU7kq00OuEEAn0he7eNd2UU+Ao9Abi7JvY+fKx71FHo3 k24SQVhVJihV1IEC4psCtaQm2bB/jdMr0jB44zHLtmqeUMLrrVf64cSAntp+2KRa sINBXA5OeblGKQ7FoAzc5NNNveSdF1ioRCvKB3MlHzI+efzRS7+I3wwh2Uz1Uwfo sivg+dAXQQBKVXn8UbfznFyEKueT0RW5CUbfeEqGQ/ocw7iTrXABsX+tjcktxl8Q zrHZNoAz6Ds= =7LWn -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging Block layer patches (CVE-2024-4467) - Don't open qcow2 data files in 'qemu-img info' - Disallow protocol prefixes for qcow2 data files, VMDK extent files and other child nodes that are neither 'file' nor 'backing' # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmaEKQwRHGt3b2xmQHJl # ZGhhdC5jb20ACgkQfwmycsiPL9YgMA/+OeQf0veFb02ZNqf907Etz8/DvnqbiWUN # 0aT5z5x8ilZQIiEDbFtLKgF3A/WO7phyCKk1q1dbRNbc1ZaWFW7mTaJM2ew++EuB # fq0mnskLt/GVSqTReO4od7flsssp3sEDxs74yuyNITIUqui4we9WK2lLRiAv3aco # 2NbyNeMHJxIW+QlOO3R62i24yjQaLyg/YekmiIK8itQkpKuI80fiVgor5W3RR0P0 # 71AVSHC0Edv5eavmiRqmQ+pfSI8tlINsN1s5jvxge6XpVTaL8NHsgH3LVv1R3Qtx # Uo9hp6lQboAfc4I06gf+fcsYSBRiGCwA/J+JsWusX4FLaaTNHLt5eJAEJhfZlioj # wgTqpy2ImRu5lcuLjLWRu4cLapPLI6CSwf4/lG9/szmRA/1UtOKpquKeTuCwMl9Y # XEVoNDzo7GpfSb7YONo7fU7kq00OuEEAn0he7eNd2UU+Ao9Abi7JvY+fKx71FHo3 # k24SQVhVJihV1IEC4psCtaQm2bB/jdMr0jB44zHLtmqeUMLrrVf64cSAntp+2KRa # sINBXA5OeblGKQ7FoAzc5NNNveSdF1ioRCvKB3MlHzI+efzRS7+I3wwh2Uz1Uwfo # sivg+dAXQQBKVXn8UbfznFyEKueT0RW5CUbfeEqGQ/ocw7iTrXABsX+tjcktxl8Q # zrHZNoAz6Ds= # =7LWn # -----END PGP SIGNATURE----- # gpg: Signature made Tue 02 Jul 2024 09:21:32 AM PDT # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] * tag 'for-upstream' of https://repo.or.cz/qemu/kevin: block: Parse filenames only when explicitly requested iotests/270: Don't store data-file with json: prefix in image iotests/244: Don't store data-file with protocol in image qcow2: Don't open data_file with BDRV_O_NO_IO Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
727f4a7800
6 changed files with 110 additions and 44 deletions
82
block.c
82
block.c
|
@ -86,6 +86,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||||
BlockDriverState *parent,
|
BlockDriverState *parent,
|
||||||
const BdrvChildClass *child_class,
|
const BdrvChildClass *child_class,
|
||||||
BdrvChildRole child_role,
|
BdrvChildRole child_role,
|
||||||
|
bool parse_filename,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
static bool bdrv_recurse_has_child(BlockDriverState *bs,
|
static bool bdrv_recurse_has_child(BlockDriverState *bs,
|
||||||
|
@ -2055,7 +2056,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
|
||||||
* block driver has been specified explicitly.
|
* block driver has been specified explicitly.
|
||||||
*/
|
*/
|
||||||
static int bdrv_fill_options(QDict **options, const char *filename,
|
static int bdrv_fill_options(QDict **options, const char *filename,
|
||||||
int *flags, Error **errp)
|
int *flags, bool allow_parse_filename,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
const char *drvname;
|
const char *drvname;
|
||||||
bool protocol = *flags & BDRV_O_PROTOCOL;
|
bool protocol = *flags & BDRV_O_PROTOCOL;
|
||||||
|
@ -2097,7 +2099,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
||||||
if (protocol && filename) {
|
if (protocol && filename) {
|
||||||
if (!qdict_haskey(*options, "filename")) {
|
if (!qdict_haskey(*options, "filename")) {
|
||||||
qdict_put_str(*options, "filename", filename);
|
qdict_put_str(*options, "filename", filename);
|
||||||
parse_filename = true;
|
parse_filename = allow_parse_filename;
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "Can't specify 'file' and 'filename' options at "
|
error_setg(errp, "Can't specify 'file' and 'filename' options at "
|
||||||
"the same time");
|
"the same time");
|
||||||
|
@ -3660,7 +3662,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||||
}
|
}
|
||||||
|
|
||||||
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
|
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
|
||||||
&child_of_bds, bdrv_backing_role(bs), errp);
|
&child_of_bds, bdrv_backing_role(bs), true,
|
||||||
|
errp);
|
||||||
if (!backing_hd) {
|
if (!backing_hd) {
|
||||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||||
error_prepend(errp, "Could not open backing file: ");
|
error_prepend(errp, "Could not open backing file: ");
|
||||||
|
@ -3694,7 +3697,8 @@ free_exit:
|
||||||
static BlockDriverState *
|
static BlockDriverState *
|
||||||
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||||
BlockDriverState *parent, const BdrvChildClass *child_class,
|
BlockDriverState *parent, const BdrvChildClass *child_class,
|
||||||
BdrvChildRole child_role, bool allow_none, Error **errp)
|
BdrvChildRole child_role, bool allow_none,
|
||||||
|
bool parse_filename, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
QDict *image_options;
|
QDict *image_options;
|
||||||
|
@ -3725,7 +3729,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_open_inherit(filename, reference, image_options, 0,
|
bs = bdrv_open_inherit(filename, reference, image_options, 0,
|
||||||
parent, child_class, child_role, errp);
|
parent, child_class, child_role, parse_filename,
|
||||||
|
errp);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -3735,6 +3740,33 @@ done:
|
||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BdrvChild *bdrv_open_child_common(const char *filename,
|
||||||
|
QDict *options, const char *bdref_key,
|
||||||
|
BlockDriverState *parent,
|
||||||
|
const BdrvChildClass *child_class,
|
||||||
|
BdrvChildRole child_role,
|
||||||
|
bool allow_none, bool parse_filename,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BlockDriverState *bs;
|
||||||
|
BdrvChild *child;
|
||||||
|
|
||||||
|
GLOBAL_STATE_CODE();
|
||||||
|
|
||||||
|
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
||||||
|
child_role, allow_none, parse_filename, errp);
|
||||||
|
if (bs == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bdrv_graph_wrlock();
|
||||||
|
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||||
|
errp);
|
||||||
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opens a disk image whose options are given as BlockdevRef in another block
|
* Opens a disk image whose options are given as BlockdevRef in another block
|
||||||
* device's options.
|
* device's options.
|
||||||
|
@ -3758,27 +3790,15 @@ BdrvChild *bdrv_open_child(const char *filename,
|
||||||
BdrvChildRole child_role,
|
BdrvChildRole child_role,
|
||||||
bool allow_none, Error **errp)
|
bool allow_none, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
return bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||||
BdrvChild *child;
|
child_class, child_role, allow_none, false,
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
|
||||||
|
|
||||||
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
|
||||||
child_role, allow_none, errp);
|
|
||||||
if (bs == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bdrv_graph_wrlock();
|
|
||||||
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
|
||||||
errp);
|
errp);
|
||||||
bdrv_graph_wrunlock();
|
|
||||||
|
|
||||||
return child;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
|
* This does mostly the same as bdrv_open_child(), but for opening the primary
|
||||||
|
* child of a node. A notable difference from bdrv_open_child() is that it
|
||||||
|
* enables filename parsing for protocol names (including json:).
|
||||||
*
|
*
|
||||||
* @parent can move to a different AioContext in this function.
|
* @parent can move to a different AioContext in this function.
|
||||||
*/
|
*/
|
||||||
|
@ -3793,8 +3813,8 @@ int bdrv_open_file_child(const char *filename,
|
||||||
role = parent->drv->is_filter ?
|
role = parent->drv->is_filter ?
|
||||||
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
|
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
|
||||||
|
|
||||||
if (!bdrv_open_child(filename, options, bdref_key, parent,
|
if (!bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||||
&child_of_bds, role, false, errp))
|
&child_of_bds, role, false, true, errp))
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -3839,7 +3859,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
|
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
|
||||||
|
errp);
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
qobject_unref(obj);
|
qobject_unref(obj);
|
||||||
visit_free(v);
|
visit_free(v);
|
||||||
|
@ -3929,7 +3950,7 @@ static BlockDriverState * no_coroutine_fn
|
||||||
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||||
int flags, BlockDriverState *parent,
|
int flags, BlockDriverState *parent,
|
||||||
const BdrvChildClass *child_class, BdrvChildRole child_role,
|
const BdrvChildClass *child_class, BdrvChildRole child_role,
|
||||||
Error **errp)
|
bool parse_filename, Error **errp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
BlockBackend *file = NULL;
|
BlockBackend *file = NULL;
|
||||||
|
@ -3977,10 +3998,12 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* json: syntax counts as explicit options, as if in the QDict */
|
/* json: syntax counts as explicit options, as if in the QDict */
|
||||||
|
if (parse_filename) {
|
||||||
parse_json_protocol(options, &filename, &local_err);
|
parse_json_protocol(options, &filename, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bs->explicit_options = qdict_clone_shallow(options);
|
bs->explicit_options = qdict_clone_shallow(options);
|
||||||
|
|
||||||
|
@ -4004,7 +4027,8 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||||
parent->open_flags, parent->options);
|
parent->open_flags, parent->options);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_fill_options(&options, filename, &flags, &local_err);
|
ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
|
||||||
|
&local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -4073,7 +4097,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||||
|
|
||||||
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
|
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
|
||||||
&child_of_bds, BDRV_CHILD_IMAGE,
|
&child_of_bds, BDRV_CHILD_IMAGE,
|
||||||
true, &local_err);
|
true, true, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -4222,7 +4246,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
|
|
||||||
return bdrv_open_inherit(filename, reference, options, flags, NULL,
|
return bdrv_open_inherit(filename, reference, options, flags, NULL,
|
||||||
NULL, 0, errp);
|
NULL, 0, true, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if the NULL-terminated @list contains @str */
|
/* Return true if the NULL-terminated @list contains @str */
|
||||||
|
|
|
@ -1636,7 +1636,22 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open_data_file) {
|
if (open_data_file && (flags & BDRV_O_NO_IO)) {
|
||||||
|
/*
|
||||||
|
* Don't open the data file for 'qemu-img info' so that it can be used
|
||||||
|
* to verify that an untrusted qcow2 image doesn't refer to external
|
||||||
|
* files.
|
||||||
|
*
|
||||||
|
* Note: This still makes has_data_file() return true.
|
||||||
|
*/
|
||||||
|
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
|
||||||
|
s->data_file = NULL;
|
||||||
|
} else {
|
||||||
|
s->data_file = bs->file;
|
||||||
|
}
|
||||||
|
qdict_extract_subqdict(options, NULL, "data-file.");
|
||||||
|
qdict_del(options, "data-file");
|
||||||
|
} else if (open_data_file) {
|
||||||
/* Open external data file */
|
/* Open external data file */
|
||||||
bdrv_graph_co_rdunlock();
|
bdrv_graph_co_rdunlock();
|
||||||
s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs,
|
s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs,
|
||||||
|
|
|
@ -326,12 +326,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
|
||||||
echo
|
echo
|
||||||
_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
|
_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
|
||||||
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
|
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
|
||||||
_img_info --format-specific
|
$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
|
||||||
|
$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
|
||||||
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
|
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
|
||||||
|
|
||||||
echo
|
echo
|
||||||
$QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG"
|
$QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG"
|
||||||
_img_info --format-specific
|
$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
|
||||||
|
$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
|
||||||
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
|
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||||
qemu-img: data-file can only be set for images that use an external data file
|
qemu-img: data-file can only be set for images that use an external data file
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data
|
||||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory
|
qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
image: TEST_DIR/t.IMGFMT
|
image: TEST_DIR/t.IMGFMT
|
||||||
file format: IMGFMT
|
file format: IMGFMT
|
||||||
virtual size: 64 MiB (67108864 bytes)
|
virtual size: 64 MiB (67108864 bytes)
|
||||||
|
@ -560,7 +562,9 @@ Format specific information:
|
||||||
corrupt: false
|
corrupt: false
|
||||||
extended l2: false
|
extended l2: false
|
||||||
|
|
||||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image
|
qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
image: TEST_DIR/t.IMGFMT
|
image: TEST_DIR/t.IMGFMT
|
||||||
file format: IMGFMT
|
file format: IMGFMT
|
||||||
virtual size: 64 MiB (67108864 bytes)
|
virtual size: 64 MiB (67108864 bytes)
|
||||||
|
|
|
@ -215,9 +215,22 @@ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
|
||||||
$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
|
$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
|
||||||
|
|
||||||
# blkdebug doesn't support copy offloading, so this tests the error path
|
# blkdebug doesn't support copy offloading, so this tests the error path
|
||||||
$QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG"
|
test_img_with_blkdebug="json:{
|
||||||
$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
|
'driver': 'qcow2',
|
||||||
$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
|
'file': {
|
||||||
|
'driver': 'file',
|
||||||
|
'filename': '$TEST_IMG'
|
||||||
|
},
|
||||||
|
'data-file': {
|
||||||
|
'driver': 'blkdebug',
|
||||||
|
'image': {
|
||||||
|
'driver': 'file',
|
||||||
|
'filename': '$TEST_IMG.data'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$test_img_with_blkdebug"
|
||||||
|
$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$test_img_with_blkdebug"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "=== Flushing should flush the data file ==="
|
echo "=== Flushing should flush the data file ==="
|
||||||
|
|
|
@ -60,8 +60,16 @@ _make_test_img -o cluster_size=2M,data_file="$TEST_IMG.orig" \
|
||||||
# "write" 2G of data without using any space.
|
# "write" 2G of data without using any space.
|
||||||
# (qemu-img create does not like it, though, because null-co does not
|
# (qemu-img create does not like it, though, because null-co does not
|
||||||
# support image creation.)
|
# support image creation.)
|
||||||
$QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \
|
test_img_with_null_data="json:{
|
||||||
"$TEST_IMG"
|
'driver': '$IMGFMT',
|
||||||
|
'file': {
|
||||||
|
'filename': '$TEST_IMG'
|
||||||
|
},
|
||||||
|
'data-file': {
|
||||||
|
'driver': 'null-co',
|
||||||
|
'size':'4294967296'
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
# This gives us a range of:
|
# This gives us a range of:
|
||||||
# 2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31
|
# 2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31
|
||||||
|
@ -74,7 +82,7 @@ $QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \
|
||||||
# on L2 boundaries, we need large L2 tables; hence the cluster size of
|
# on L2 boundaries, we need large L2 tables; hence the cluster size of
|
||||||
# 2 MB. (Anything from 256 kB should work, though, because then one L2
|
# 2 MB. (Anything from 256 kB should work, though, because then one L2
|
||||||
# table covers 8 GB.)
|
# table covers 8 GB.)
|
||||||
$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$test_img_with_null_data" | _filter_qemu_io
|
||||||
|
|
||||||
_check_test_img
|
_check_test_img
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue