From nobody Sat May 18 08:35:39 2024 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; 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; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1539271132128886.6633863788252; Thu, 11 Oct 2018 08:18:52 -0700 (PDT) Received: from localhost ([::1]:35058 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAcjg-0007uX-3J for importer@patchew.org; Thu, 11 Oct 2018 11:18:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59605) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAchX-0006af-Ue for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gAchU-0006h5-LF for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:35 -0400 Received: from relay.sw.ru ([185.231.240.75]:35514) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gAchU-0006di-9T; Thu, 11 Oct 2018 11:16:32 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gAchN-0002Z5-9s; Thu, 11 Oct 2018 18:16:25 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 11 Oct 2018 18:16:16 +0300 Message-Id: <20181011151623.25702-2-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181011151623.25702-1-vsementsov@virtuozzo.com> References: <20181011151623.25702-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v3 1/8] block/qcow2-refcount: fix check_oflag_copied 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: kwolf@redhat.com, den@openvz.org, vsementsov@virtuozzo.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Increase corruptions_fixed only after successful fix. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/qcow2-refcount.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 3c539f02e5..b453d87a3f 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1816,7 +1816,7 @@ static int check_oflag_copied(BlockDriverState *bs, B= drvCheckResult *res, for (i =3D 0; i < s->l1_size; i++) { uint64_t l1_entry =3D s->l1_table[i]; uint64_t l2_offset =3D l1_entry & L1E_OFFSET_MASK; - bool l2_dirty =3D false; + int l2_dirty =3D 0; =20 if (!l2_offset) { continue; @@ -1878,8 +1878,7 @@ static int check_oflag_copied(BlockDriverState *bs, B= drvCheckResult *res, l2_table[j] =3D cpu_to_be64(refcount =3D=3D 1 ? l2_entry | QCOW_OFLAG_COPIED : l2_entry & ~QCOW_OFLAG_COPIED); - l2_dirty =3D true; - res->corruptions_fixed++; + l2_dirty++; } else { res->corruptions++; } @@ -1887,7 +1886,7 @@ static int check_oflag_copied(BlockDriverState *bs, B= drvCheckResult *res, } } =20 - if (l2_dirty) { + if (l2_dirty > 0) { ret =3D qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L2, l2_offset, s->cluster_size= ); if (ret < 0) { @@ -1905,6 +1904,7 @@ static int check_oflag_copied(BlockDriverState *bs, B= drvCheckResult *res, res->check_errors++; goto fail; } + res->corruptions_fixed +=3D l2_dirty; } } =20 --=20 2.18.0 From nobody Sat May 18 08:35:39 2024 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; 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; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 153927113212894.50773028219066; Thu, 11 Oct 2018 08:18:52 -0700 (PDT) Received: from localhost ([::1]:35057 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAcje-0007uF-SC for importer@patchew.org; Thu, 11 Oct 2018 11:18:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59610) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAchX-0006aj-VY for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gAchU-0006hA-M8 for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:35 -0400 Received: from relay.sw.ru ([185.231.240.75]:35516) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gAchU-0006dj-9X; Thu, 11 Oct 2018 11:16:32 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gAchN-0002Z5-P9; Thu, 11 Oct 2018 18:16:25 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 11 Oct 2018 18:16:17 +0300 Message-Id: <20181011151623.25702-3-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181011151623.25702-1-vsementsov@virtuozzo.com> References: <20181011151623.25702-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v3 2/8] block/qcow2-refcount: avoid eating RAM 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: kwolf@redhat.com, den@openvz.org, vsementsov@virtuozzo.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" qcow2_inc_refcounts_imrt() (through realloc_refcount_array()) can eat an unpredictable amount of memory on corrupted table entries, which are referencing regions far beyond the end of file. Prevent this, by skipping such regions from further processing. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/qcow2-refcount.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index b453d87a3f..afaa1a1409 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1499,12 +1499,30 @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, = BdrvCheckResult *res, { BDRVQcow2State *s =3D bs->opaque; uint64_t start, last, cluster_offset, k, refcount; + int64_t file_len; int ret; =20 if (size <=3D 0) { return 0; } =20 + file_len =3D bdrv_getlength(bs->file->bs); + if (file_len < 0) { + return file_len; + } + + /* Last cluster of qcow2 image may be semi-allocated, so it's may be O= K to + * reference some space after file end but it should be less than one + * cluster. + */ + if (offset + size - file_len >=3D s->cluster_size) { + fprintf(stderr, "ERROR: counting reference for region exceeding th= e " + "end of the file by one cluster or more: offset 0x%" PRIx64 + " size 0x%" PRIx64 "\n", offset, size); + res->corruptions++; + return 0; + } + start =3D start_of_cluster(s, offset); last =3D start_of_cluster(s, offset + size - 1); for(cluster_offset =3D start; cluster_offset <=3D last; --=20 2.18.0 From nobody Sat May 18 08:35:39 2024 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; 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; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1539271299668150.55598711495554; Thu, 11 Oct 2018 08:21:39 -0700 (PDT) Received: from localhost ([::1]:35079 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAcmL-0001fe-EQ for importer@patchew.org; Thu, 11 Oct 2018 11:21:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59606) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAchX-0006ag-V6 for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gAchV-0006hl-1H for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:35 -0400 Received: from relay.sw.ru ([185.231.240.75]:35524) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gAchU-0006eP-LJ; Thu, 11 Oct 2018 11:16:32 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gAchO-0002Z5-D8; Thu, 11 Oct 2018 18:16:26 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 11 Oct 2018 18:16:18 +0300 Message-Id: <20181011151623.25702-4-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181011151623.25702-1-vsementsov@virtuozzo.com> References: <20181011151623.25702-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v3 3/8] block/qcow2-refcount: check_refcounts_l2: refactor compressed case 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: kwolf@redhat.com, den@openvz.org, vsementsov@virtuozzo.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Separate offset and size of compressed cluster. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/qcow2-refcount.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index afaa1a1409..23b105b43b 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1574,7 +1574,7 @@ static int check_refcounts_l2(BlockDriverState *bs, B= drvCheckResult *res, BDRVQcow2State *s =3D bs->opaque; uint64_t *l2_table, l2_entry; uint64_t next_contiguous_offset =3D 0; - int i, l2_size, nb_csectors, ret; + int i, l2_size, ret; =20 /* Read L2 table from disk */ l2_size =3D s->l2_size * sizeof(uint64_t); @@ -1593,6 +1593,9 @@ static int check_refcounts_l2(BlockDriverState *bs, B= drvCheckResult *res, =20 switch (qcow2_get_cluster_type(l2_entry)) { case QCOW2_CLUSTER_COMPRESSED: + { + int64_t csize, coffset; + /* Compressed clusters don't have QCOW_OFLAG_COPIED */ if (l2_entry & QCOW_OFLAG_COPIED) { fprintf(stderr, "ERROR: coffset=3D0x%" PRIx64 ": " @@ -1603,12 +1606,11 @@ static int check_refcounts_l2(BlockDriverState *bs,= BdrvCheckResult *res, } =20 /* Mark cluster as used */ - nb_csectors =3D ((l2_entry >> s->csize_shift) & - s->csize_mask) + 1; - l2_entry &=3D s->cluster_offset_mask; + csize =3D (((l2_entry >> s->csize_shift) & s->csize_mask) + 1)= * 512; + coffset =3D l2_entry & s->cluster_offset_mask & ~511; ret =3D qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_= size, - l2_entry & ~511, nb_csectors * = 512); + coffset, csize); if (ret < 0) { goto fail; } @@ -1625,6 +1627,7 @@ static int check_refcounts_l2(BlockDriverState *bs, B= drvCheckResult *res, res->bfi.fragmented_clusters++; } break; + } =20 case QCOW2_CLUSTER_ZERO_ALLOC: case QCOW2_CLUSTER_NORMAL: --=20 2.18.0 From nobody Sat May 18 08:35:39 2024 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; 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; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1539271527801260.63662233036655; Thu, 11 Oct 2018 08:25:27 -0700 (PDT) Received: from localhost ([::1]:35100 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAcq6-0004R2-QP for importer@patchew.org; Thu, 11 Oct 2018 11:25:26 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59619) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAchY-0006an-0E for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gAchU-0006ha-Ue for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:35 -0400 Received: from relay.sw.ru ([185.231.240.75]:35530) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gAchU-0006el-Hs; Thu, 11 Oct 2018 11:16:32 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gAchP-0002Z5-AH; Thu, 11 Oct 2018 18:16:27 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 11 Oct 2018 18:16:19 +0300 Message-Id: <20181011151623.25702-5-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181011151623.25702-1-vsementsov@virtuozzo.com> References: <20181011151623.25702-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v3 4/8] block/qcow2-refcount: check_refcounts_l2: reduce ignored overlaps 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: kwolf@redhat.com, den@openvz.org, vsementsov@virtuozzo.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Reduce number of structures ignored in overlap check: when checking active table ignore active tables, when checking inactive table ignore inactive ones. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Max Reitz --- block/qcow2-refcount.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 23b105b43b..8fb9c9af39 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1569,7 +1569,7 @@ enum { static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, void **refcount_table, int64_t *refcount_table_size, int64_t l2_off= set, - int flags, BdrvCheckMode fix) + int flags, BdrvCheckMode fix, bool active) { BDRVQcow2State *s =3D bs->opaque; uint64_t *l2_table, l2_entry; @@ -1656,11 +1656,12 @@ static int check_refcounts_l2(BlockDriverState *bs,= BdrvCheckResult *res, if (fix & BDRV_FIX_ERRORS) { uint64_t l2e_offset =3D l2_offset + (uint64_t)i * sizeof(uint64_t); + int ign =3D active ? QCOW2_OL_ACTIVE_L2 : + QCOW2_OL_INACTIVE_L2; =20 l2_entry =3D QCOW_OFLAG_ZERO; l2_table[i] =3D cpu_to_be64(l2_entry); - ret =3D qcow2_pre_write_overlap_check(bs, - QCOW2_OL_ACTIVE_L2 | QCOW2_OL_INACTIVE_L2, + ret =3D qcow2_pre_write_overlap_check(bs, ign, l2e_offset, sizeof(uint64_t)); if (ret < 0) { fprintf(stderr, "ERROR: Overlap check failed\n= "); @@ -1734,7 +1735,7 @@ static int check_refcounts_l1(BlockDriverState *bs, void **refcount_table, int64_t *refcount_table_size, int64_t l1_table_offset, int l1_size, - int flags, BdrvCheckMode fix) + int flags, BdrvCheckMode fix, bool active) { BDRVQcow2State *s =3D bs->opaque; uint64_t *l1_table =3D NULL, l2_offset, l1_size2; @@ -1790,7 +1791,7 @@ static int check_refcounts_l1(BlockDriverState *bs, /* Process and check L2 entries */ ret =3D check_refcounts_l2(bs, res, refcount_table, refcount_table_size, l2_offset, flags, - fix); + fix, active); if (ret < 0) { goto fail; } @@ -2076,7 +2077,7 @@ static int calculate_refcounts(BlockDriverState *bs, = BdrvCheckResult *res, /* current L1 table */ ret =3D check_refcounts_l1(bs, res, refcount_table, nb_clusters, s->l1_table_offset, s->l1_size, CHECK_FRAG_IN= FO, - fix); + fix, true); if (ret < 0) { return ret; } @@ -2099,7 +2100,8 @@ static int calculate_refcounts(BlockDriverState *bs, = BdrvCheckResult *res, continue; } ret =3D check_refcounts_l1(bs, res, refcount_table, nb_clusters, - sn->l1_table_offset, sn->l1_size, 0, fix); + sn->l1_table_offset, sn->l1_size, 0, fix, + false); if (ret < 0) { return ret; } --=20 2.18.0 From nobody Sat May 18 08:35:39 2024 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; 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; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1539271131262647.3961982662446; Thu, 11 Oct 2018 08:18:51 -0700 (PDT) Received: from localhost ([::1]:35060 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAcji-0007xJ-1D for importer@patchew.org; Thu, 11 Oct 2018 11:18:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59607) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAchX-0006ah-VF for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gAchU-0006hM-Ox for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:35 -0400 Received: from relay.sw.ru ([185.231.240.75]:35534) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gAchU-0006em-EA; Thu, 11 Oct 2018 11:16:32 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gAchQ-0002Z5-13; Thu, 11 Oct 2018 18:16:28 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 11 Oct 2018 18:16:20 +0300 Message-Id: <20181011151623.25702-6-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181011151623.25702-1-vsementsov@virtuozzo.com> References: <20181011151623.25702-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v3 5/8] block/qcow2-refcount: check_refcounts_l2: don't count corrupted entries 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: kwolf@redhat.com, den@openvz.org, vsementsov@virtuozzo.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Misaligned entries will lead to fatal qcow2 driver corruption on read or write to corresponding offset, so there is no sense to take them into account. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/qcow2-refcount.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 8fb9c9af39..3b34681f16 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1634,15 +1634,6 @@ static int check_refcounts_l2(BlockDriverState *bs, = BdrvCheckResult *res, { uint64_t offset =3D l2_entry & L2E_OFFSET_MASK; =20 - if (flags & CHECK_FRAG_INFO) { - res->bfi.allocated_clusters++; - if (next_contiguous_offset && - offset !=3D next_contiguous_offset) { - res->bfi.fragmented_clusters++; - } - next_contiguous_offset =3D offset + s->cluster_size; - } - /* Correct offsets are cluster aligned */ if (offset_into_cluster(s, offset)) { if (qcow2_get_cluster_type(l2_entry) =3D=3D @@ -1681,9 +1672,6 @@ static int check_refcounts_l2(BlockDriverState *bs, B= drvCheckResult *res, * L2 table's entries */ } else { res->corruptions_fixed++; - /* Skip marking the cluster as used - * (it is unused now) */ - continue; } } else { res->corruptions++; @@ -1693,6 +1681,19 @@ static int check_refcounts_l2(BlockDriverState *bs, = BdrvCheckResult *res, "not properly aligned; L2 entry corrupted.\n", off= set); res->corruptions++; } + + /* Skip marking the cluster as used + * (l2 entry is marked as zero or still fatally corrupted)= */ + continue; + } + + if (flags & CHECK_FRAG_INFO) { + res->bfi.allocated_clusters++; + if (next_contiguous_offset && + offset !=3D next_contiguous_offset) { + res->bfi.fragmented_clusters++; + } + next_contiguous_offset =3D offset + s->cluster_size; } =20 /* Mark cluster as used */ --=20 2.18.0 From nobody Sat May 18 08:35:39 2024 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; 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; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 15392713024921007.0026086853111; Thu, 11 Oct 2018 08:21:42 -0700 (PDT) Received: from localhost ([::1]:35080 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAcmO-0001hn-5N for importer@patchew.org; Thu, 11 Oct 2018 11:21:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59615) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAchX-0006am-Vn for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gAchU-0006hF-Lv for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:35 -0400 Received: from relay.sw.ru ([185.231.240.75]:35536) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gAchU-0006fi-9d; Thu, 11 Oct 2018 11:16:32 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gAchQ-0002Z5-Hj; Thu, 11 Oct 2018 18:16:28 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 11 Oct 2018 18:16:21 +0300 Message-Id: <20181011151623.25702-7-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181011151623.25702-1-vsementsov@virtuozzo.com> References: <20181011151623.25702-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v3 6/8] block/qcow2-refcount: refactor fixing L2 entry 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: kwolf@redhat.com, den@openvz.org, vsementsov@virtuozzo.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Split entry repairing to separate function, to be reused later in check_refcounts_l2, prepare the whole pipeline for adding more corruption types which may be repaired. Note: entry in in-memory l2 table (local variable in check_refcounts_l2) is not updated after this patch. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/qcow2-refcount.c | 234 ++++++++++++++++++++++++++--------------- 1 file changed, 148 insertions(+), 86 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 3b34681f16..65e0fd2de3 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1558,6 +1558,63 @@ enum { CHECK_FRAG_INFO =3D 0x2, /* update BlockFragInfo counters */ }; =20 +typedef enum { + REP_ACTIVE_L1, + REP_INACTIVE_L1, + REP_ACTIVE_L2, + REP_INACTIVE_L2 +} RepTableType; + +/* repair_table_entry + * + * Rewrite entry in L1 or L2 table and set @res appropriately. + * + * Returns: -errno if overlap check failed + * 0 if write failed + * 1 on success + */ +static int repair_table_entry(BlockDriverState *bs, BdrvCheckResult *res, + RepTableType type, uint64_t table_offset, + int entry_index, uint64_t new_val) +{ + int ret; + uint64_t entry_offset =3D + table_offset + (uint64_t)entry_index * sizeof(new_val); + + static const struct { + const char *name; + int ign; + } types[] =3D { + [REP_ACTIVE_L1] =3D { "L1", QCOW2_OL_ACTIVE_L1 }, + [REP_INACTIVE_L1] =3D { "L1", QCOW2_OL_INACTIVE_L1 }, + [REP_ACTIVE_L2] =3D { "L2", QCOW2_OL_ACTIVE_L1 }, + [REP_INACTIVE_L2] =3D { "L2", QCOW2_OL_INACTIVE_L1 }, + }; + + cpu_to_be64s(&new_val); + ret =3D qcow2_pre_write_overlap_check(bs, types[type].ign, entry_offse= t, + sizeof(new_val)); + if (ret < 0) { + res->check_errors++; + fprintf(stderr, + "ERROR: Cannot write %s table entry: " + "overlap check failed: %s\n", + types[type].name, strerror(-ret)); + return ret; + } + + ret =3D bdrv_pwrite_sync(bs->file, entry_offset, &new_val, sizeof(new_= val)); + if (ret < 0) { + res->check_errors++; + fprintf(stderr, "ERROR: Failed to overwrite %s table entry: %s\n", + types[type].name, strerror(-ret)); + return 0; + } + + res->corruptions_fixed++; + return 1; +} + /* * Increases the refcount in the given refcount table for the all clusters * referenced in the L2 table. While doing so, performs some checks on L2 @@ -1572,9 +1629,11 @@ static int check_refcounts_l2(BlockDriverState *bs, = BdrvCheckResult *res, int flags, BdrvCheckMode fix, bool active) { BDRVQcow2State *s =3D bs->opaque; - uint64_t *l2_table, l2_entry; + uint64_t *l2_table; uint64_t next_contiguous_offset =3D 0; int i, l2_size, ret; + bool fix_er =3D fix & BDRV_FIX_ERRORS; + RepTableType type =3D active ? REP_ACTIVE_L2 : REP_INACTIVE_L2; =20 /* Read L2 table from disk */ l2_size =3D s->l2_size * sizeof(uint64_t); @@ -1589,13 +1648,17 @@ static int check_refcounts_l2(BlockDriverState *bs,= BdrvCheckResult *res, =20 /* Do the actual checks */ for(i =3D 0; i < s->l2_size; i++) { - l2_entry =3D be64_to_cpu(l2_table[i]); - - switch (qcow2_get_cluster_type(l2_entry)) { + uint64_t l2_entry =3D be64_to_cpu(l2_table[i]); + uint64_t l2_entry_fix =3D l2_entry; + QCow2ClusterType entry_type =3D qcow2_get_cluster_type(l2_entry); + int64_t offset, size; + bool fatal =3D false; /* l2_entry is fatally corrupted, don't coun= t it if + fail to fix */ + + /* check for errors: either increase res->corruptions or set + * @l2_entry_fix to something other */ + switch (entry_type) { case QCOW2_CLUSTER_COMPRESSED: - { - int64_t csize, coffset; - /* Compressed clusters don't have QCOW_OFLAG_COPIED */ if (l2_entry & QCOW_OFLAG_COPIED) { fprintf(stderr, "ERROR: coffset=3D0x%" PRIx64 ": " @@ -1605,113 +1668,112 @@ static int check_refcounts_l2(BlockDriverState *b= s, BdrvCheckResult *res, res->corruptions++; } =20 - /* Mark cluster as used */ - csize =3D (((l2_entry >> s->csize_shift) & s->csize_mask) + 1)= * 512; - coffset =3D l2_entry & s->cluster_offset_mask & ~511; - ret =3D qcow2_inc_refcounts_imrt(bs, res, - refcount_table, refcount_table_= size, - coffset, csize); - if (ret < 0) { - goto fail; - } - - if (flags & CHECK_FRAG_INFO) { - res->bfi.allocated_clusters++; - res->bfi.compressed_clusters++; - - /* Compressed clusters are fragmented by nature. Since th= ey - * take up sub-sector space but we only have sector granul= arity - * I/O we need to re-read the same sectors even for adjace= nt - * compressed clusters. - */ - res->bfi.fragmented_clusters++; - } + offset =3D l2_entry & s->cluster_offset_mask & ~511; + size =3D (((l2_entry >> s->csize_shift) & s->csize_mask) + 1) = * 512; break; - } =20 case QCOW2_CLUSTER_ZERO_ALLOC: case QCOW2_CLUSTER_NORMAL: - { - uint64_t offset =3D l2_entry & L2E_OFFSET_MASK; + offset =3D l2_entry & L2E_OFFSET_MASK; + size =3D s->cluster_size; =20 /* Correct offsets are cluster aligned */ if (offset_into_cluster(s, offset)) { + fatal =3D true; /* misaligned cluster leads to + * qcow2_signal_corruption(fatal =3D true) + */ if (qcow2_get_cluster_type(l2_entry) =3D=3D QCOW2_CLUSTER_ZERO_ALLOC) { fprintf(stderr, "%s offset=3D%" PRIx64 ": Preallocated= zero " "cluster is not properly aligned; L2 entry " "corrupted.\n", - fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", - offset); - if (fix & BDRV_FIX_ERRORS) { - uint64_t l2e_offset =3D - l2_offset + (uint64_t)i * sizeof(uint64_t); - int ign =3D active ? QCOW2_OL_ACTIVE_L2 : - QCOW2_OL_INACTIVE_L2; - - l2_entry =3D QCOW_OFLAG_ZERO; - l2_table[i] =3D cpu_to_be64(l2_entry); - ret =3D qcow2_pre_write_overlap_check(bs, ign, - l2e_offset, sizeof(uint64_t)); - if (ret < 0) { - fprintf(stderr, "ERROR: Overlap check failed\n= "); - res->check_errors++; - /* Something is seriously wrong, so abort chec= king - * this L2 table */ - goto fail; - } - - ret =3D bdrv_pwrite_sync(bs->file, l2e_offset, - &l2_table[i], sizeof(uint64= _t)); - if (ret < 0) { - fprintf(stderr, "ERROR: Failed to overwrite L2= " - "table entry: %s\n", strerror(-ret)); - res->check_errors++; - /* Do not abort, continue checking the rest of= this - * L2 table's entries */ - } else { - res->corruptions_fixed++; - } - } else { - res->corruptions++; - } + fix_er ? "Repairing" : "ERROR", offset); + l2_entry_fix =3D QCOW_OFLAG_ZERO; } else { fprintf(stderr, "ERROR offset=3D%" PRIx64 ": Data clus= ter is " "not properly aligned; L2 entry corrupted.\n", off= set); res->corruptions++; } + } =20 - /* Skip marking the cluster as used - * (l2 entry is marked as zero or still fatally corrupted)= */ - continue; + break; + + case QCOW2_CLUSTER_ZERO_PLAIN: + case QCOW2_CLUSTER_UNALLOCATED: + /* No allocation to be counted */ + continue; + + default: + abort(); + } + + /* handle found errors */ + if (l2_entry_fix !=3D l2_entry) { + if (fix_er) { + ret =3D repair_table_entry(bs, res, type, + l2_offset, i, l2_entry_fix); + if (ret < 0) { + /* Something is seriously wrong, so abort checking + * this L2 table */ + goto fail; + } else if (ret =3D=3D 1) { + /* successfully fixed */ + l2_entry =3D l2_entry_fix; + entry_type =3D qcow2_get_cluster_type(l2_entry); + fatal =3D false; + } + } else { + res->corruptions++; } + } + if (fatal || entry_type =3D=3D QCOW2_CLUSTER_ZERO_PLAIN || + entry_type =3D=3D QCOW2_CLUSTER_ZERO_PLAIN) + { + /* entry is either: + * fatally corrupted, and we did not fix it, + * we can't count it like normal entry + * or: + * successfully fixed to be zero/unallocated, + * we should not count it. + */ + continue; + } + + ret =3D qcow2_inc_refcounts_imrt(bs, res, + refcount_table, refcount_table_size, + offset, size); + if (ret < 0) { + goto fail; + } + + /* update counters */ + if (flags & CHECK_FRAG_INFO) { + res->bfi.allocated_clusters++; + switch (entry_type) { + case QCOW2_CLUSTER_COMPRESSED: + res->bfi.compressed_clusters++; =20 - if (flags & CHECK_FRAG_INFO) { - res->bfi.allocated_clusters++; + /* Compressed clusters are fragmented by nature. Since th= ey + * take up sub-sector space but we only have sector granul= arity + * I/O we need to re-read the same sectors even for adjace= nt + * compressed clusters. + */ + res->bfi.fragmented_clusters++; + break; + + case QCOW2_CLUSTER_ZERO_ALLOC: + case QCOW2_CLUSTER_NORMAL: if (next_contiguous_offset && offset !=3D next_contiguous_offset) { res->bfi.fragmented_clusters++; } next_contiguous_offset =3D offset + s->cluster_size; - } + break; =20 - /* Mark cluster as used */ - ret =3D qcow2_inc_refcounts_imrt(bs, res, - refcount_table, refcount_table_= size, - offset, s->cluster_size); - if (ret < 0) { - goto fail; + default: + abort(); } - break; - } - - case QCOW2_CLUSTER_ZERO_PLAIN: - case QCOW2_CLUSTER_UNALLOCATED: - break; - - default: - abort(); } } =20 --=20 2.18.0 From nobody Sat May 18 08:35:39 2024 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; 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; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1539271129710601.0926912435431; Thu, 11 Oct 2018 08:18:49 -0700 (PDT) Received: from localhost ([::1]:35059 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAcjg-0007vN-5x for importer@patchew.org; Thu, 11 Oct 2018 11:18:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59613) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAchX-0006al-Vf for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gAchU-0006hf-VG for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:35 -0400 Received: from relay.sw.ru ([185.231.240.75]:35542) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gAchU-0006fm-Jp; Thu, 11 Oct 2018 11:16:32 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gAchR-0002Z5-PQ; Thu, 11 Oct 2018 18:16:30 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 11 Oct 2018 18:16:22 +0300 Message-Id: <20181011151623.25702-8-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181011151623.25702-1-vsementsov@virtuozzo.com> References: <20181011151623.25702-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v3 7/8] block/qcow2-refcount: fix out-of-file L1 entries to be zero 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: kwolf@redhat.com, den@openvz.org, vsementsov@virtuozzo.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Zero out corrupted L1 table entry, which reference L2 table out of underlying file. Zero L1 table entry means that "the L2 table and all clusters described by this L2 table are unallocated." Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/qcow2-refcount.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 65e0fd2de3..5ebe292fc1 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1803,6 +1803,13 @@ static int check_refcounts_l1(BlockDriverState *bs, BDRVQcow2State *s =3D bs->opaque; uint64_t *l1_table =3D NULL, l2_offset, l1_size2; int i, ret; + bool fix_er =3D fix & BDRV_FIX_ERRORS; + RepTableType type =3D active ? REP_ACTIVE_L1 : REP_INACTIVE_L1; + int64_t file_len =3D bdrv_getlength(bs->file->bs); + + if (file_len < 0) { + return file_len; + } =20 l1_size2 =3D l1_size * sizeof(uint64_t); =20 @@ -1837,6 +1844,25 @@ static int check_refcounts_l1(BlockDriverState *bs, if (l2_offset) { /* Mark L2 table as used */ l2_offset &=3D L1E_OFFSET_MASK; + if (l2_offset >=3D file_len) { + fprintf(stderr, + "%s: l2 table offset out of file: offset 0x%" PRIx= 64 + "\n", fix_er ? "Repairing" : "ERROR", l2_offset); + if (fix_er) { + ret =3D repair_table_entry(bs, res, type, + l1_table_offset, i, 0); + if (ret < 0) { + /* Something is seriously wrong, so abort checking + * this L1 table */ + goto fail; + } + } else { + res->corruptions++; + } + + continue; + } + ret =3D qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_= size, l2_offset, s->cluster_size); --=20 2.18.0 From nobody Sat May 18 08:35:39 2024 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; 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; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1539271414651899.0162104538198; Thu, 11 Oct 2018 08:23:34 -0700 (PDT) Received: from localhost ([::1]:35090 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAcoH-00033S-7q for importer@patchew.org; Thu, 11 Oct 2018 11:23:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59612) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gAchX-0006ak-Vb for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gAchV-0006il-Na for qemu-devel@nongnu.org; Thu, 11 Oct 2018 11:16:35 -0400 Received: from relay.sw.ru ([185.231.240.75]:35554) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gAchV-0006gn-C4; Thu, 11 Oct 2018 11:16:33 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gAchS-0002Z5-N7; Thu, 11 Oct 2018 18:16:31 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 11 Oct 2018 18:16:23 +0300 Message-Id: <20181011151623.25702-9-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181011151623.25702-1-vsementsov@virtuozzo.com> References: <20181011151623.25702-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v3 8/8] block/qcow2-refcount: fix out-of-file L2 entries 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: kwolf@redhat.com, den@openvz.org, vsementsov@virtuozzo.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Rewrite corrupted L2 table entry, which reference space out of underlying file. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/qcow2-refcount.c | 66 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 5ebe292fc1..2e2ba806ed 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1629,11 +1629,37 @@ static int check_refcounts_l2(BlockDriverState *bs,= BdrvCheckResult *res, int flags, BdrvCheckMode fix, bool active) { BDRVQcow2State *s =3D bs->opaque; - uint64_t *l2_table; + uint64_t *l2_table, zero_fix_entry; uint64_t next_contiguous_offset =3D 0; int i, l2_size, ret; bool fix_er =3D fix & BDRV_FIX_ERRORS; RepTableType type =3D active ? REP_ACTIVE_L2 : REP_INACTIVE_L2; + const char *zero_fix_desc =3D ""; + int64_t file_len =3D bdrv_getlength(bs->file->bs); + + if (file_len < 0) { + return file_len; + } + + if (fix_er) { + /* prepare options for fixing corrupted l2 entries to be marked as= zero + * or unallocated + */ + if (s->qcow_version >=3D 3) { + zero_fix_entry =3D QCOW_OFLAG_ZERO; + zero_fix_desc =3D ": mark cluster as zero"; + } else { + /* v2 doesn't support ZERO flag, so we just mark it unallocate= d. + * It's a bit unsafe, as backing file may become available thr= ough + * the hole. However, discard for v2 do the same, so we don't = care + * too. + */ + zero_fix_entry =3D 0; + zero_fix_desc =3D ": mark cluster as unallocated (warning: " + "underlying backing file may become available " + "through the hole)"; + } + } =20 /* Read L2 table from disk */ l2_size =3D s->l2_size * sizeof(uint64_t); @@ -1670,6 +1696,34 @@ static int check_refcounts_l2(BlockDriverState *bs, = BdrvCheckResult *res, =20 offset =3D l2_entry & s->cluster_offset_mask & ~511; size =3D (((l2_entry >> s->csize_shift) & s->csize_mask) + 1) = * 512; + + if (offset + size > QEMU_ALIGN_UP(file_len, 512)) { + /* The compressed data does not necessarily occupy + * all of the bytes in the final 512-bytes sector + */ + const char *fix_desc =3D ""; + uint64_t orig_size =3D size; + fatal =3D true; + + if (fix_er) { + if (offset < file_len) { + size =3D QEMU_ALIGN_UP(file_len, 512) - offset; + l2_entry_fix &=3D + ~((uint64_t)s->csize_mask << s->csize_shif= t); + l2_entry_fix |=3D (size / 512 - 1) << s->csize_shi= ft; + fix_desc =3D ": try to fix cluster size"; + } else { + l2_entry_fix =3D zero_fix_entry; + fix_desc =3D zero_fix_desc; + } + } else { + res->corruptions++; + } + fprintf(stderr, "%s: compressed cluster out of file: " + "offset 0x%" PRIx64 " size 0x%" PRIx64 "%s\n", + fix_er ? "Repairing" : "ERROR", + offset, orig_size, fix_desc); + } break; =20 case QCOW2_CLUSTER_ZERO_ALLOC: @@ -1677,6 +1731,16 @@ static int check_refcounts_l2(BlockDriverState *bs, = BdrvCheckResult *res, offset =3D l2_entry & L2E_OFFSET_MASK; size =3D s->cluster_size; =20 + if (offset >=3D file_len) { + fatal =3D true; /* for sure, there is no allocation after = EOF */ + fprintf(stderr, + "%s: cluster out of file: offset 0x%" PRIx64 "%s\n= ", + fix_er ? "Repairing" : "ERROR", offset, + fix_er ? zero_fix_desc : ""); + l2_entry_fix =3D zero_fix_entry; + break; + } + /* Correct offsets are cluster aligned */ if (offset_into_cluster(s, offset)) { fatal =3D true; /* misaligned cluster leads to --=20 2.18.0