mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 09:55:55 +00:00
qcow2: Fix error path for unknown incompatible features
qcow2's report_unsupported_feature() had two bugs: A 32 bit truncation would prevent feature table entries for bits 32-63 from being used, and it could assign errp multiple times if there was more than one unknown feature, resulting in an error_set() assertion failure. Fix the truncation, make sure to set the error exactly once and add a qemu-iotests case for it. This fixes https://bugs.launchpad.net/qemu/+bug/1342704/ Reported-by: Maria Kustova <maria.k@catit.be> Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
5a73480450
commit
12ac6d3db7
|
@ -210,20 +210,31 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs,
|
|||
static void report_unsupported_feature(BlockDriverState *bs,
|
||||
Error **errp, Qcow2Feature *table, uint64_t mask)
|
||||
{
|
||||
char *features = g_strdup("");
|
||||
char *old;
|
||||
|
||||
while (table && table->name[0] != '\0') {
|
||||
if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) {
|
||||
if (mask & (1 << table->bit)) {
|
||||
report_unsupported(bs, errp, "%.46s", table->name);
|
||||
mask &= ~(1 << table->bit);
|
||||
if (mask & (1ULL << table->bit)) {
|
||||
old = features;
|
||||
features = g_strdup_printf("%s%s%.46s", old, *old ? ", " : "",
|
||||
table->name);
|
||||
g_free(old);
|
||||
mask &= ~(1ULL << table->bit);
|
||||
}
|
||||
}
|
||||
table++;
|
||||
}
|
||||
|
||||
if (mask) {
|
||||
report_unsupported(bs, errp, "Unknown incompatible feature: %" PRIx64,
|
||||
mask);
|
||||
old = features;
|
||||
features = g_strdup_printf("%s%sUnknown incompatible feature: %" PRIx64,
|
||||
old, *old ? ", " : "", mask);
|
||||
g_free(old);
|
||||
}
|
||||
|
||||
report_unsupported(bs, errp, "%s", features);
|
||||
g_free(features);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Test that qcow2 unknown autoclear feature bits are cleared
|
||||
# Test qcow2 feature bits
|
||||
#
|
||||
# Copyright (C) 2011 Red Hat, Inc.
|
||||
# Copyright IBM, Corp. 2010
|
||||
|
@ -50,6 +50,56 @@ _supported_os Linux
|
|||
# Only qcow2v3 and later supports feature bits
|
||||
IMGOPTS="compat=1.1"
|
||||
|
||||
echo
|
||||
echo === Image with unknown incompatible feature bit ===
|
||||
echo
|
||||
_make_test_img 64M
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
|
||||
|
||||
# Without feature table
|
||||
$PYTHON qcow2.py "$TEST_IMG" dump-header
|
||||
_img_info
|
||||
|
||||
# With feature table containing bit 63
|
||||
printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
echo
|
||||
echo === Image with multiple incompatible feature bits ===
|
||||
echo
|
||||
_make_test_img 64M
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 61
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 62
|
||||
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
|
||||
|
||||
# Without feature table
|
||||
_img_info
|
||||
|
||||
# With feature table containing bit 63
|
||||
printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
# With feature table containing bit 61
|
||||
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
|
||||
printf "\x00\x3d%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
# With feature table containing bits 61 and 62
|
||||
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
|
||||
printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s" "test1" "" "test2" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
# With feature table containing all bits
|
||||
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
|
||||
printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s\x00\x3f%s\x00%40s" "test1" "" "test2" "" "test3" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
# With feature table containing unrelated bits, including compatible/autoclear
|
||||
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
|
||||
printf "\x01\x3d%s\x00%40s\x00\x3e%s\x00%40s\x02\x3f%s\x00%40s\x00\x3c%s\x00%40s" "test1" "" "test2" "" "test3" "" "test4" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
|
||||
_img_info
|
||||
|
||||
|
||||
echo === Create image with unknown autoclear feature bit ===
|
||||
echo
|
||||
_make_test_img 64M
|
||||
|
|
|
@ -1,4 +1,39 @@
|
|||
QA output created by 036
|
||||
|
||||
=== Image with unknown incompatible feature bit ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
magic 0x514649fb
|
||||
version 3
|
||||
backing_file_offset 0x0
|
||||
backing_file_size 0x0
|
||||
cluster_bits 16
|
||||
size 67108864
|
||||
crypt_method 0
|
||||
l1_size 1
|
||||
l1_table_offset 0x30000
|
||||
refcount_table_offset 0x10000
|
||||
refcount_table_clusters 1
|
||||
nb_snapshots 0
|
||||
snapshot_offset 0x0
|
||||
incompatible_features 0x8000000000000000
|
||||
compatible_features 0x0
|
||||
autoclear_features 0x0
|
||||
refcount_order 4
|
||||
header_length 104
|
||||
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: 8000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature
|
||||
|
||||
=== Image with multiple incompatible feature bits ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: e000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: 6000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: c000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, Unknown incompatible feature: 8000000000000000
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, test3
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test2, Unknown incompatible feature: a000000000000000
|
||||
=== Create image with unknown autoclear feature bit ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
|
|
|
@ -176,6 +176,10 @@ def cmd_add_header_ext(fd, magic, data):
|
|||
h.extensions.append(QcowHeaderExtension.create(magic, data))
|
||||
h.update(fd)
|
||||
|
||||
def cmd_add_header_ext_stdio(fd, magic):
|
||||
data = sys.stdin.read()
|
||||
cmd_add_header_ext(fd, magic, data)
|
||||
|
||||
def cmd_del_header_ext(fd, magic):
|
||||
try:
|
||||
magic = int(magic, 0)
|
||||
|
@ -220,11 +224,12 @@ def cmd_set_feature_bit(fd, group, bit):
|
|||
h.update(fd)
|
||||
|
||||
cmds = [
|
||||
[ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
|
||||
[ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
|
||||
[ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
|
||||
[ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
|
||||
[ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
|
||||
[ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
|
||||
[ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
|
||||
[ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
|
||||
[ 'add-header-ext-stdio', cmd_add_header_ext_stdio, 1, 'Add a header extension, data from stdin' ],
|
||||
[ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
|
||||
[ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
|
||||
]
|
||||
|
||||
def main(filename, cmd, args):
|
||||
|
|
Loading…
Reference in a new issue