render / rpms / libvirt

Forked from rpms/libvirt 7 months ago
Clone
3e5111
From 15eb05f245e919ce5674ba4dbf41173eee13d3e4 Mon Sep 17 00:00:00 2001
3e5111
Message-Id: <15eb05f245e919ce5674ba4dbf41173eee13d3e4@dist-git>
3e5111
From: John Ferlan <jferlan@redhat.com>
3e5111
Date: Mon, 3 Apr 2017 16:45:08 -0400
3e5111
Subject: [PATCH] storage: Fix capacity value for LUKS encrypted volumes
3e5111
3e5111
https://bugzilla.redhat.com/show_bug.cgi?id=1371892
3e5111
3e5111
The 'capacity' value (e.g. guest logical size) for a LUKS volume is
3e5111
smaller than the 'physical' value of the file in the file system, so
3e5111
we need to account for that.
3e5111
3e5111
When peeking at the encryption information about the volume add a fetch
3e5111
of the payload_offset which is described as the offset to the start of
3e5111
the volume data (in 512 byte sectors) in QEMU's QCryptoBlockLUKSHeader.
3e5111
3e5111
Then adjust the ->capacity appropriately when we determine that the
3e5111
volume target encryption has a payload_offset value.
3e5111
3e5111
(cherry picked from commit b7d44f450c06803df7df3ad380f7a5c97425c1e6)
3e5111
Signed-off-by: John Ferlan <jferlan@redhat.com>
3e5111
---
3e5111
 src/storage/storage_util.c      |  3 +++
3e5111
 src/util/virstorageencryption.h |  1 +
3e5111
 src/util/virstoragefile.c       | 39 +++++++++++++++++++++++++++++++++++++++
3e5111
 3 files changed, 43 insertions(+)
3e5111
3e5111
diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
3e5111
index 7687eb89a..0ceaab6b9 100644
3e5111
--- a/src/storage/storage_util.c
3e5111
+++ b/src/storage/storage_util.c
3e5111
@@ -3436,6 +3436,9 @@ storageBackendProbeTarget(virStorageSourcePtr target,
3e5111
         target->capacity = meta->capacity;
3e5111
 
3e5111
     if (encryption && meta->encryption) {
3e5111
+        if (meta->encryption->payload_offset != -1)
3e5111
+            target->capacity -= meta->encryption->payload_offset * 512;
3e5111
+
3e5111
         *encryption = meta->encryption;
3e5111
         meta->encryption = NULL;
3e5111
 
3e5111
diff --git a/src/util/virstorageencryption.h b/src/util/virstorageencryption.h
3e5111
index fa439fb72..42f990c49 100644
3e5111
--- a/src/util/virstorageencryption.h
3e5111
+++ b/src/util/virstorageencryption.h
3e5111
@@ -70,6 +70,7 @@ typedef struct _virStorageEncryption virStorageEncryption;
3e5111
 typedef virStorageEncryption *virStorageEncryptionPtr;
3e5111
 struct _virStorageEncryption {
3e5111
     int format; /* virStorageEncryptionFormatType */
3e5111
+    int payload_offset;
3e5111
 
3e5111
     size_t nsecrets;
3e5111
     virStorageEncryptionSecretPtr *secrets;
3e5111
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
3e5111
index 22cdb83e4..a51622aff 100644
3e5111
--- a/src/util/virstoragefile.c
3e5111
+++ b/src/util/virstoragefile.c
3e5111
@@ -133,6 +133,8 @@ struct FileEncryptionInfo {
3e5111
 
3e5111
     int modeOffset; /* Byte offset of the format native encryption mode */
3e5111
     char modeValue; /* Value expected at offset */
3e5111
+
3e5111
+    int payloadOffset; /* start offset of the volume data (in 512 byte sectors) */
3e5111
 };
3e5111
 
3e5111
 /* Either 'magic' or 'extension' *must* be provided */
3e5111
@@ -212,9 +214,18 @@ qedGetBackingStore(char **, int *, const char *, size_t);
3e5111
 
3e5111
 #define LUKS_HDR_MAGIC_LEN 6
3e5111
 #define LUKS_HDR_VERSION_LEN 2
3e5111
+#define LUKS_HDR_CIPHER_NAME_LEN 32
3e5111
+#define LUKS_HDR_CIPHER_MODE_LEN 32
3e5111
+#define LUKS_HDR_HASH_SPEC_LEN 32
3e5111
+#define LUKS_HDR_PAYLOAD_LEN 4
3e5111
 
3e5111
 /* Format described by qemu commit id '3e308f20e' */
3e5111
 #define LUKS_HDR_VERSION_OFFSET LUKS_HDR_MAGIC_LEN
3e5111
+#define LUKS_HDR_PAYLOAD_OFFSET (LUKS_HDR_MAGIC_LEN+\
3e5111
+                                 LUKS_HDR_VERSION_LEN+\
3e5111
+                                 LUKS_HDR_CIPHER_NAME_LEN+\
3e5111
+                                 LUKS_HDR_CIPHER_MODE_LEN+\
3e5111
+                                 LUKS_HDR_HASH_SPEC_LEN)
3e5111
 
3e5111
 static struct FileEncryptionInfo const luksEncryptionInfo[] = {
3e5111
     {
3e5111
@@ -231,6 +242,8 @@ static struct FileEncryptionInfo const luksEncryptionInfo[] = {
3e5111
 
3e5111
         .modeOffset = -1,
3e5111
         .modeValue = -1,
3e5111
+
3e5111
+        .payloadOffset = LUKS_HDR_PAYLOAD_OFFSET,
3e5111
     },
3e5111
     { 0 }
3e5111
 };
3e5111
@@ -249,6 +262,8 @@ static struct FileEncryptionInfo const qcow1EncryptionInfo[] = {
3e5111
 
3e5111
         .modeOffset = QCOW1_HDR_CRYPT,
3e5111
         .modeValue = 1,
3e5111
+
3e5111
+        .payloadOffset = -1,
3e5111
     },
3e5111
     { 0 }
3e5111
 };
3e5111
@@ -267,6 +282,8 @@ static struct FileEncryptionInfo const qcow2EncryptionInfo[] = {
3e5111
 
3e5111
         .modeOffset = QCOW2_HDR_CRYPT,
3e5111
         .modeValue = 1,
3e5111
+
3e5111
+        .payloadOffset = -1,
3e5111
     },
3e5111
     { 0 }
3e5111
 };
3e5111
@@ -921,6 +938,23 @@ virStorageFileHasEncryptionFormat(const struct FileEncryptionInfo *info,
3e5111
 }
3e5111
 
3e5111
 
3e5111
+static int
3e5111
+virStorageFileGetEncryptionPayloadOffset(const struct FileEncryptionInfo *info,
3e5111
+                                         char *buf)
3e5111
+{
3e5111
+    int payload_offset = -1;
3e5111
+
3e5111
+    if (info->payloadOffset != -1) {
3e5111
+        if (info->endian == LV_LITTLE_ENDIAN)
3e5111
+            payload_offset = virReadBufInt32LE(buf + info->payloadOffset);
3e5111
+        else
3e5111
+            payload_offset = virReadBufInt32BE(buf + info->payloadOffset);
3e5111
+    }
3e5111
+
3e5111
+    return payload_offset;
3e5111
+}
3e5111
+
3e5111
+
3e5111
 /* Given a header in BUF with length LEN, as parsed from the storage file
3e5111
  * assuming it has the given FORMAT, populate information into META
3e5111
  * with information about the file and its backing store. Return format
3e5111
@@ -967,6 +1001,8 @@ virStorageFileGetMetadataInternal(virStorageSourcePtr meta,
3e5111
                         goto cleanup;
3e5111
                     }
3e5111
                 }
3e5111
+                meta->encryption->payload_offset =
3e5111
+                    virStorageFileGetEncryptionPayloadOffset(&fileTypeInfo[meta->format].cryptInfo[i], buf);
3e5111
             }
3e5111
         }
3e5111
     }
3e5111
@@ -3423,6 +3459,9 @@ virStorageSourceUpdateCapacity(virStorageSourcePtr src,
3e5111
     else
3e5111
         goto cleanup;
3e5111
 
3e5111
+    if (src->encryption && src->encryption->payload_offset != -1)
3e5111
+        src->capacity -= src->encryption->payload_offset * 512;
3e5111
+
3e5111
     ret = 0;
3e5111
 
3e5111
  cleanup:
3e5111
-- 
3e5111
2.12.2
3e5111