yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

Blame SOURCES/kvm-qcow2-add-overlap-check-for-bitmap-directory.patch

ae23c9
From e7b1acac8246a203ed0ed55a83cec29a4fa6252c Mon Sep 17 00:00:00 2001
ae23c9
From: John Snow <jsnow@redhat.com>
ae23c9
Date: Wed, 18 Jul 2018 22:54:45 +0200
ae23c9
Subject: [PATCH 227/268] qcow2: add overlap check for bitmap directory
ae23c9
ae23c9
RH-Author: John Snow <jsnow@redhat.com>
ae23c9
Message-id: <20180718225511.14878-10-jsnow@redhat.com>
ae23c9
Patchwork-id: 81394
ae23c9
O-Subject: [RHEL-7.6 qemu-kvm-rhev PATCH 09/35] qcow2: add overlap check for bitmap directory
ae23c9
Bugzilla: 1207657
ae23c9
RH-Acked-by: Eric Blake <eblake@redhat.com>
ae23c9
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ae23c9
RH-Acked-by: Fam Zheng <famz@redhat.com>
ae23c9
ae23c9
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
ae23c9
ae23c9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
ae23c9
Message-id: 20180705151515.779173-1-vsementsov@virtuozzo.com
ae23c9
Signed-off-by: Max Reitz <mreitz@redhat.com>
ae23c9
(cherry picked from commit 0e4e4318eaa56c831001bdf617094807ec6d451c)
ae23c9
Signed-off-by: John Snow <jsnow@redhat.com>
ae23c9
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
ae23c9
---
ae23c9
 block/qcow2-bitmap.c   |  7 ++++++-
ae23c9
 block/qcow2-refcount.c | 10 ++++++++++
ae23c9
 block/qcow2.c          | 22 ++++++++++++++--------
ae23c9
 block/qcow2.h          | 45 ++++++++++++++++++++++++---------------------
ae23c9
 qapi/block-core.json   | 21 ++++++++++++---------
ae23c9
 5 files changed, 66 insertions(+), 39 deletions(-)
ae23c9
ae23c9
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
ae23c9
index 3e4e4e4..14050eb 100644
ae23c9
--- a/block/qcow2-bitmap.c
ae23c9
+++ b/block/qcow2-bitmap.c
ae23c9
@@ -775,7 +775,12 @@ static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
ae23c9
         }
ae23c9
     }
ae23c9
 
ae23c9
-    ret = qcow2_pre_write_overlap_check(bs, 0, dir_offset, dir_size);
ae23c9
+    /* Actually, even in in-place case ignoring QCOW2_OL_BITMAP_DIRECTORY is not
ae23c9
+     * necessary, because we drop QCOW2_AUTOCLEAR_BITMAPS when updating bitmap
ae23c9
+     * directory in-place (actually, turn-off the extension), which is checked
ae23c9
+     * in qcow2_check_metadata_overlap() */
ae23c9
+    ret = qcow2_pre_write_overlap_check(
ae23c9
+            bs, in_place ? QCOW2_OL_BITMAP_DIRECTORY : 0, dir_offset, dir_size);
ae23c9
     if (ret < 0) {
ae23c9
         goto fail;
ae23c9
     }
ae23c9
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
ae23c9
index 4e14c0a..1307069 100644
ae23c9
--- a/block/qcow2-refcount.c
ae23c9
+++ b/block/qcow2-refcount.c
ae23c9
@@ -2705,6 +2705,16 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
ae23c9
         }
ae23c9
     }
ae23c9
 
ae23c9
+    if ((chk & QCOW2_OL_BITMAP_DIRECTORY) &&
ae23c9
+        (s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS))
ae23c9
+    {
ae23c9
+        if (overlaps_with(s->bitmap_directory_offset,
ae23c9
+                          s->bitmap_directory_size))
ae23c9
+        {
ae23c9
+            return QCOW2_OL_BITMAP_DIRECTORY;
ae23c9
+        }
ae23c9
+    }
ae23c9
+
ae23c9
     return 0;
ae23c9
 }
ae23c9
 
ae23c9
diff --git a/block/qcow2.c b/block/qcow2.c
ae23c9
index 71fbfcd..c5341a4 100644
ae23c9
--- a/block/qcow2.c
ae23c9
+++ b/block/qcow2.c
ae23c9
@@ -676,6 +676,11 @@ static QemuOptsList qcow2_runtime_opts = {
ae23c9
             .help = "Check for unintended writes into an inactive L2 table",
ae23c9
         },
ae23c9
         {
ae23c9
+            .name = QCOW2_OPT_OVERLAP_BITMAP_DIRECTORY,
ae23c9
+            .type = QEMU_OPT_BOOL,
ae23c9
+            .help = "Check for unintended writes into the bitmap directory",
ae23c9
+        },
ae23c9
+        {
ae23c9
             .name = QCOW2_OPT_CACHE_SIZE,
ae23c9
             .type = QEMU_OPT_SIZE,
ae23c9
             .help = "Maximum combined metadata (L2 tables and refcount blocks) "
ae23c9
@@ -708,14 +713,15 @@ static QemuOptsList qcow2_runtime_opts = {
ae23c9
 };
ae23c9
 
ae23c9
 static const char *overlap_bool_option_names[QCOW2_OL_MAX_BITNR] = {
ae23c9
-    [QCOW2_OL_MAIN_HEADER_BITNR]    = QCOW2_OPT_OVERLAP_MAIN_HEADER,
ae23c9
-    [QCOW2_OL_ACTIVE_L1_BITNR]      = QCOW2_OPT_OVERLAP_ACTIVE_L1,
ae23c9
-    [QCOW2_OL_ACTIVE_L2_BITNR]      = QCOW2_OPT_OVERLAP_ACTIVE_L2,
ae23c9
-    [QCOW2_OL_REFCOUNT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_TABLE,
ae23c9
-    [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK,
ae23c9
-    [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE,
ae23c9
-    [QCOW2_OL_INACTIVE_L1_BITNR]    = QCOW2_OPT_OVERLAP_INACTIVE_L1,
ae23c9
-    [QCOW2_OL_INACTIVE_L2_BITNR]    = QCOW2_OPT_OVERLAP_INACTIVE_L2,
ae23c9
+    [QCOW2_OL_MAIN_HEADER_BITNR]      = QCOW2_OPT_OVERLAP_MAIN_HEADER,
ae23c9
+    [QCOW2_OL_ACTIVE_L1_BITNR]        = QCOW2_OPT_OVERLAP_ACTIVE_L1,
ae23c9
+    [QCOW2_OL_ACTIVE_L2_BITNR]        = QCOW2_OPT_OVERLAP_ACTIVE_L2,
ae23c9
+    [QCOW2_OL_REFCOUNT_TABLE_BITNR]   = QCOW2_OPT_OVERLAP_REFCOUNT_TABLE,
ae23c9
+    [QCOW2_OL_REFCOUNT_BLOCK_BITNR]   = QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK,
ae23c9
+    [QCOW2_OL_SNAPSHOT_TABLE_BITNR]   = QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE,
ae23c9
+    [QCOW2_OL_INACTIVE_L1_BITNR]      = QCOW2_OPT_OVERLAP_INACTIVE_L1,
ae23c9
+    [QCOW2_OL_INACTIVE_L2_BITNR]      = QCOW2_OPT_OVERLAP_INACTIVE_L2,
ae23c9
+    [QCOW2_OL_BITMAP_DIRECTORY_BITNR] = QCOW2_OPT_OVERLAP_BITMAP_DIRECTORY,
ae23c9
 };
ae23c9
 
ae23c9
 static void cache_clean_timer_cb(void *opaque)
ae23c9
diff --git a/block/qcow2.h b/block/qcow2.h
ae23c9
index b5e2aa3..d2c63e4 100644
ae23c9
--- a/block/qcow2.h
ae23c9
+++ b/block/qcow2.h
ae23c9
@@ -98,6 +98,7 @@
ae23c9
 #define QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE "overlap-check.snapshot-table"
ae23c9
 #define QCOW2_OPT_OVERLAP_INACTIVE_L1 "overlap-check.inactive-l1"
ae23c9
 #define QCOW2_OPT_OVERLAP_INACTIVE_L2 "overlap-check.inactive-l2"
ae23c9
+#define QCOW2_OPT_OVERLAP_BITMAP_DIRECTORY "overlap-check.bitmap-directory"
ae23c9
 #define QCOW2_OPT_CACHE_SIZE "cache-size"
ae23c9
 #define QCOW2_OPT_L2_CACHE_SIZE "l2-cache-size"
ae23c9
 #define QCOW2_OPT_L2_CACHE_ENTRY_SIZE "l2-cache-entry-size"
ae23c9
@@ -401,34 +402,36 @@ typedef enum QCow2ClusterType {
ae23c9
 } QCow2ClusterType;
ae23c9
 
ae23c9
 typedef enum QCow2MetadataOverlap {
ae23c9
-    QCOW2_OL_MAIN_HEADER_BITNR    = 0,
ae23c9
-    QCOW2_OL_ACTIVE_L1_BITNR      = 1,
ae23c9
-    QCOW2_OL_ACTIVE_L2_BITNR      = 2,
ae23c9
-    QCOW2_OL_REFCOUNT_TABLE_BITNR = 3,
ae23c9
-    QCOW2_OL_REFCOUNT_BLOCK_BITNR = 4,
ae23c9
-    QCOW2_OL_SNAPSHOT_TABLE_BITNR = 5,
ae23c9
-    QCOW2_OL_INACTIVE_L1_BITNR    = 6,
ae23c9
-    QCOW2_OL_INACTIVE_L2_BITNR    = 7,
ae23c9
-
ae23c9
-    QCOW2_OL_MAX_BITNR            = 8,
ae23c9
-
ae23c9
-    QCOW2_OL_NONE           = 0,
ae23c9
-    QCOW2_OL_MAIN_HEADER    = (1 << QCOW2_OL_MAIN_HEADER_BITNR),
ae23c9
-    QCOW2_OL_ACTIVE_L1      = (1 << QCOW2_OL_ACTIVE_L1_BITNR),
ae23c9
-    QCOW2_OL_ACTIVE_L2      = (1 << QCOW2_OL_ACTIVE_L2_BITNR),
ae23c9
-    QCOW2_OL_REFCOUNT_TABLE = (1 << QCOW2_OL_REFCOUNT_TABLE_BITNR),
ae23c9
-    QCOW2_OL_REFCOUNT_BLOCK = (1 << QCOW2_OL_REFCOUNT_BLOCK_BITNR),
ae23c9
-    QCOW2_OL_SNAPSHOT_TABLE = (1 << QCOW2_OL_SNAPSHOT_TABLE_BITNR),
ae23c9
-    QCOW2_OL_INACTIVE_L1    = (1 << QCOW2_OL_INACTIVE_L1_BITNR),
ae23c9
+    QCOW2_OL_MAIN_HEADER_BITNR      = 0,
ae23c9
+    QCOW2_OL_ACTIVE_L1_BITNR        = 1,
ae23c9
+    QCOW2_OL_ACTIVE_L2_BITNR        = 2,
ae23c9
+    QCOW2_OL_REFCOUNT_TABLE_BITNR   = 3,
ae23c9
+    QCOW2_OL_REFCOUNT_BLOCK_BITNR   = 4,
ae23c9
+    QCOW2_OL_SNAPSHOT_TABLE_BITNR   = 5,
ae23c9
+    QCOW2_OL_INACTIVE_L1_BITNR      = 6,
ae23c9
+    QCOW2_OL_INACTIVE_L2_BITNR      = 7,
ae23c9
+    QCOW2_OL_BITMAP_DIRECTORY_BITNR = 8,
ae23c9
+
ae23c9
+    QCOW2_OL_MAX_BITNR              = 9,
ae23c9
+
ae23c9
+    QCOW2_OL_NONE             = 0,
ae23c9
+    QCOW2_OL_MAIN_HEADER      = (1 << QCOW2_OL_MAIN_HEADER_BITNR),
ae23c9
+    QCOW2_OL_ACTIVE_L1        = (1 << QCOW2_OL_ACTIVE_L1_BITNR),
ae23c9
+    QCOW2_OL_ACTIVE_L2        = (1 << QCOW2_OL_ACTIVE_L2_BITNR),
ae23c9
+    QCOW2_OL_REFCOUNT_TABLE   = (1 << QCOW2_OL_REFCOUNT_TABLE_BITNR),
ae23c9
+    QCOW2_OL_REFCOUNT_BLOCK   = (1 << QCOW2_OL_REFCOUNT_BLOCK_BITNR),
ae23c9
+    QCOW2_OL_SNAPSHOT_TABLE   = (1 << QCOW2_OL_SNAPSHOT_TABLE_BITNR),
ae23c9
+    QCOW2_OL_INACTIVE_L1      = (1 << QCOW2_OL_INACTIVE_L1_BITNR),
ae23c9
     /* NOTE: Checking overlaps with inactive L2 tables will result in bdrv
ae23c9
      * reads. */
ae23c9
-    QCOW2_OL_INACTIVE_L2    = (1 << QCOW2_OL_INACTIVE_L2_BITNR),
ae23c9
+    QCOW2_OL_INACTIVE_L2      = (1 << QCOW2_OL_INACTIVE_L2_BITNR),
ae23c9
+    QCOW2_OL_BITMAP_DIRECTORY = (1 << QCOW2_OL_BITMAP_DIRECTORY_BITNR),
ae23c9
 } QCow2MetadataOverlap;
ae23c9
 
ae23c9
 /* Perform all overlap checks which can be done in constant time */
ae23c9
 #define QCOW2_OL_CONSTANT \
ae23c9
     (QCOW2_OL_MAIN_HEADER | QCOW2_OL_ACTIVE_L1 | QCOW2_OL_REFCOUNT_TABLE | \
ae23c9
-     QCOW2_OL_SNAPSHOT_TABLE)
ae23c9
+     QCOW2_OL_SNAPSHOT_TABLE | QCOW2_OL_BITMAP_DIRECTORY)
ae23c9
 
ae23c9
 /* Perform all overlap checks which don't require disk access */
ae23c9
 #define QCOW2_OL_CACHED \
ae23c9
diff --git a/qapi/block-core.json b/qapi/block-core.json
ae23c9
index 9a9cfa0..b2de7af 100644
ae23c9
--- a/qapi/block-core.json
ae23c9
+++ b/qapi/block-core.json
ae23c9
@@ -2666,18 +2666,21 @@
ae23c9
 # @template: Specifies a template mode which can be adjusted using the other
ae23c9
 #            flags, defaults to 'cached'
ae23c9
 #
ae23c9
+# @bitmap-directory: since 3.0
ae23c9
+#
ae23c9
 # Since: 2.9
ae23c9
 ##
ae23c9
 { 'struct': 'Qcow2OverlapCheckFlags',
ae23c9
-  'data': { '*template':       'Qcow2OverlapCheckMode',
ae23c9
-            '*main-header':    'bool',
ae23c9
-            '*active-l1':      'bool',
ae23c9
-            '*active-l2':      'bool',
ae23c9
-            '*refcount-table': 'bool',
ae23c9
-            '*refcount-block': 'bool',
ae23c9
-            '*snapshot-table': 'bool',
ae23c9
-            '*inactive-l1':    'bool',
ae23c9
-            '*inactive-l2':    'bool' } }
ae23c9
+  'data': { '*template':         'Qcow2OverlapCheckMode',
ae23c9
+            '*main-header':      'bool',
ae23c9
+            '*active-l1':        'bool',
ae23c9
+            '*active-l2':        'bool',
ae23c9
+            '*refcount-table':   'bool',
ae23c9
+            '*refcount-block':   'bool',
ae23c9
+            '*snapshot-table':   'bool',
ae23c9
+            '*inactive-l1':      'bool',
ae23c9
+            '*inactive-l2':      'bool',
ae23c9
+            '*bitmap-directory': 'bool' } }
ae23c9
 
ae23c9
 ##
ae23c9
 # @Qcow2OverlapChecks:
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9