mirror of https://gitee.com/openkylin/libvirt.git
Recognize encryption format of qcow volumes.
(The implementation is not very generic, but that can be very easily rectified if/when new encryption formats appear.) * src/storage_backend_fs.c: Probe for qcow/qcow2 encryption algorithm field
This commit is contained in:
parent
eda3af2488
commit
d288703d57
|
@ -26,6 +26,7 @@
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -81,6 +82,9 @@ struct FileTypeInfo {
|
||||||
/* Store a COW base image path (possibly relative),
|
/* Store a COW base image path (possibly relative),
|
||||||
* or NULL if there is no COW base image, to RES;
|
* or NULL if there is no COW base image, to RES;
|
||||||
* return BACKING_STORE_* */
|
* return BACKING_STORE_* */
|
||||||
|
int qcowCryptOffset; /* Byte offset from start of file
|
||||||
|
* where to find encryption mode,
|
||||||
|
* -1 if encryption is not used */
|
||||||
int (*getBackingStore)(virConnectPtr conn, char **res,
|
int (*getBackingStore)(virConnectPtr conn, char **res,
|
||||||
const unsigned char *buf, size_t buf_size);
|
const unsigned char *buf, size_t buf_size);
|
||||||
};
|
};
|
||||||
|
@ -89,54 +93,54 @@ struct FileTypeInfo const fileTypeInfo[] = {
|
||||||
/* XXX Untested
|
/* XXX Untested
|
||||||
{ VIR_STORAGE_VOL_FILE_BOCHS, "Bochs Virtual HD Image", NULL,
|
{ VIR_STORAGE_VOL_FILE_BOCHS, "Bochs Virtual HD Image", NULL,
|
||||||
LV_LITTLE_ENDIAN, 64, 0x20000,
|
LV_LITTLE_ENDIAN, 64, 0x20000,
|
||||||
32+16+16+4+4+4+4+4, 8, 1, NULL },*/
|
32+16+16+4+4+4+4+4, 8, 1, -1, NULL },*/
|
||||||
/* CLoop */
|
/* CLoop */
|
||||||
/* XXX Untested
|
/* XXX Untested
|
||||||
{ VIR_STORAGE_VOL_CLOOP, "#!/bin/sh\n#V2.0 Format\nmodprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n", NULL,
|
{ VIR_STORAGE_VOL_CLOOP, "#!/bin/sh\n#V2.0 Format\nmodprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n", NULL,
|
||||||
LV_LITTLE_ENDIAN, -1, 0,
|
LV_LITTLE_ENDIAN, -1, 0,
|
||||||
-1, 0, 0, NULL }, */
|
-1, 0, 0, -1, NULL }, */
|
||||||
/* Cow */
|
/* Cow */
|
||||||
{ VIR_STORAGE_VOL_FILE_COW, "OOOM", NULL,
|
{ VIR_STORAGE_VOL_FILE_COW, "OOOM", NULL,
|
||||||
LV_BIG_ENDIAN, 4, 2,
|
LV_BIG_ENDIAN, 4, 2,
|
||||||
4+4+1024+4, 8, 1, cowGetBackingStore },
|
4+4+1024+4, 8, 1, -1, cowGetBackingStore },
|
||||||
/* DMG */
|
/* DMG */
|
||||||
/* XXX QEMU says there's no magic for dmg, but we should check... */
|
/* XXX QEMU says there's no magic for dmg, but we should check... */
|
||||||
{ VIR_STORAGE_VOL_FILE_DMG, NULL, ".dmg",
|
{ VIR_STORAGE_VOL_FILE_DMG, NULL, ".dmg",
|
||||||
0, -1, 0,
|
0, -1, 0,
|
||||||
-1, 0, 0, NULL },
|
-1, 0, 0, -1, NULL },
|
||||||
/* XXX there's probably some magic for iso we can validate too... */
|
/* XXX there's probably some magic for iso we can validate too... */
|
||||||
{ VIR_STORAGE_VOL_FILE_ISO, NULL, ".iso",
|
{ VIR_STORAGE_VOL_FILE_ISO, NULL, ".iso",
|
||||||
0, -1, 0,
|
0, -1, 0,
|
||||||
-1, 0, 0, NULL },
|
-1, 0, 0, -1, NULL },
|
||||||
/* Parallels */
|
/* Parallels */
|
||||||
/* XXX Untested
|
/* XXX Untested
|
||||||
{ VIR_STORAGE_VOL_FILE_PARALLELS, "WithoutFreeSpace", NULL,
|
{ VIR_STORAGE_VOL_FILE_PARALLELS, "WithoutFreeSpace", NULL,
|
||||||
LV_LITTLE_ENDIAN, 16, 2,
|
LV_LITTLE_ENDIAN, 16, 2,
|
||||||
16+4+4+4+4, 4, 512, NULL },
|
16+4+4+4+4, 4, 512, -1, NULL },
|
||||||
*/
|
*/
|
||||||
/* QCow */
|
/* QCow */
|
||||||
{ VIR_STORAGE_VOL_FILE_QCOW, "QFI", NULL,
|
{ VIR_STORAGE_VOL_FILE_QCOW, "QFI", NULL,
|
||||||
LV_BIG_ENDIAN, 4, 1,
|
LV_BIG_ENDIAN, 4, 1,
|
||||||
4+4+8+4+4, 8, 1, qcowXGetBackingStore },
|
4+4+8+4+4, 8, 1, 4+4+8+4+4+8+1+1+2, qcowXGetBackingStore },
|
||||||
/* QCow 2 */
|
/* QCow 2 */
|
||||||
{ VIR_STORAGE_VOL_FILE_QCOW2, "QFI", NULL,
|
{ VIR_STORAGE_VOL_FILE_QCOW2, "QFI", NULL,
|
||||||
LV_BIG_ENDIAN, 4, 2,
|
LV_BIG_ENDIAN, 4, 2,
|
||||||
4+4+8+4+4, 8, 1, qcowXGetBackingStore },
|
4+4+8+4+4, 8, 1, 4+4+8+4+4+8, qcowXGetBackingStore },
|
||||||
/* VMDK 3 */
|
/* VMDK 3 */
|
||||||
/* XXX Untested
|
/* XXX Untested
|
||||||
{ VIR_STORAGE_VOL_FILE_VMDK, "COWD", NULL,
|
{ VIR_STORAGE_VOL_FILE_VMDK, "COWD", NULL,
|
||||||
LV_LITTLE_ENDIAN, 4, 1,
|
LV_LITTLE_ENDIAN, 4, 1,
|
||||||
4+4+4, 4, 512, NULL },
|
4+4+4, 4, 512, -1, NULL },
|
||||||
*/
|
*/
|
||||||
/* VMDK 4 */
|
/* VMDK 4 */
|
||||||
{ VIR_STORAGE_VOL_FILE_VMDK, "KDMV", NULL,
|
{ VIR_STORAGE_VOL_FILE_VMDK, "KDMV", NULL,
|
||||||
LV_LITTLE_ENDIAN, 4, 1,
|
LV_LITTLE_ENDIAN, 4, 1,
|
||||||
4+4+4, 8, 512, vmdk4GetBackingStore },
|
4+4+4, 8, 512, -1, vmdk4GetBackingStore },
|
||||||
/* Connectix / VirtualPC */
|
/* Connectix / VirtualPC */
|
||||||
/* XXX Untested
|
/* XXX Untested
|
||||||
{ VIR_STORAGE_VOL_FILE_VPC, "conectix", NULL,
|
{ VIR_STORAGE_VOL_FILE_VPC, "conectix", NULL,
|
||||||
LV_BIG_ENDIAN, -1, 0,
|
LV_BIG_ENDIAN, -1, 0,
|
||||||
-1, 0, 0, NULL},
|
-1, 0, 0, -1, NULL},
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -282,13 +286,16 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
|
||||||
virStorageVolTargetPtr target,
|
virStorageVolTargetPtr target,
|
||||||
char **backingStore,
|
char **backingStore,
|
||||||
unsigned long long *allocation,
|
unsigned long long *allocation,
|
||||||
unsigned long long *capacity) {
|
unsigned long long *capacity,
|
||||||
|
virStorageEncryptionPtr *encryption) {
|
||||||
int fd;
|
int fd;
|
||||||
unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
|
unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
|
||||||
int len, i, ret;
|
int len, i, ret;
|
||||||
|
|
||||||
if (backingStore)
|
if (backingStore)
|
||||||
*backingStore = NULL;
|
*backingStore = NULL;
|
||||||
|
if (encryption)
|
||||||
|
*encryption = NULL;
|
||||||
|
|
||||||
if ((fd = open(target->path, O_RDONLY)) < 0) {
|
if ((fd = open(target->path, O_RDONLY)) < 0) {
|
||||||
virReportSystemError(conn, errno,
|
virReportSystemError(conn, errno,
|
||||||
|
@ -317,6 +324,8 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
|
||||||
/* First check file magic */
|
/* First check file magic */
|
||||||
for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
|
for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
|
||||||
int mlen;
|
int mlen;
|
||||||
|
bool encrypted_qcow = false;
|
||||||
|
|
||||||
if (fileTypeInfo[i].magic == NULL)
|
if (fileTypeInfo[i].magic == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -375,6 +384,16 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
|
||||||
*capacity *= fileTypeInfo[i].sizeMultiplier;
|
*capacity *= fileTypeInfo[i].sizeMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fileTypeInfo[i].qcowCryptOffset != -1) {
|
||||||
|
int crypt_format;
|
||||||
|
|
||||||
|
crypt_format = (head[fileTypeInfo[i].qcowCryptOffset] << 24) |
|
||||||
|
(head[fileTypeInfo[i].qcowCryptOffset+1] << 16) |
|
||||||
|
(head[fileTypeInfo[i].qcowCryptOffset+2] << 8) |
|
||||||
|
head[fileTypeInfo[i].qcowCryptOffset+3];
|
||||||
|
encrypted_qcow = crypt_format != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Validation passed, we know the file format now */
|
/* Validation passed, we know the file format now */
|
||||||
target->format = fileTypeInfo[i].type;
|
target->format = fileTypeInfo[i].type;
|
||||||
if (fileTypeInfo[i].getBackingStore != NULL && backingStore) {
|
if (fileTypeInfo[i].getBackingStore != NULL && backingStore) {
|
||||||
|
@ -400,6 +419,18 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (encryption != NULL && encrypted_qcow) {
|
||||||
|
virStorageEncryptionPtr enc;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(enc) < 0) {
|
||||||
|
virReportOOMError(conn);
|
||||||
|
if (backingStore)
|
||||||
|
VIR_FREE(*backingStore);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
enc->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
|
||||||
|
*encryption = enc;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,7 +899,8 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn,
|
||||||
&vol->target,
|
&vol->target,
|
||||||
&backingStore,
|
&backingStore,
|
||||||
&vol->allocation,
|
&vol->allocation,
|
||||||
&vol->capacity) < 0)) {
|
&vol->capacity,
|
||||||
|
&vol->target.encryption) < 0)) {
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
else {
|
else {
|
||||||
|
@ -908,7 +940,8 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn,
|
||||||
|
|
||||||
if ((ret = virStorageBackendProbeTarget(conn,
|
if ((ret = virStorageBackendProbeTarget(conn,
|
||||||
&vol->backingStore,
|
&vol->backingStore,
|
||||||
NULL, NULL, NULL)) < 0) {
|
NULL, NULL, NULL,
|
||||||
|
NULL)) < 0) {
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Reference in New Issue