With BDRV_O_NO_IO, we suppress opening data-file to prevent opening unchecked paths through `qemu-img info`. However, a future commit will make qcow2_co_create() pass BDRV_O_NO_IO for the new image if possible, and then we need data-file attached to be able to query its size.
qcow2_co_create() already has the data-file open, so it specifies it by node name; and if we get the data-file by node name, there is no security risk attaching it because it is already open. So check whether the data-file option is a string, i.e. a node name, and if so, allow attaching it despite BDRV_O_NO_IO. Signed-off-by: Hanna Czenczek <[email protected]> --- block/qcow2.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index cf9189b829..edf18630f6 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1410,6 +1410,7 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, uint64_t ext_end; uint64_t l1_vm_state_index; bool update_header = false; + bool suppress_data_file = false; ret = bdrv_co_pread(bs->file, 0, sizeof(header), &header, 0); if (ret < 0) { @@ -1719,14 +1720,23 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } - 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. - */ + /* + * 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. + * + * Exception: If the data-file option is a node name, attaching that + * node will not open a new file, so cannot pose a security risk. + * + * Note: This still makes has_data_file() return true. + */ + if (flags & BDRV_O_NO_IO) { + QObject *data_file = qdict_get(options, "data-file"); + suppress_data_file = + !data_file || qobject_type(data_file) != QTYPE_QSTRING; + } + + if (open_data_file && suppress_data_file) { if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { s->data_file = NULL; } else { -- 2.53.0
