Skip to content

Commit 5be2bb4

Browse files
kevmwMichael Tokarev
authored andcommitted
block: Parse filenames only when explicitly requested
When handling image filenames from legacy options such as -drive or from tools, these filenames are parsed for protocol prefixes, including for the json:{} pseudo-protocol. This behaviour is intended for filenames that come directly from the command line and for backing files, which may come from the image file itself. Higher level management tools generally take care to verify that untrusted images don't contain a bad (or any) backing file reference; 'qemu-img info' is a suitable tool for this. However, for other files that can be referenced in images, such as qcow2 data files or VMDK extents, the string from the image file is usually not verified by management tools - and 'qemu-img info' wouldn't be suitable because in contrast to backing files, it already opens these other referenced files. So here the string should be interpreted as a literal local filename. More complex configurations need to be specified explicitly on the command line or in QMP. This patch changes bdrv_open_inherit() so that it only parses filenames if a new parameter parse_filename is true. It is set for the top level in bdrv_open(), for the file child and for the backing file child. All other callers pass false and disable filename parsing this way. 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 7ead946) Signed-off-by: Michael Tokarev <[email protected]>
1 parent 8c022d8 commit 5be2bb4

File tree

1 file changed

+57
-33
lines changed

1 file changed

+57
-33
lines changed

block.c

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
8686
BlockDriverState *parent,
8787
const BdrvChildClass *child_class,
8888
BdrvChildRole child_role,
89+
bool parse_filename,
8990
Error **errp);
9091

9192
static bool bdrv_recurse_has_child(BlockDriverState *bs,
@@ -2058,7 +2059,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
20582059
* block driver has been specified explicitly.
20592060
*/
20602061
static int bdrv_fill_options(QDict **options, const char *filename,
2061-
int *flags, Error **errp)
2062+
int *flags, bool allow_parse_filename,
2063+
Error **errp)
20622064
{
20632065
const char *drvname;
20642066
bool protocol = *flags & BDRV_O_PROTOCOL;
@@ -2100,7 +2102,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
21002102
if (protocol && filename) {
21012103
if (!qdict_haskey(*options, "filename")) {
21022104
qdict_put_str(*options, "filename", filename);
2103-
parse_filename = true;
2105+
parse_filename = allow_parse_filename;
21042106
} else {
21052107
error_setg(errp, "Can't specify 'file' and 'filename' options at "
21062108
"the same time");
@@ -3663,7 +3665,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
36633665
}
36643666

36653667
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
3666-
&child_of_bds, bdrv_backing_role(bs), errp);
3668+
&child_of_bds, bdrv_backing_role(bs), true,
3669+
errp);
36673670
if (!backing_hd) {
36683671
bs->open_flags |= BDRV_O_NO_BACKING;
36693672
error_prepend(errp, "Could not open backing file: ");
@@ -3697,7 +3700,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
36973700
static BlockDriverState *
36983701
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
36993702
BlockDriverState *parent, const BdrvChildClass *child_class,
3700-
BdrvChildRole child_role, bool allow_none, Error **errp)
3703+
BdrvChildRole child_role, bool allow_none,
3704+
bool parse_filename, Error **errp)
37013705
{
37023706
BlockDriverState *bs = NULL;
37033707
QDict *image_options;
@@ -3728,7 +3732,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
37283732
}
37293733

37303734
bs = bdrv_open_inherit(filename, reference, image_options, 0,
3731-
parent, child_class, child_role, errp);
3735+
parent, child_class, child_role, parse_filename,
3736+
errp);
37323737
if (!bs) {
37333738
goto done;
37343739
}
@@ -3738,6 +3743,33 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
37383743
return bs;
37393744
}
37403745

3746+
static BdrvChild *bdrv_open_child_common(const char *filename,
3747+
QDict *options, const char *bdref_key,
3748+
BlockDriverState *parent,
3749+
const BdrvChildClass *child_class,
3750+
BdrvChildRole child_role,
3751+
bool allow_none, bool parse_filename,
3752+
Error **errp)
3753+
{
3754+
BlockDriverState *bs;
3755+
BdrvChild *child;
3756+
3757+
GLOBAL_STATE_CODE();
3758+
3759+
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
3760+
child_role, allow_none, parse_filename, errp);
3761+
if (bs == NULL) {
3762+
return NULL;
3763+
}
3764+
3765+
bdrv_graph_wrlock();
3766+
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
3767+
errp);
3768+
bdrv_graph_wrunlock();
3769+
3770+
return child;
3771+
}
3772+
37413773
/*
37423774
* Opens a disk image whose options are given as BlockdevRef in another block
37433775
* device's options.
@@ -3761,27 +3793,15 @@ BdrvChild *bdrv_open_child(const char *filename,
37613793
BdrvChildRole child_role,
37623794
bool allow_none, Error **errp)
37633795
{
3764-
BlockDriverState *bs;
3765-
BdrvChild *child;
3766-
3767-
GLOBAL_STATE_CODE();
3768-
3769-
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
3770-
child_role, allow_none, errp);
3771-
if (bs == NULL) {
3772-
return NULL;
3773-
}
3774-
3775-
bdrv_graph_wrlock();
3776-
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
3777-
errp);
3778-
bdrv_graph_wrunlock();
3779-
3780-
return child;
3796+
return bdrv_open_child_common(filename, options, bdref_key, parent,
3797+
child_class, child_role, allow_none, false,
3798+
errp);
37813799
}
37823800

37833801
/*
3784-
* Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
3802+
* This does mostly the same as bdrv_open_child(), but for opening the primary
3803+
* child of a node. A notable difference from bdrv_open_child() is that it
3804+
* enables filename parsing for protocol names (including json:).
37853805
*
37863806
* @parent can move to a different AioContext in this function.
37873807
*/
@@ -3796,8 +3816,8 @@ int bdrv_open_file_child(const char *filename,
37963816
role = parent->drv->is_filter ?
37973817
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
37983818

3799-
if (!bdrv_open_child(filename, options, bdref_key, parent,
3800-
&child_of_bds, role, false, errp))
3819+
if (!bdrv_open_child_common(filename, options, bdref_key, parent,
3820+
&child_of_bds, role, false, true, errp))
38013821
{
38023822
return -EINVAL;
38033823
}
@@ -3842,7 +3862,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
38423862

38433863
}
38443864

3845-
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
3865+
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
3866+
errp);
38463867
obj = NULL;
38473868
qobject_unref(obj);
38483869
visit_free(v);
@@ -3932,7 +3953,7 @@ static BlockDriverState * no_coroutine_fn
39323953
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
39333954
int flags, BlockDriverState *parent,
39343955
const BdrvChildClass *child_class, BdrvChildRole child_role,
3935-
Error **errp)
3956+
bool parse_filename, Error **errp)
39363957
{
39373958
int ret;
39383959
BlockBackend *file = NULL;
@@ -3980,9 +4001,11 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
39804001
}
39814002

39824003
/* json: syntax counts as explicit options, as if in the QDict */
3983-
parse_json_protocol(options, &filename, &local_err);
3984-
if (local_err) {
3985-
goto fail;
4004+
if (parse_filename) {
4005+
parse_json_protocol(options, &filename, &local_err);
4006+
if (local_err) {
4007+
goto fail;
4008+
}
39864009
}
39874010

39884011
bs->explicit_options = qdict_clone_shallow(options);
@@ -4007,7 +4030,8 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
40074030
parent->open_flags, parent->options);
40084031
}
40094032

4010-
ret = bdrv_fill_options(&options, filename, &flags, &local_err);
4033+
ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
4034+
&local_err);
40114035
if (ret < 0) {
40124036
goto fail;
40134037
}
@@ -4076,7 +4100,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
40764100

40774101
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
40784102
&child_of_bds, BDRV_CHILD_IMAGE,
4079-
true, &local_err);
4103+
true, true, &local_err);
40804104
if (local_err) {
40814105
goto fail;
40824106
}
@@ -4225,7 +4249,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
42254249
GLOBAL_STATE_CODE();
42264250

42274251
return bdrv_open_inherit(filename, reference, options, flags, NULL,
4228-
NULL, 0, errp);
4252+
NULL, 0, true, errp);
42294253
}
42304254

42314255
/* Return true if the NULL-terminated @list contains @str */

0 commit comments

Comments
 (0)