From nobody Wed Oct 22 15:24:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1519921811124970.309815606212; Thu, 1 Mar 2018 08:30:11 -0800 (PST) Received: from localhost ([::1]:57924 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR5u-0000wz-4G for importer@patchew.org; Thu, 01 Mar 2018 11:30:10 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41360) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR46-0008BY-Iz for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1erR41-0004KG-Hf for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:18 -0500 Received: from fanzine.igalia.com ([91.117.99.155]:54920) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1erR40-0003uQ-TH; Thu, 01 Mar 2018 11:28:13 -0500 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1erR3P-0003Db-Ep; Thu, 01 Mar 2018 17:27:35 +0100 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1erR36-0004OQ-Op; Thu, 01 Mar 2018 18:27:16 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=9+MgQ3UUxXkOiRKucr1U3m95ah94OII31wn0zEPIYlM=; b=JemJlgBDHxBM1FAlI4BS9Oo+1Dl+twLW61MKbGwVCjgCIcIiq6FfNxtA3kXS9kiu/NRBWhxKImmK/jVUSKJQ+NFiVcaXam5fUP7ki7cldemp1lpq+qe0uqN5fIsVEwO6/aLFiMi8P9D7AxIWRQYC0qnfhlf0HaW70MF5cOvVYK4hRzSWfjnKa8S0yWRbFHw2WexsBweZMmjeLmmJuZQuqhsfpoRP8q0rDFWreU+7a+zoWUZNBscfIO42vg/dsphGVemiTSJNHWyBouDUsB9VMO48lfAK5BNwezy4s9P2cldtx4Xv8ZSmxd+5y+xJlh1fSu2hX7CCBBpAZCk59UnnDA==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Thu, 1 Mar 2018 18:27:07 +0200 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH 1/7] qcow2: Generalize validate_table_offset() into qcow2_validate_table() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This function checks that the offset and size of a table are valid. While the offset checks are fine, the size check is too generic, since it only verifies that the total size in bytes fits in a 64-bit integer. In practice all tables used in qcow2 have much smaller size limits, so the size needs to be checked again for each table using its actual limit. This patch generalizes this function by allowing the caller to specify the maximum size for that table. In addition to that it allows passing an Error variable. The function is also renamed and made public since we're going to use it in other parts of the code. Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2.c | 77 ++++++++++++++++++------------------------= ---- block/qcow2.h | 10 +++--- tests/qemu-iotests/080.out | 16 +++++----- 3 files changed, 43 insertions(+), 60 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 57a517e2bd..4c695b3472 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -561,26 +561,23 @@ static int qcow2_check(BlockDriverState *bs, BdrvChec= kResult *result, return ret; } =20 -static int validate_table_offset(BlockDriverState *bs, uint64_t offset, - uint64_t entries, size_t entry_len) +int qcow2_validate_table(BlockDriverState *bs, uint64_t offset, + uint64_t entries, size_t entry_len, + int64_t max_size_bytes, const char *table_name, + Error **errp) { BDRVQcow2State *s =3D bs->opaque; - uint64_t size; + + if (entries > max_size_bytes / entry_len) { + error_setg(errp, "%s too large", table_name); + return -EFBIG; + } =20 /* Use signed INT64_MAX as the maximum even for uint64_t header fields, * because values will be passed to qemu functions taking int64_t. */ - if (entries > INT64_MAX / entry_len) { - return -EINVAL; - } - - size =3D entries * entry_len; - - if (INT64_MAX - size < offset) { - return -EINVAL; - } - - /* Tables must be cluster aligned */ - if (offset_into_cluster(s, offset) !=3D 0) { + if ((INT64_MAX - entries * entry_len < offset) || + (offset_into_cluster(s, offset) !=3D 0)) { + error_setg(errp, "%s offset invalid", table_name); return -EINVAL; } =20 @@ -1310,47 +1307,42 @@ static int qcow2_do_open(BlockDriverState *bs, QDic= t *options, int flags, s->refcount_table_size =3D header.refcount_table_clusters << (s->cluster_bits - 3); =20 - if (header.refcount_table_clusters > qcow2_max_refcount_clusters(s)) { - error_setg(errp, "Reference count table too large"); - ret =3D -EINVAL; - goto fail; - } - if (header.refcount_table_clusters =3D=3D 0 && !(flags & BDRV_O_CHECK)= ) { error_setg(errp, "Image does not contain a reference count table"); ret =3D -EINVAL; goto fail; } =20 - ret =3D validate_table_offset(bs, s->refcount_table_offset, - s->refcount_table_size, sizeof(uint64_t)); + ret =3D qcow2_validate_table(bs, s->refcount_table_offset, + header.refcount_table_clusters, + s->cluster_size, QCOW_MAX_REFTABLE_SIZE, + "Reference count table", errp); if (ret < 0) { - error_setg(errp, "Invalid reference count table offset"); goto fail; } =20 - /* Snapshot table offset/length */ - if (header.nb_snapshots > QCOW_MAX_SNAPSHOTS) { - error_setg(errp, "Too many snapshots"); - ret =3D -EINVAL; - goto fail; - } - - ret =3D validate_table_offset(bs, header.snapshots_offset, - header.nb_snapshots, - sizeof(QCowSnapshotHeader)); + /* The total size in bytes of the snapshot table is checked in + * qcow2_read_snapshots() because the size of each snapshot is + * variable and we don't know it yet. + * Here we only check the offset and number of snapshots. */ + ret =3D qcow2_validate_table(bs, header.snapshots_offset, + header.nb_snapshots, + sizeof(QCowSnapshotHeader), + sizeof(QCowSnapshotHeader) * QCOW_MAX_SNAPS= HOTS, + "Snapshot table", errp); if (ret < 0) { - error_setg(errp, "Invalid snapshot table offset"); goto fail; } =20 /* read the level 1 table */ - if (header.l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) { - error_setg(errp, "Active L1 table too large"); - ret =3D -EFBIG; + ret =3D qcow2_validate_table(bs, header.l1_table_offset, + header.l1_size, sizeof(uint64_t), + QCOW_MAX_L1_SIZE, "Active L1 table", errp); + if (ret < 0) { goto fail; } s->l1_size =3D header.l1_size; + s->l1_table_offset =3D header.l1_table_offset; =20 l1_vm_state_index =3D size_to_l1(s, header.size); if (l1_vm_state_index > INT_MAX) { @@ -1368,15 +1360,6 @@ static int qcow2_do_open(BlockDriverState *bs, QDict= *options, int flags, goto fail; } =20 - ret =3D validate_table_offset(bs, header.l1_table_offset, - header.l1_size, sizeof(uint64_t)); - if (ret < 0) { - error_setg(errp, "Invalid L1 table offset"); - goto fail; - } - s->l1_table_offset =3D header.l1_table_offset; - - if (s->l1_size > 0) { s->l1_table =3D qemu_try_blockalign(bs->file->bs, align_offset(s->l1_size * sizeof(uint64_t), 512)); diff --git a/block/qcow2.h b/block/qcow2.h index 883802241f..ef7910b149 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -491,11 +491,6 @@ static inline int64_t qcow2_vm_state_offset(BDRVQcow2S= tate *s) return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits); } =20 -static inline uint64_t qcow2_max_refcount_clusters(BDRVQcow2State *s) -{ - return QCOW_MAX_REFTABLE_SIZE >> s->cluster_bits; -} - static inline QCow2ClusterType qcow2_get_cluster_type(uint64_t l2_entry) { if (l2_entry & QCOW_OFLAG_COMPRESSED) { @@ -553,6 +548,11 @@ void qcow2_signal_corruption(BlockDriverState *bs, boo= l fatal, int64_t offset, int64_t size, const char *message_format, ...) GCC_FMT_ATTR(5, 6); =20 +int qcow2_validate_table(BlockDriverState *bs, uint64_t offset, + uint64_t entries, size_t entry_len, + int64_t max_size_bytes, const char *table_name, + Error **errp); + /* qcow2-refcount.c functions */ int qcow2_refcount_init(BlockDriverState *bs); void qcow2_refcount_close(BlockDriverState *bs); diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 6a7fda1356..4c7790c9ee 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -18,18 +18,18 @@ can't open device TEST_DIR/t.qcow2: Reference count tab= le too large =20 =3D=3D Misaligned refcount table =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 -can't open device TEST_DIR/t.qcow2: Invalid reference count table offset +can't open device TEST_DIR/t.qcow2: Reference count table offset invalid =20 =3D=3D Huge refcount offset =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 -can't open device TEST_DIR/t.qcow2: Invalid reference count table offset +can't open device TEST_DIR/t.qcow2: Reference count table offset invalid =20 =3D=3D Invalid snapshot table =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 -can't open device TEST_DIR/t.qcow2: Too many snapshots -can't open device TEST_DIR/t.qcow2: Too many snapshots -can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset -can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset +can't open device TEST_DIR/t.qcow2: Snapshot table too large +can't open device TEST_DIR/t.qcow2: Snapshot table too large +can't open device TEST_DIR/t.qcow2: Snapshot table offset invalid +can't open device TEST_DIR/t.qcow2: Snapshot table offset invalid =20 =3D=3D Hitting snapshot table size limit =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 @@ -41,8 +41,8 @@ read 512/512 bytes at offset 0 Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 can't open device TEST_DIR/t.qcow2: Active L1 table too large can't open device TEST_DIR/t.qcow2: Active L1 table too large -can't open device TEST_DIR/t.qcow2: Invalid L1 table offset -can't open device TEST_DIR/t.qcow2: Invalid L1 table offset +can't open device TEST_DIR/t.qcow2: Active L1 table offset invalid +can't open device TEST_DIR/t.qcow2: Active L1 table offset invalid =20 =3D=3D Invalid L1 table (with internal snapshot in the image) =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 --=20 2.11.0 From nobody Wed Oct 22 15:24:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1519921982155431.41562181902657; Thu, 1 Mar 2018 08:33:02 -0800 (PST) Received: from localhost ([::1]:57943 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR8b-0003AW-Pz for importer@patchew.org; Thu, 01 Mar 2018 11:32:57 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41354) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR46-0008BX-ID for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1erR41-0004Jo-Dq for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:18 -0500 Received: from fanzine.igalia.com ([91.117.99.155]:54926) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1erR40-0003uD-Tg; Thu, 01 Mar 2018 11:28:13 -0500 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1erR3P-0003De-Ij; Thu, 01 Mar 2018 17:27:35 +0100 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1erR36-0004OS-Ps; Thu, 01 Mar 2018 18:27:16 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=y7D8vBY0sTVfMEQf3CQZBbtjX071Jl3HOZlk3wS2e9A=; b=hBehUWriAmSbtfq546CLho2rlv+IrHGL2TeT6cH0y1HhCYT0cWqQpsuwJnadswO+DSG+agp0t9W+0sfp5T27Ld1Qeahhdgkn0NsyDK1D0PpP105EwvxjrsnK7M4rvAM4MqHw64JD68yX2J5e+sTxschgZo/JEjLp+NzbH5OXpU3Oimqmje62BC6R2mjTKqKAIo8xqO8WjUEOQiXRN+PMcTnh3fB7aciQ3j1z9jQxXmzkdtUaz6PuJPacWUeKFPVSgnI9Qb+J/M1wIyD/RELiMZYKZZWUGzkJR4fCfjwfIbWSI/T4tSoBGferjy03gKZJFM2JmN+pS/hE1FVAX4rSOg==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Thu, 1 Mar 2018 18:27:08 +0200 Message-Id: <867f70a315f3b30aca22ab6ae90555bfa8e79c20.1519921268.git.berto@igalia.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH 2/7] qcow2: Check L1 table offset in qcow2_snapshot_load_tmp() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This function checks that the size of a snapshot's L1 table is not too large, but it doesn't validate the offset. We now have a function to take care of this, so let's use it. Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2-snapshot.c | 8 +++++--- tests/qemu-iotests/080 | 10 +++++++++- tests/qemu-iotests/080.out | 8 +++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 44243e0e95..98bb039295 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -704,9 +704,11 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, sn =3D &s->snapshots[snapshot_index]; =20 /* Allocate and read in the snapshot's L1 table */ - if (sn->l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) { - error_setg(errp, "Snapshot L1 table too large"); - return -EFBIG; + ret =3D qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size, + sizeof(uint64_t), QCOW_MAX_L1_SIZE, + "Snapshot L1 table", errp); + if (ret < 0) { + return ret; } new_l1_bytes =3D sn->l1_size * sizeof(uint64_t); new_l1_table =3D qemu_try_blockalign(bs->file->bs, diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 1c2bd85742..6a10e7defa 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -171,7 +171,15 @@ poke_file "$TEST_IMG" "$offset_l2_table_0" "\x80\x00\x= 00\xff\xff\xff\x00\x00" { $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter= _testdir =20 echo -echo "=3D=3D Invalid snapshot L1 table =3D=3D" +echo "=3D=3D Invalid snapshot L1 table offset =3D=3D" +_make_test_img 64M +{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_= testdir +{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir +poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\= x02\x00" +{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_tes= tdir + +echo +echo "=3D=3D Invalid snapshot L1 table size =3D=3D" _make_test_img 64M { $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_= testdir { $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 4c7790c9ee..f0d9038d55 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -59,7 +59,13 @@ wrote 512/512 bytes at offset 0 qemu-img: Could not create snapshot 'test': -27 (File too large) qemu-img: Could not create snapshot 'test': -11 (Resource temporarily unav= ailable) =20 -=3D=3D Invalid snapshot L1 table =3D=3D +=3D=3D Invalid snapshot L1 table offset =3D=3D +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Failed to load snapshot: Snapshot L1 table offset invalid + +=3D=3D Invalid snapshot L1 table size =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) --=20 2.11.0 From nobody Wed Oct 22 15:24:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1519922480035921.1359946849007; Thu, 1 Mar 2018 08:41:20 -0800 (PST) Received: from localhost ([::1]:58008 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erRGh-0001eo-0P for importer@patchew.org; Thu, 01 Mar 2018 11:41:19 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41351) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR46-0008BU-HI for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1erR41-0004Jc-Ff for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:18 -0500 Received: from fanzine.igalia.com ([91.117.99.155]:54922) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1erR40-0003uP-TJ; Thu, 01 Mar 2018 11:28:13 -0500 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1erR3P-0003Da-IF; Thu, 01 Mar 2018 17:27:35 +0100 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1erR36-0004OU-Qr; Thu, 01 Mar 2018 18:27:16 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=uVZAwB2g/CoxGOAF7C3FcUPBisvUQ9solApNHKy/PgM=; b=SlnqMfU1toqidaIs8PGODMD/8FWmklIOIhGOlj1i+xbFJ0BKw8vmLBL2UzBxmhvI6HDGgSoy6P80UAIJKTF6r54YTVWqF/ZQ6fLcll3hbqlbxJLyLBZBKpPQ4bPRdPgAIKBdwu0yPP2UELMmMrlq2JTVpFDMKJ8HlGr0SZGtBIvWGWEv5dZtnbs8AKwLUgBNh3bSRrrFmchqjpYd3+Rdq9HZZRO/yurcsdXM2PEkR1hFR+r1PjLnmeYMcmS3Tr3x+CUIjELfQ4w6zu8POLI+POkM/cNJcEQhceyeej6WOqheTq1zKzHhdOwyRY6p4u5LbQo6BQIL484yZCwtgIvWMw==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Thu, 1 Mar 2018 18:27:09 +0200 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH 3/7] qcow2: Check L1 table parameters in qcow2_expand_zero_clusters() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This function iterates over all snapshots of a qcow2 file in order to expand all zero clusters, but it does not validate the snapshots' L1 tables first. We now have a function to take care of this, so let's use it. We can also take the opportunity to replace the sector-based bdrv_read() with bdrv_pread(). Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2-cluster.c | 20 +++++++++++++------- tests/qemu-iotests/080 | 2 ++ tests/qemu-iotests/080.out | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index e406b0f3b9..40167ac09c 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -2092,11 +2092,18 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs, } =20 for (i =3D 0; i < s->nb_snapshots; i++) { - int l1_sectors =3D DIV_ROUND_UP(s->snapshots[i].l1_size * - sizeof(uint64_t), BDRV_SECTOR_SIZE); + int l1_size2; + uint64_t *new_l1_table; =20 - uint64_t *new_l1_table =3D - g_try_realloc(l1_table, l1_sectors * BDRV_SECTOR_SIZE); + ret =3D qcow2_validate_table(bs, s->snapshots[i].l1_table_offset, + s->snapshots[i].l1_size, sizeof(uint64_= t), + QCOW_MAX_L1_SIZE, "", NULL); + if (ret < 0) { + return ret; + } + + l1_size2 =3D s->snapshots[i].l1_size * sizeof(uint64_t); + new_l1_table =3D g_try_realloc(l1_table, l1_size2); =20 if (!new_l1_table) { ret =3D -ENOMEM; @@ -2105,9 +2112,8 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs, =20 l1_table =3D new_l1_table; =20 - ret =3D bdrv_read(bs->file, - s->snapshots[i].l1_table_offset / BDRV_SECTOR_SIZE, - (void *)l1_table, l1_sectors); + ret =3D bdrv_pread(bs->file, s->snapshots[i].l1_table_offset, + l1_table, l1_size2); if (ret < 0) { goto fail; } diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 6a10e7defa..5622604f83 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -177,6 +177,7 @@ _make_test_img 64M { $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\= x02\x00" { $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_tes= tdir +{ $QEMU_IMG amend -o compat=3D0.10 $TEST_IMG; } 2>&1 | _filter_testdir =20 echo echo "=3D=3D Invalid snapshot L1 table size =3D=3D" @@ -185,6 +186,7 @@ _make_test_img 64M { $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00" { $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_tes= tdir +{ $QEMU_IMG amend -o compat=3D0.10 $TEST_IMG; } 2>&1 | _filter_testdir =20 # success, all done echo "*** done" diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index f0d9038d55..5d9030ab93 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -64,10 +64,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D671= 08864 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Failed to load snapshot: Snapshot L1 table offset invalid +qemu-img: Error while amending options: Invalid argument =20 =3D=3D Invalid snapshot L1 table size =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Failed to load snapshot: Snapshot L1 table too large +qemu-img: Error while amending options: File too large *** done --=20 2.11.0 From nobody Wed Oct 22 15:24:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1519921805833361.252235704114; Thu, 1 Mar 2018 08:30:05 -0800 (PST) Received: from localhost ([::1]:57923 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR5k-0000o1-43 for importer@patchew.org; Thu, 01 Mar 2018 11:30:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41352) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR46-0008BV-HA for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1erR41-0004K8-HK for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:18 -0500 Received: from fanzine.igalia.com ([91.117.99.155]:54927) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1erR40-0003uM-Te; Thu, 01 Mar 2018 11:28:13 -0500 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1erR3P-0003Dc-IR; Thu, 01 Mar 2018 17:27:35 +0100 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1erR36-0004OW-S0; Thu, 01 Mar 2018 18:27:16 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=SutdRM4TbbzoQm94sdn/9lSOfZF9w2LL5yxzEinQsU4=; b=Y8MdCZRziuXI5vuxPZ6rh4LmLbU3QOYmHgJ0ZUfmVyiwgz2Q0H9nokAPkDae/wmG0MFQkF2v4/6Nrm3q3FLFtf5kpMrizzzkRgWv2jiHwa3PoJuHPx0VictqK9dSMGylMzBhN+DR8SDYXehqeJZaZaxq+OmUv4EkevxpW49HE+Hs+rgKDX+AR0en8SkkrtLMjgiKvpP8Iz9ZqZ0Acx8DO47BqwC0YwvhA6eHljYF8gA9a2rVmXVTRMiYUsKRgEGbUij59alCJ6KyMRCMGDOaA7Uj04tCaMKEcxjA6ZOMPNzMCj2VHilS/Safo1Usu2Bd43WTRWp3jXh77bVWRrwNfQ==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Thu, 1 Mar 2018 18:27:10 +0200 Message-Id: <39f9a5666cc50c3733d01d4d01fb514a5a5da9a5.1519921268.git.berto@igalia.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH 4/7] qcow2: Check snapshot L1 tables in qcow2_check_metadata_overlap() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The inactive-l2 overlap check iterates uses the L1 tables from all snapshots, but it does not validate them first. We now have a function to take care of this, so let's use it. Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2-refcount.c | 10 +++++++++- tests/qemu-iotests/080 | 4 ++++ tests/qemu-iotests/080.out | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index d46b69d7f3..dcb96e2b16 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -2614,9 +2614,17 @@ int qcow2_check_metadata_overlap(BlockDriverState *b= s, int ign, int64_t offset, uint64_t l1_ofs =3D s->snapshots[i].l1_table_offset; uint32_t l1_sz =3D s->snapshots[i].l1_size; uint64_t l1_sz2 =3D l1_sz * sizeof(uint64_t); - uint64_t *l1 =3D g_try_malloc(l1_sz2); + uint64_t *l1; int ret; =20 + ret =3D qcow2_validate_table(bs, l1_ofs, l1_sz, sizeof(uint64_= t), + QCOW_MAX_L1_SIZE, "", NULL); + if (ret < 0) { + return ret; + } + + l1 =3D g_try_malloc(l1_sz2); + if (l1_sz2 && l1 =3D=3D NULL) { return -ENOMEM; } diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 5622604f83..018f815697 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -178,6 +178,8 @@ _make_test_img 64M poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\= x02\x00" { $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_tes= tdir { $QEMU_IMG amend -o compat=3D0.10 $TEST_IMG; } 2>&1 | _filter_testdir +{ $QEMU_IO -c "open -o overlap-check.inactive-l2=3Don $TEST_IMG" \ + -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir =20 echo echo "=3D=3D Invalid snapshot L1 table size =3D=3D" @@ -187,6 +189,8 @@ _make_test_img 64M poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00" { $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_tes= tdir { $QEMU_IMG amend -o compat=3D0.10 $TEST_IMG; } 2>&1 | _filter_testdir +{ $QEMU_IO -c "open -o overlap-check.inactive-l2=3Don $TEST_IMG" \ + -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir =20 # success, all done echo "*** done" diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 5d9030ab93..cf8f863be2 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -65,6 +65,8 @@ wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Failed to load snapshot: Snapshot L1 table offset invalid qemu-img: Error while amending options: Invalid argument +Failed to flush the refcount block cache: Invalid argument +write failed: Invalid argument =20 =3D=3D Invalid snapshot L1 table size =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 @@ -72,4 +74,6 @@ wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Failed to load snapshot: Snapshot L1 table too large qemu-img: Error while amending options: File too large +Failed to flush the refcount block cache: File too large +write failed: File too large *** done --=20 2.11.0 From nobody Wed Oct 22 15:24:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1519921976890355.38851918475996; Thu, 1 Mar 2018 08:32:56 -0800 (PST) Received: from localhost ([::1]:57942 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR8Z-00038O-R5 for importer@patchew.org; Thu, 01 Mar 2018 11:32:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41362) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR46-0008BZ-Jf for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1erR41-0004Jb-ET for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:18 -0500 Received: from fanzine.igalia.com ([91.117.99.155]:54929) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1erR40-0003uH-TW; Thu, 01 Mar 2018 11:28:13 -0500 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1erR3P-0003Dg-IV; Thu, 01 Mar 2018 17:27:35 +0100 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1erR36-0004OY-T1; Thu, 01 Mar 2018 18:27:16 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=Li1T6yxaFBJNbBB8mLjnbwRJ7GDpsEuoUtdp5LBFNFk=; b=IFo69MwmScS4KyXC/qZyzJaoJsXLRdD06oFagKfZZiC8hp7hmtQWmVCiTYstkHJZ4UKI5fh5bjGpzAqhw1YpVC/gn+ZxD0N4YdPIAWDAx7CuvHkSxAdsrvbUajGvnhe1QRF3gFjzfbxhhuWtKy/TE2U/lI8EEqjtnKivnBC8mfUQenPZTwpVmxb0nouOJFWBEEpL7ShtMxxgiKhjliAZyuA+qxppJ66TtmykKKYfmD+QdTMw5go4DpsJgoTVU+8lOulem9Sh0pwL35njl6Yke7SxZrToQD0dh0vRJMscAw8Rw2lHdak0wWRNyI+TTiIiGWV+3nrIoHykPNj2RfI/gg==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Thu, 1 Mar 2018 18:27:11 +0200 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH 5/7] qcow2: Check snapshot L1 table in qcow2_snapshot_goto() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This function copies a snapshot's L1 table into the active one without validating it first. We now have a function to take care of this, so let's use it. Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2-snapshot.c | 6 ++++++ tests/qemu-iotests/080 | 2 ++ tests/qemu-iotests/080.out | 2 ++ 3 files changed, 10 insertions(+) diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 98bb039295..f1be5506a2 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -477,6 +477,12 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const ch= ar *snapshot_id) } sn =3D &s->snapshots[snapshot_index]; =20 + ret =3D qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size, + sizeof(uint64_t), QCOW_MAX_L1_SIZE, "", NUL= L); + if (ret < 0) { + goto fail; + } + if (sn->disk_size !=3D bs->total_sectors * BDRV_SECTOR_SIZE) { error_report("qcow2: Loading snapshots with different disk " "size is not implemented"); diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 018f815697..538857310f 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -180,6 +180,7 @@ poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x= 00\x00\x00\x00\x40\x02\x0 { $QEMU_IMG amend -o compat=3D0.10 $TEST_IMG; } 2>&1 | _filter_testdir { $QEMU_IO -c "open -o overlap-check.inactive-l2=3Don $TEST_IMG" \ -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir +{ $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir =20 echo echo "=3D=3D Invalid snapshot L1 table size =3D=3D" @@ -191,6 +192,7 @@ poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00= \x00\x00" { $QEMU_IMG amend -o compat=3D0.10 $TEST_IMG; } 2>&1 | _filter_testdir { $QEMU_IO -c "open -o overlap-check.inactive-l2=3Don $TEST_IMG" \ -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir +{ $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir =20 # success, all done echo "*** done" diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index cf8f863be2..35c768aff3 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -67,6 +67,7 @@ qemu-img: Failed to load snapshot: Snapshot L1 table offs= et invalid qemu-img: Error while amending options: Invalid argument Failed to flush the refcount block cache: Invalid argument write failed: Invalid argument +qemu-img: Could not apply snapshot 'test': Failed to load snapshot: Invali= d argument =20 =3D=3D Invalid snapshot L1 table size =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 @@ -76,4 +77,5 @@ qemu-img: Failed to load snapshot: Snapshot L1 table too = large qemu-img: Error while amending options: File too large Failed to flush the refcount block cache: File too large write failed: File too large +qemu-img: Could not apply snapshot 'test': Failed to load snapshot: File t= oo large *** done --=20 2.11.0 From nobody Wed Oct 22 15:24:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1519922134010168.81041540883496; Thu, 1 Mar 2018 08:35:34 -0800 (PST) Received: from localhost ([::1]:57963 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erRB2-0005LG-UX for importer@patchew.org; Thu, 01 Mar 2018 11:35:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41353) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR46-0008BW-HQ for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1erR41-0004Jx-Fj for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:18 -0500 Received: from fanzine.igalia.com ([91.117.99.155]:54919) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1erR40-0003uK-TM; Thu, 01 Mar 2018 11:28:13 -0500 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1erR3P-0003Df-IZ; Thu, 01 Mar 2018 17:27:35 +0100 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1erR36-0004Oa-U9; Thu, 01 Mar 2018 18:27:16 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=BCwcELryjpTPhmvQNazAW2Yos7og3MqTalTG/q4X/o0=; b=kRS/SgkY/05+ATnokuONKxn7NZjcPSRhwM9IBZ0LYtD7R/oHDaviSaRtyV3hTVdUXzu82YGa6AXVpSsq6qDH4t9X8/Lcvhch/XoBxfnjfjMwZTJWw6F8dEj7WJZ1MriOlgjV8JSHNu83C6HEns+omdDboeVn/5i1gu9LZTU+OyKI4dOoWetAI+G2Oz16QklTrYJVPsLXKvbiiHZKP1d7XxGhuefEWABBDd5DPKGjvY2zeLlLaAKqAKOMXfZcOiLECmiPsyiV8Tv8UkuCcfs8FVfiBVVoI+PgmvsoLwkgSVZRU18wIVyeIqG7XlOAomSv77xvEEKd+emeO4fdrBRf7A==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Thu, 1 Mar 2018 18:27:12 +0200 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH 6/7] qcow2: Check snapshot L1 table in qcow2_snapshot_delete() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This function deletes a snapshot from disk, removing its entry from the snapshot table, freeing its L1 table and decreasing the refcounts of all clusters. The L1 table offset and size are however not validated. If we use invalid values in this function we'll probably corrupt the image even more, so we should return an error instead. We now have a function to take care of this, so let's use it. Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2-snapshot.c | 7 +++++++ tests/qemu-iotests/080 | 2 ++ tests/qemu-iotests/080.out | 2 ++ 3 files changed, 11 insertions(+) diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index f1be5506a2..727a3d79de 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -608,6 +608,13 @@ int qcow2_snapshot_delete(BlockDriverState *bs, } sn =3D s->snapshots[snapshot_index]; =20 + ret =3D qcow2_validate_table(bs, sn.l1_table_offset, sn.l1_size, + sizeof(uint64_t), QCOW_MAX_L1_SIZE, + "Snapshot L1 table", errp); + if (ret < 0) { + return ret; + } + /* Remove it from the snapshot list */ memmove(s->snapshots + snapshot_index, s->snapshots + snapshot_index + 1, diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 538857310f..f8e7d6f4df 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -181,6 +181,7 @@ poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x= 00\x00\x00\x00\x40\x02\x0 { $QEMU_IO -c "open -o overlap-check.inactive-l2=3Don $TEST_IMG" \ -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir { $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir +{ $QEMU_IMG snapshot -d test $TEST_IMG; } 2>&1 | _filter_testdir =20 echo echo "=3D=3D Invalid snapshot L1 table size =3D=3D" @@ -193,6 +194,7 @@ poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00= \x00\x00" { $QEMU_IO -c "open -o overlap-check.inactive-l2=3Don $TEST_IMG" \ -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir { $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir +{ $QEMU_IMG snapshot -d test $TEST_IMG; } 2>&1 | _filter_testdir =20 # success, all done echo "*** done" diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 35c768aff3..f16fd59053 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -68,6 +68,7 @@ qemu-img: Error while amending options: Invalid argument Failed to flush the refcount block cache: Invalid argument write failed: Invalid argument qemu-img: Could not apply snapshot 'test': Failed to load snapshot: Invali= d argument +qemu-img: Could not delete snapshot 'test': Snapshot L1 table offset inval= id =20 =3D=3D Invalid snapshot L1 table size =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 @@ -78,4 +79,5 @@ qemu-img: Error while amending options: File too large Failed to flush the refcount block cache: File too large write failed: File too large qemu-img: Could not apply snapshot 'test': Failed to load snapshot: File t= oo large +qemu-img: Could not delete snapshot 'test': Snapshot L1 table too large *** done --=20 2.11.0 From nobody Wed Oct 22 15:24:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1519922302867477.20226770636475; Thu, 1 Mar 2018 08:38:22 -0800 (PST) Received: from localhost ([::1]:57987 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erRDj-0007Py-4b for importer@patchew.org; Thu, 01 Mar 2018 11:38:15 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41350) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erR46-0008BT-H3 for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1erR41-0004K5-GU for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:28:18 -0500 Received: from fanzine.igalia.com ([91.117.99.155]:54930) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1erR40-0003uO-Tb; Thu, 01 Mar 2018 11:28:13 -0500 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1erR3P-0003Dh-RY; Thu, 01 Mar 2018 17:27:35 +0100 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1erR36-0004Oh-VF; Thu, 01 Mar 2018 18:27:16 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=soRhI3HOwQgIzdDFduXWlQyyZejLosAlsFnasmofjXE=; b=BZFfbeG8EojCoh3QtPnegGwUcgT6Ke4KGw8TON/xed4uHzSggNAWmeXHbZdvV6PO1aagSsUrlIFYnvlbLTDjcQFYoiYszzlYS/hiFWfvsPjRxFEFpgX+EED5OuuQbsiYQVc4pXXbo1RiwcfKytM24rDBSvv5KPicrHfAFSaZgSV7krUedpcGvZr0sbKJqi3rBs+ZTaBezwbk5LziZlihsNWqQUuDm8v2/5iV07HVh1T4OG57CxQnPzYJrPNqm7kitroNpO6uVRO4Cv4LvUwmpcegHDk1jjtQcUmPpI7JpfqKNlXtboShNAedex6GbrnUHJo1iVpAq8S3J402J1XLmw==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Thu, 1 Mar 2018 18:27:13 +0200 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH 7/7] qcow2: Make qemu-img check detect corrupted L1 tables in snapshots X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 'qemu-img check' cannot detect if a snapshot's L1 table is corrupted. This patch checks the table's offset and size and reports corruption if the values are not valid. This patch doesn't add code to fix that corruption yet, only to detect and report it. Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2-refcount.c | 14 ++++++++++++++ tests/qemu-iotests/080 | 2 ++ tests/qemu-iotests/080.out | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index dcb96e2b16..b1828d6fce 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -2019,6 +2019,20 @@ static int calculate_refcounts(BlockDriverState *bs,= BdrvCheckResult *res, /* snapshots */ for (i =3D 0; i < s->nb_snapshots; i++) { sn =3D s->snapshots + i; + if (offset_into_cluster(s, sn->l1_table_offset)) { + fprintf(stderr, "ERROR snapshot %s (%s) l1_offset=3D%#" PRIx64= ": " + "L1 table is not cluster aligned; snapshot table entry= " + "corrupted\n", sn->id_str, sn->name, sn->l1_table_offs= et); + res->corruptions++; + continue; + } + if (sn->l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) { + fprintf(stderr, "ERROR snapshot %s (%s) l1_size=3D%#" PRIx32 "= : " + "L1 table is too large; snapshot table entry corrupted= \n", + sn->id_str, sn->name, sn->l1_size); + res->corruptions++; + continue; + } ret =3D check_refcounts_l1(bs, res, refcount_table, nb_clusters, sn->l1_table_offset, sn->l1_size, 0, fix); if (ret < 0) { diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index f8e7d6f4df..4dbe68e950 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -182,6 +182,7 @@ poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x= 00\x00\x00\x00\x40\x02\x0 -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir { $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir { $QEMU_IMG snapshot -d test $TEST_IMG; } 2>&1 | _filter_testdir +_check_test_img =20 echo echo "=3D=3D Invalid snapshot L1 table size =3D=3D" @@ -195,6 +196,7 @@ poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00= \x00\x00" -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir { $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir { $QEMU_IMG snapshot -d test $TEST_IMG; } 2>&1 | _filter_testdir +_check_test_img =20 # success, all done echo "*** done" diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index f16fd59053..2dad7f46a0 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -69,6 +69,16 @@ Failed to flush the refcount block cache: Invalid argume= nt write failed: Invalid argument qemu-img: Could not apply snapshot 'test': Failed to load snapshot: Invali= d argument qemu-img: Could not delete snapshot 'test': Snapshot L1 table offset inval= id +ERROR snapshot 1 (test) l1_offset=3D0x400200: L1 table is not cluster alig= ned; snapshot table entry corrupted +Leaked cluster 4 refcount=3D2 reference=3D1 +Leaked cluster 5 refcount=3D2 reference=3D1 +Leaked cluster 6 refcount=3D1 reference=3D0 + +1 errors were found on the image. +Data may be corrupted, or further writes to the image may corrupt it. + +3 leaked clusters were found on the image. +This means waste of disk space, but no harm to data. =20 =3D=3D Invalid snapshot L1 table size =3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 @@ -80,4 +90,14 @@ Failed to flush the refcount block cache: File too large write failed: File too large qemu-img: Could not apply snapshot 'test': Failed to load snapshot: File t= oo large qemu-img: Could not delete snapshot 'test': Snapshot L1 table too large +ERROR snapshot 1 (test) l1_size=3D0x10000000: L1 table is too large; snaps= hot table entry corrupted +Leaked cluster 4 refcount=3D2 reference=3D1 +Leaked cluster 5 refcount=3D2 reference=3D1 +Leaked cluster 6 refcount=3D1 reference=3D0 + +1 errors were found on the image. +Data may be corrupted, or further writes to the image may corrupt it. + +3 leaked clusters were found on the image. +This means waste of disk space, but no harm to data. *** done --=20 2.11.0