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