|
|
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 |
|