From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 22/25] qcow2: Refuse to get unaligned offsets from cache
Date: Fri, 17 Nov 2017 19:16:50 +0100 [thread overview]
Message-ID: <20171117181653.20651-23-kwolf@redhat.com> (raw)
In-Reply-To: <20171117181653.20651-1-kwolf@redhat.com>
From: Max Reitz <mreitz@redhat.com>
Instead of using an assertion, it is better to emit a corruption event
here. Checking all offsets for correct alignment can be tedious and it
is easily possible to forget to do so. qcow2_cache_do_get() is a
function every L2 and refblock access has to go through, so this is a
good central point to add such a check.
And for good measure, let us also add an assertion that the offset is
non-zero. Making this a corruption event is not feasible, because a
zero offset usually means something special (such as the cluster is
unused), so all callers should be checking this anyway. If they do not,
it is their fault, hence the assertion here.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20171110203111.7666-6-mreitz@redhat.com
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/qcow2-cache.c | 21 +++++++++++++++++++++
tests/qemu-iotests/060 | 21 +++++++++++++++++++++
tests/qemu-iotests/060.out | 29 +++++++++++++++++++++++++++++
3 files changed, 71 insertions(+)
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 75746a7f43..a5baaba0ff 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -62,6 +62,18 @@ static inline int qcow2_cache_get_table_idx(BlockDriverState *bs,
return idx;
}
+static inline const char *qcow2_cache_get_name(BDRVQcow2State *s, Qcow2Cache *c)
+{
+ if (c == s->refcount_block_cache) {
+ return "refcount block";
+ } else if (c == s->l2_table_cache) {
+ return "L2 table";
+ } else {
+ /* Do not abort, because this is not critical */
+ return "unknown";
+ }
+}
+
static void qcow2_cache_table_release(BlockDriverState *bs, Qcow2Cache *c,
int i, int num_tables)
{
@@ -314,9 +326,18 @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
uint64_t min_lru_counter = UINT64_MAX;
int min_lru_index = -1;
+ assert(offset != 0);
+
trace_qcow2_cache_get(qemu_coroutine_self(), c == s->l2_table_cache,
offset, read_from_disk);
+ if (offset_into_cluster(s, offset)) {
+ qcow2_signal_corruption(bs, true, -1, -1, "Cannot get entry from %s "
+ "cache: Offset %#" PRIx64 " is unaligned",
+ qcow2_cache_get_name(s, c), offset);
+ return -EIO;
+ }
+
/* Check if the table is already cached */
i = lookup_index = (offset / s->cluster_size * 4) % c->size;
do {
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
index c230696b3a..1eca09417b 100755
--- a/tests/qemu-iotests/060
+++ b/tests/qemu-iotests/060
@@ -405,6 +405,27 @@ _check_test_img -r all
$QEMU_IMG resize --shrink "$TEST_IMG" 32M
_img_info | grep 'virtual size'
+echo
+echo "=== Discarding a refblock covered by an unaligned refblock ==="
+echo
+
+IMGOPTS='refcount_bits=1' _make_test_img 64M
+
+# Same as above
+poke_file "$TEST_IMG" "$(($rt_offset+8))" "\x00\x00\x00\x10\x00\x00\x00\x00"
+# But now we actually "create" an unaligned third refblock
+poke_file "$TEST_IMG" "$(($rt_offset+16))" "\x00\x00\x00\x00\x00\x00\x02\x00"
+$QEMU_IMG resize --shrink "$TEST_IMG" 32M
+
+echo '--- Repairing ---'
+# Fails the first repair because the corruption prevents the check
+# function from double-checking
+# (Using -q for the first invocation, because otherwise the
+# double-check error message appears above the summary for some
+# reason -- so let's just hide the summary)
+_check_test_img -q -r all
+_check_test_img -r all
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
index 358e54cdc9..56f5eb15d8 100644
--- a/tests/qemu-iotests/060.out
+++ b/tests/qemu-iotests/060.out
@@ -370,4 +370,33 @@ virtual size: 64M (67108864 bytes)
No errors were found on the image.
Image resized.
virtual size: 32M (33554432 bytes)
+
+=== Discarding a refblock covered by an unaligned refblock ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+qcow2: Marking image as corrupt: Cannot get entry from refcount block cache: Offset 0x200 is unaligned; further corruption events will be suppressed
+qemu-img: Failed to discard unused refblocks: Input/output error
+--- Repairing ---
+Repairing refcount block 1 is outside image
+ERROR refcount block 2 is not cluster aligned; refcount table entry corrupted
+qcow2: Marking image as corrupt: Refblock offset 0x200 unaligned (reftable index: 0x2); further corruption events will be suppressed
+Can't get refcount for cluster 1048576: Input/output error
+Rebuilding refcount structure
+Repairing cluster 1 refcount=1 reference=0
+Repairing cluster 2 refcount=1 reference=0
+Repairing cluster 1048576 refcount=1 reference=0
+qemu-img: Check failed: No medium found
+Leaked cluster 1 refcount=1 reference=0
+Leaked cluster 2 refcount=1 reference=0
+Leaked cluster 1048576 refcount=1 reference=0
+Repairing cluster 1 refcount=1 reference=0
+Repairing cluster 2 refcount=1 reference=0
+Repairing cluster 1048576 refcount=1 reference=0
+The following inconsistencies were found and repaired:
+
+ 3 leaked clusters
+ 0 corruptions
+
+Double checking the fixed image now...
+No errors were found on the image.
*** done
--
2.13.6
next prev parent reply other threads:[~2017-11-17 18:17 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-17 18:16 [Qemu-devel] [PULL 00/25] Block layer patches for 2.11.0-rc2 Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 01/25] replication: Fix replication open fail Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 02/25] qemu-iotests: Use -nographic in 182 Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 03/25] block: Fix error path in bdrv_backing_update_filename() Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 04/25] qcow2: don't permit changing encryption parameters Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 05/25] block: Deprecate bdrv_set_read_only() and users Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 06/25] qcow2: fix image corruption after committing qcow2 image into base Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 07/25] block: Fix permissions in image activation Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 08/25] iotests: test clearing unknown autoclear_features by qcow2 Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 09/25] qcow2: fix image corruption on commit with persistent bitmap Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 10/25] qapi/qnull: Add own header Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 11/25] qapi/qlist: Add qlist_append_null() macro Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 12/25] qapi: Add qobject_is_equal() Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 13/25] block: qobject_is_equal() in bdrv_reopen_prepare() Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 14/25] iotests: Add test for non-string option reopening Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 15/25] tests: Add check-qobject for equality tests Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 16/25] iotests: Add test for failing qemu-img commit Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 17/25] qcow2: reject unaligned offsets in write compressed Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 18/25] qcow2: check_errors are fatal Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 19/25] qcow2: Unaligned zero cluster in handle_alloc() Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 20/25] block: Guard against NULL bs->drv Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 21/25] qcow2: Add bounds check to get_refblock_offset() Kevin Wolf
2017-11-17 18:16 ` Kevin Wolf [this message]
2017-11-17 18:16 ` [Qemu-devel] [PULL 23/25] qcow2: Fix overly broad madvise() Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 24/25] block: Make bdrv_next() keep strong references Kevin Wolf
2017-11-17 18:16 ` [Qemu-devel] [PULL 25/25] iotests: Make 087 pass without AIO enabled Kevin Wolf
2017-11-20 14:53 ` [Qemu-devel] [PULL 00/25] Block layer patches for 2.11.0-rc2 Peter Maydell
2017-11-20 15:24 ` Kevin Wolf
2017-11-20 17:16 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171117181653.20651-23-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).