update to libvirt 0.8.3
OBS-URL: https://build.opensuse.org/package/show/Virtualization/libvirt?expand=0&rev=61
This commit is contained in:
parent
274bce922a
commit
8b4217ed93
@ -1,339 +0,0 @@
|
|||||||
>From 7b91c43bef0348c8cc18037bec5aef668b51fc90 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Mon, 14 Jun 2010 15:53:59 +0100
|
|
||||||
Subject: [PATCH 01/10] Extract the backing store format as well as name, if available
|
|
||||||
|
|
||||||
When QEMU opens a backing store for a QCow2 file, it will
|
|
||||||
normally auto-probe for the format of the backing store,
|
|
||||||
rather than assuming it has the same format as the referencing
|
|
||||||
file. There is a QCow2 extension that allows an explicit format
|
|
||||||
for the backing store to be embedded in the referencing file.
|
|
||||||
This closes the auto-probing security hole in QEMU.
|
|
||||||
|
|
||||||
This backing store format can be useful for libvirt users
|
|
||||||
of virStorageFileGetMetadata, so extract this data and report
|
|
||||||
it.
|
|
||||||
|
|
||||||
QEMU does not require disk image backing store files to be in
|
|
||||||
the same format the file linkee. It will auto-probe the disk
|
|
||||||
format for the backing store when opening it. If the backing
|
|
||||||
store was intended to be a raw file this could be a security
|
|
||||||
hole, because a guest may have written data into its disk that
|
|
||||||
then makes the backing store look like a qcow2 file. If it can
|
|
||||||
trick QEMU into thinking the raw file is a qcow2 file, it can
|
|
||||||
access arbitrary files on the host by adding further backing
|
|
||||||
store links.
|
|
||||||
|
|
||||||
To address this, callers of virStorageFileGetMeta need to be
|
|
||||||
told of the backing store format. If no format is declared,
|
|
||||||
they can make a decision whether to allow format probing or
|
|
||||||
not.
|
|
||||||
---
|
|
||||||
src/util/storage_file.c | 192 ++++++++++++++++++++++++++++++++++++++++------
|
|
||||||
src/util/storage_file.h | 2 +
|
|
||||||
2 files changed, 169 insertions(+), 25 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/util/storage_file.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/storage_file.c
|
|
||||||
+++ libvirt-0.8.1/src/util/storage_file.c
|
|
||||||
@@ -71,12 +71,18 @@ struct FileTypeInfo {
|
|
||||||
int qcowCryptOffset; /* Byte offset from start of file
|
|
||||||
* where to find encryption mode,
|
|
||||||
* -1 if encryption is not used */
|
|
||||||
- int (*getBackingStore)(char **res, const unsigned char *buf, size_t buf_size);
|
|
||||||
+ int (*getBackingStore)(char **res, int *format,
|
|
||||||
+ const unsigned char *buf, size_t buf_size);
|
|
||||||
};
|
|
||||||
|
|
||||||
-static int cowGetBackingStore(char **, const unsigned char *, size_t);
|
|
||||||
-static int qcowXGetBackingStore(char **, const unsigned char *, size_t);
|
|
||||||
-static int vmdk4GetBackingStore(char **, const unsigned char *, size_t);
|
|
||||||
+static int cowGetBackingStore(char **, int *,
|
|
||||||
+ const unsigned char *, size_t);
|
|
||||||
+static int qcow1GetBackingStore(char **, int *,
|
|
||||||
+ const unsigned char *, size_t);
|
|
||||||
+static int qcow2GetBackingStore(char **, int *,
|
|
||||||
+ const unsigned char *, size_t);
|
|
||||||
+static int vmdk4GetBackingStore(char **, int *,
|
|
||||||
+ const unsigned char *, size_t);
|
|
||||||
|
|
||||||
|
|
||||||
static struct FileTypeInfo const fileTypeInfo[] = {
|
|
||||||
@@ -112,11 +118,11 @@ static struct FileTypeInfo const fileTyp
|
|
||||||
/* QCow */
|
|
||||||
{ VIR_STORAGE_FILE_QCOW, "QFI", NULL,
|
|
||||||
LV_BIG_ENDIAN, 4, 1,
|
|
||||||
- 4+4+8+4+4, 8, 1, 4+4+8+4+4+8+1+1+2, qcowXGetBackingStore },
|
|
||||||
+ 4+4+8+4+4, 8, 1, 4+4+8+4+4+8+1+1+2, qcow1GetBackingStore },
|
|
||||||
/* QCow 2 */
|
|
||||||
{ VIR_STORAGE_FILE_QCOW2, "QFI", NULL,
|
|
||||||
LV_BIG_ENDIAN, 4, 2,
|
|
||||||
- 4+4+8+4+4, 8, 1, 4+4+8+4+4+8, qcowXGetBackingStore },
|
|
||||||
+ 4+4+8+4+4, 8, 1, 4+4+8+4+4+8, qcow2GetBackingStore },
|
|
||||||
/* VMDK 3 */
|
|
||||||
/* XXX Untested
|
|
||||||
{ VIR_STORAGE_FILE_VMDK, "COWD", NULL,
|
|
||||||
@@ -137,11 +143,14 @@ static struct FileTypeInfo const fileTyp
|
|
||||||
|
|
||||||
static int
|
|
||||||
cowGetBackingStore(char **res,
|
|
||||||
+ int *format,
|
|
||||||
const unsigned char *buf,
|
|
||||||
size_t buf_size)
|
|
||||||
{
|
|
||||||
#define COW_FILENAME_MAXLEN 1024
|
|
||||||
*res = NULL;
|
|
||||||
+ *format = VIR_STORAGE_FILE_AUTO;
|
|
||||||
+
|
|
||||||
if (buf_size < 4+4+ COW_FILENAME_MAXLEN)
|
|
||||||
return BACKING_STORE_INVALID;
|
|
||||||
if (buf[4+4] == '\0') /* cow_header_v2.backing_file[0] */
|
|
||||||
@@ -155,31 +164,101 @@ cowGetBackingStore(char **res,
|
|
||||||
return BACKING_STORE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#define QCOWX_HDR_BACKING_FILE_OFFSET 4+4
|
|
||||||
+#define QCOWX_HDR_BACKING_FILE_SIZE 4+4+8
|
|
||||||
+
|
|
||||||
+#define QCOW2_HDR_TOTAL_SIZE 4+4+8+4+4+8+4+4+8+8+4+4+8
|
|
||||||
+#define QCOW2_HDR_EXTENSION_END 0
|
|
||||||
+#define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+qcow2GetBackingStoreFormat(int *format,
|
|
||||||
+ const unsigned char *buf,
|
|
||||||
+ size_t buf_size,
|
|
||||||
+ size_t extension_start,
|
|
||||||
+ size_t extension_end)
|
|
||||||
+{
|
|
||||||
+ size_t offset = extension_start;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * The extensions take format of
|
|
||||||
+ *
|
|
||||||
+ * int32: magic
|
|
||||||
+ * int32: length
|
|
||||||
+ * byte[length]: payload
|
|
||||||
+ *
|
|
||||||
+ * Unknown extensions can be ignored by skipping
|
|
||||||
+ * over "length" bytes in the data stream.
|
|
||||||
+ */
|
|
||||||
+ while (offset < (buf_size-8) &&
|
|
||||||
+ offset < (extension_end-8)) {
|
|
||||||
+ int magic = (buf[offset] << 24) +
|
|
||||||
+ (buf[offset+1] << 16) +
|
|
||||||
+ (buf[offset+2] << 8) +
|
|
||||||
+ (buf[offset+3]);
|
|
||||||
+ int len = (buf[offset+4] << 24) +
|
|
||||||
+ (buf[offset+5] << 16) +
|
|
||||||
+ (buf[offset+6] << 8) +
|
|
||||||
+ (buf[offset+7]);
|
|
||||||
+
|
|
||||||
+ offset += 8;
|
|
||||||
+
|
|
||||||
+ if ((offset + len) > buf_size)
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ switch (magic) {
|
|
||||||
+ case QCOW2_HDR_EXTENSION_END:
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ case QCOW2_HDR_EXTENSION_BACKING_FORMAT:
|
|
||||||
+ if (buf[offset+len] != '\0')
|
|
||||||
+ break;
|
|
||||||
+ *format = virStorageFileFormatTypeFromString(
|
|
||||||
+ ((const char *)buf)+offset);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ offset += len;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
static int
|
|
||||||
qcowXGetBackingStore(char **res,
|
|
||||||
+ int *format,
|
|
||||||
const unsigned char *buf,
|
|
||||||
- size_t buf_size)
|
|
||||||
+ size_t buf_size,
|
|
||||||
+ bool isQCow2)
|
|
||||||
{
|
|
||||||
unsigned long long offset;
|
|
||||||
unsigned long size;
|
|
||||||
|
|
||||||
*res = NULL;
|
|
||||||
- if (buf_size < 4+4+8+4)
|
|
||||||
+ if (format)
|
|
||||||
+ *format = VIR_STORAGE_FILE_AUTO;
|
|
||||||
+
|
|
||||||
+ if (buf_size < QCOWX_HDR_BACKING_FILE_OFFSET+8+4)
|
|
||||||
return BACKING_STORE_INVALID;
|
|
||||||
- offset = (((unsigned long long)buf[4+4] << 56)
|
|
||||||
- | ((unsigned long long)buf[4+4+1] << 48)
|
|
||||||
- | ((unsigned long long)buf[4+4+2] << 40)
|
|
||||||
- | ((unsigned long long)buf[4+4+3] << 32)
|
|
||||||
- | ((unsigned long long)buf[4+4+4] << 24)
|
|
||||||
- | ((unsigned long long)buf[4+4+5] << 16)
|
|
||||||
- | ((unsigned long long)buf[4+4+6] << 8)
|
|
||||||
- | buf[4+4+7]); /* QCowHeader.backing_file_offset */
|
|
||||||
+ offset = (((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET] << 56)
|
|
||||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+1] << 48)
|
|
||||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+2] << 40)
|
|
||||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+3] << 32)
|
|
||||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+4] << 24)
|
|
||||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+5] << 16)
|
|
||||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+6] << 8)
|
|
||||||
+ | buf[QCOWX_HDR_BACKING_FILE_OFFSET+7]); /* QCowHeader.backing_file_offset */
|
|
||||||
if (offset > buf_size)
|
|
||||||
return BACKING_STORE_INVALID;
|
|
||||||
- size = ((buf[4+4+8] << 24)
|
|
||||||
- | (buf[4+4+8+1] << 16)
|
|
||||||
- | (buf[4+4+8+2] << 8)
|
|
||||||
- | buf[4+4+8+3]); /* QCowHeader.backing_file_size */
|
|
||||||
+ size = ((buf[QCOWX_HDR_BACKING_FILE_SIZE] << 24)
|
|
||||||
+ | (buf[QCOWX_HDR_BACKING_FILE_SIZE+1] << 16)
|
|
||||||
+ | (buf[QCOWX_HDR_BACKING_FILE_SIZE+2] << 8)
|
|
||||||
+ | buf[QCOWX_HDR_BACKING_FILE_SIZE+3]); /* QCowHeader.backing_file_size */
|
|
||||||
if (size == 0)
|
|
||||||
return BACKING_STORE_OK;
|
|
||||||
if (offset + size > buf_size || offset + size < offset)
|
|
||||||
@@ -192,12 +271,63 @@ qcowXGetBackingStore(char **res,
|
|
||||||
}
|
|
||||||
memcpy(*res, buf + offset, size);
|
|
||||||
(*res)[size] = '\0';
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Traditionally QCow2 files had a layout of
|
|
||||||
+ *
|
|
||||||
+ * [header]
|
|
||||||
+ * [backingStoreName]
|
|
||||||
+ *
|
|
||||||
+ * Although the backingStoreName typically followed
|
|
||||||
+ * the header immediately, this was not required by
|
|
||||||
+ * the format. By specifying a higher byte offset for
|
|
||||||
+ * the backing file offset in the header, it was
|
|
||||||
+ * possible to leave space between the header and
|
|
||||||
+ * start of backingStore.
|
|
||||||
+ *
|
|
||||||
+ * This hack is now used to store extensions to the
|
|
||||||
+ * qcow2 format:
|
|
||||||
+ *
|
|
||||||
+ * [header]
|
|
||||||
+ * [extensions]
|
|
||||||
+ * [backingStoreName]
|
|
||||||
+ *
|
|
||||||
+ * Thus the file region to search for extensions is
|
|
||||||
+ * between the end of the header (QCOW2_HDR_TOTAL_SIZE)
|
|
||||||
+ * and the start of the backingStoreName (offset)
|
|
||||||
+ */
|
|
||||||
+ if (isQCow2)
|
|
||||||
+ qcow2GetBackingStoreFormat(format, buf, buf_size, QCOW2_HDR_TOTAL_SIZE, offset);
|
|
||||||
+
|
|
||||||
return BACKING_STORE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
+qcow1GetBackingStore(char **res,
|
|
||||||
+ int *format,
|
|
||||||
+ const unsigned char *buf,
|
|
||||||
+ size_t buf_size)
|
|
||||||
+{
|
|
||||||
+ /* QCow1 doesn't have the extensions capability
|
|
||||||
+ * used to store backing format */
|
|
||||||
+ *format = VIR_STORAGE_FILE_AUTO;
|
|
||||||
+ return qcowXGetBackingStore(res, NULL, buf, buf_size, false);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+qcow2GetBackingStore(char **res,
|
|
||||||
+ int *format,
|
|
||||||
+ const unsigned char *buf,
|
|
||||||
+ size_t buf_size)
|
|
||||||
+{
|
|
||||||
+ return qcowXGetBackingStore(res, format, buf, buf_size, true);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
vmdk4GetBackingStore(char **res,
|
|
||||||
+ int *format,
|
|
||||||
const unsigned char *buf,
|
|
||||||
size_t buf_size)
|
|
||||||
{
|
|
||||||
@@ -207,6 +337,12 @@ vmdk4GetBackingStore(char **res,
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
*res = NULL;
|
|
||||||
+ /* XXX should we set VMDK instead ? QEMU does auto
|
|
||||||
+ * probing, but this isn't in compliance with the
|
|
||||||
+ * VMDK spec/VMWare impl which presumes only VMDK
|
|
||||||
+ * backing format
|
|
||||||
+ */
|
|
||||||
+ *format = VIR_STORAGE_FILE_AUTO;
|
|
||||||
|
|
||||||
if (buf_size <= 0x200)
|
|
||||||
return BACKING_STORE_INVALID;
|
|
||||||
@@ -351,9 +487,12 @@ virStorageFileGetMetadataFromFD(const ch
|
|
||||||
/* Validation passed, we know the file format now */
|
|
||||||
meta->format = fileTypeInfo[i].type;
|
|
||||||
if (fileTypeInfo[i].getBackingStore != NULL) {
|
|
||||||
- char *base;
|
|
||||||
+ char *backing;
|
|
||||||
+ int backingFormat;
|
|
||||||
|
|
||||||
- switch (fileTypeInfo[i].getBackingStore(&base, head, len)) {
|
|
||||||
+ switch (fileTypeInfo[i].getBackingStore(&backing,
|
|
||||||
+ &backingFormat,
|
|
||||||
+ head, len)) {
|
|
||||||
case BACKING_STORE_OK:
|
|
||||||
break;
|
|
||||||
|
|
||||||
@@ -363,13 +502,16 @@ virStorageFileGetMetadataFromFD(const ch
|
|
||||||
case BACKING_STORE_ERROR:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
- if (base != NULL) {
|
|
||||||
- meta->backingStore = absolutePathFromBaseFile(path, base);
|
|
||||||
- VIR_FREE(base);
|
|
||||||
+ if (backing != NULL) {
|
|
||||||
+ meta->backingStore = absolutePathFromBaseFile(path, backing);
|
|
||||||
+ VIR_FREE(backing);
|
|
||||||
if (meta->backingStore == NULL) {
|
|
||||||
virReportOOMError();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
+ meta->backingStoreFormat = backingFormat;
|
|
||||||
+ } else {
|
|
||||||
+ meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
Index: libvirt-0.8.1/src/util/storage_file.h
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/storage_file.h
|
|
||||||
+++ libvirt-0.8.1/src/util/storage_file.h
|
|
||||||
@@ -28,6 +28,7 @@
|
|
||||||
# include <stdbool.h>
|
|
||||||
|
|
||||||
enum virStorageFileFormat {
|
|
||||||
+ VIR_STORAGE_FILE_AUTO = -1,
|
|
||||||
VIR_STORAGE_FILE_RAW = 0,
|
|
||||||
VIR_STORAGE_FILE_DIR,
|
|
||||||
VIR_STORAGE_FILE_BOCHS,
|
|
||||||
@@ -47,6 +48,7 @@ VIR_ENUM_DECL(virStorageFileFormat);
|
|
||||||
typedef struct _virStorageFileMetadata {
|
|
||||||
int format;
|
|
||||||
char *backingStore;
|
|
||||||
+ int backingStoreFormat;
|
|
||||||
unsigned long long capacity;
|
|
||||||
bool encrypted;
|
|
||||||
} virStorageFileMetadata;
|
|
@ -1,158 +0,0 @@
|
|||||||
>From 66c633413960e869a15062cee8667db51e6c817a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Mon, 14 Jun 2010 16:39:32 +0100
|
|
||||||
Subject: [PATCH 02/10] Remove 'type' field from FileTypeInfo struct
|
|
||||||
|
|
||||||
Instead of including a field in FileTypeInfo struct for the
|
|
||||||
disk format, rely on the array index matching the format.
|
|
||||||
Use verify() to assert the correct number of elements in the
|
|
||||||
array.
|
|
||||||
|
|
||||||
* src/util/storage_file.c: remove type field from FileTypeInfo
|
|
||||||
---
|
|
||||||
src/util/storage_file.c | 108 +++++++++++++++++++++++-----------------------
|
|
||||||
1 files changed, 54 insertions(+), 54 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/util/storage_file.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/storage_file.c
|
|
||||||
+++ libvirt-0.8.1/src/util/storage_file.c
|
|
||||||
@@ -51,7 +51,6 @@ enum {
|
|
||||||
|
|
||||||
/* Either 'magic' or 'extension' *must* be provided */
|
|
||||||
struct FileTypeInfo {
|
|
||||||
- int type; /* One of the constants above */
|
|
||||||
const char *magic; /* Optional string of file magic
|
|
||||||
* to check at head of file */
|
|
||||||
const char *extension; /* Optional file extension to check */
|
|
||||||
@@ -86,60 +85,59 @@ static int vmdk4GetBackingStore(char **,
|
|
||||||
|
|
||||||
|
|
||||||
static struct FileTypeInfo const fileTypeInfo[] = {
|
|
||||||
- /* Bochs */
|
|
||||||
- /* XXX Untested
|
|
||||||
- { VIR_STORAGE_FILE_BOCHS, "Bochs Virtual HD Image", NULL,
|
|
||||||
- LV_LITTLE_ENDIAN, 64, 0x20000,
|
|
||||||
- 32+16+16+4+4+4+4+4, 8, 1, -1, NULL },*/
|
|
||||||
- /* CLoop */
|
|
||||||
- /* 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,
|
|
||||||
- LV_LITTLE_ENDIAN, -1, 0,
|
|
||||||
- -1, 0, 0, -1, NULL }, */
|
|
||||||
- /* Cow */
|
|
||||||
- { VIR_STORAGE_FILE_COW, "OOOM", NULL,
|
|
||||||
- LV_BIG_ENDIAN, 4, 2,
|
|
||||||
- 4+4+1024+4, 8, 1, -1, cowGetBackingStore },
|
|
||||||
- /* DMG */
|
|
||||||
- /* XXX QEMU says there's no magic for dmg, but we should check... */
|
|
||||||
- { VIR_STORAGE_FILE_DMG, NULL, ".dmg",
|
|
||||||
- 0, -1, 0,
|
|
||||||
- -1, 0, 0, -1, NULL },
|
|
||||||
- /* XXX there's probably some magic for iso we can validate too... */
|
|
||||||
- { VIR_STORAGE_FILE_ISO, NULL, ".iso",
|
|
||||||
- 0, -1, 0,
|
|
||||||
- -1, 0, 0, -1, NULL },
|
|
||||||
- /* Parallels */
|
|
||||||
- /* XXX Untested
|
|
||||||
- { VIR_STORAGE_FILE_PARALLELS, "WithoutFreeSpace", NULL,
|
|
||||||
- LV_LITTLE_ENDIAN, 16, 2,
|
|
||||||
- 16+4+4+4+4, 4, 512, -1, NULL },
|
|
||||||
- */
|
|
||||||
- /* QCow */
|
|
||||||
- { VIR_STORAGE_FILE_QCOW, "QFI", NULL,
|
|
||||||
- LV_BIG_ENDIAN, 4, 1,
|
|
||||||
- 4+4+8+4+4, 8, 1, 4+4+8+4+4+8+1+1+2, qcow1GetBackingStore },
|
|
||||||
- /* QCow 2 */
|
|
||||||
- { VIR_STORAGE_FILE_QCOW2, "QFI", NULL,
|
|
||||||
- LV_BIG_ENDIAN, 4, 2,
|
|
||||||
- 4+4+8+4+4, 8, 1, 4+4+8+4+4+8, qcow2GetBackingStore },
|
|
||||||
- /* VMDK 3 */
|
|
||||||
- /* XXX Untested
|
|
||||||
- { VIR_STORAGE_FILE_VMDK, "COWD", NULL,
|
|
||||||
- LV_LITTLE_ENDIAN, 4, 1,
|
|
||||||
- 4+4+4, 4, 512, -1, NULL },
|
|
||||||
- */
|
|
||||||
- /* VMDK 4 */
|
|
||||||
- { VIR_STORAGE_FILE_VMDK, "KDMV", NULL,
|
|
||||||
- LV_LITTLE_ENDIAN, 4, 1,
|
|
||||||
- 4+4+4, 8, 512, -1, vmdk4GetBackingStore },
|
|
||||||
- /* Connectix / VirtualPC */
|
|
||||||
- /* XXX Untested
|
|
||||||
- { VIR_STORAGE_FILE_VPC, "conectix", NULL,
|
|
||||||
- LV_BIG_ENDIAN, -1, 0,
|
|
||||||
- -1, 0, 0, -1, NULL},
|
|
||||||
- */
|
|
||||||
+ [VIR_STORAGE_FILE_RAW] = { NULL, NULL, LV_LITTLE_ENDIAN, 0, 0, 0, 0, 0, 0, NULL },
|
|
||||||
+ [VIR_STORAGE_FILE_DIR] = { NULL, NULL, LV_LITTLE_ENDIAN, 0, 0, 0, 0, 0, 0, NULL },
|
|
||||||
+ [VIR_STORAGE_FILE_BOCHS] = {
|
|
||||||
+ /*"Bochs Virtual HD Image", */ /* Untested */ NULL,
|
|
||||||
+ NULL,
|
|
||||||
+ LV_LITTLE_ENDIAN, 64, 0x20000,
|
|
||||||
+ 32+16+16+4+4+4+4+4, 8, 1, -1, NULL
|
|
||||||
+ },
|
|
||||||
+ [VIR_STORAGE_FILE_CLOOP] = {
|
|
||||||
+ /*"#!/bin/sh\n#V2.0 Format\nmodprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n", */ /* Untested */ NULL,
|
|
||||||
+ NULL,
|
|
||||||
+ LV_LITTLE_ENDIAN, -1, 0,
|
|
||||||
+ -1, 0, 0, -1, NULL
|
|
||||||
+ },
|
|
||||||
+ [VIR_STORAGE_FILE_COW] = {
|
|
||||||
+ "OOOM", NULL,
|
|
||||||
+ LV_BIG_ENDIAN, 4, 2,
|
|
||||||
+ 4+4+1024+4, 8, 1, -1, cowGetBackingStore
|
|
||||||
+ },
|
|
||||||
+ [VIR_STORAGE_FILE_DMG] = {
|
|
||||||
+ NULL, /* XXX QEMU says there's no magic for dmg, but we should check... */
|
|
||||||
+ ".dmg",
|
|
||||||
+ 0, -1, 0,
|
|
||||||
+ -1, 0, 0, -1, NULL
|
|
||||||
+ },
|
|
||||||
+ [VIR_STORAGE_FILE_ISO] = {
|
|
||||||
+ NULL, /* XXX there's probably some magic for iso we can validate too... */
|
|
||||||
+ ".iso",
|
|
||||||
+ 0, -1, 0,
|
|
||||||
+ -1, 0, 0, -1, NULL
|
|
||||||
+ },
|
|
||||||
+ [VIR_STORAGE_FILE_QCOW] = {
|
|
||||||
+ "QFI", NULL,
|
|
||||||
+ LV_BIG_ENDIAN, 4, 1,
|
|
||||||
+ 4+4+8+4+4, 8, 1, 4+4+8+4+4+8+1+1+2, qcow1GetBackingStore
|
|
||||||
+ },
|
|
||||||
+ [VIR_STORAGE_FILE_QCOW2] = {
|
|
||||||
+ "QFI", NULL,
|
|
||||||
+ LV_BIG_ENDIAN, 4, 2,
|
|
||||||
+ 4+4+8+4+4, 8, 1, 4+4+8+4+4+8, qcow2GetBackingStore
|
|
||||||
+ },
|
|
||||||
+ [VIR_STORAGE_FILE_VMDK] = {
|
|
||||||
+ "KDMV", NULL,
|
|
||||||
+ LV_LITTLE_ENDIAN, 4, 1,
|
|
||||||
+ 4+4+4, 8, 512, -1, vmdk4GetBackingStore
|
|
||||||
+ },
|
|
||||||
+ [VIR_STORAGE_FILE_VPC] = {
|
|
||||||
+ "conectix", NULL,
|
|
||||||
+ LV_BIG_ENDIAN, 12, 0x10000,
|
|
||||||
+ 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL
|
|
||||||
+ },
|
|
||||||
};
|
|
||||||
+verify(ARRAY_CARDINALITY(fileTypeInfo) == VIR_STORAGE_FILE_LAST);
|
|
||||||
|
|
||||||
static int
|
|
||||||
cowGetBackingStore(char **res,
|
|
||||||
@@ -485,7 +483,7 @@ virStorageFileGetMetadataFromFD(const ch
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validation passed, we know the file format now */
|
|
||||||
- meta->format = fileTypeInfo[i].type;
|
|
||||||
+ meta->format = i;
|
|
||||||
if (fileTypeInfo[i].getBackingStore != NULL) {
|
|
||||||
char *backing;
|
|
||||||
int backingFormat;
|
|
||||||
@@ -525,7 +523,7 @@ virStorageFileGetMetadataFromFD(const ch
|
|
||||||
if (!virFileHasSuffix(path, fileTypeInfo[i].extension))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
- meta->format = fileTypeInfo[i].type;
|
|
||||||
+ meta->format = i;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,486 +0,0 @@
|
|||||||
>From f8d3e740cee4903bd2eef1a072e8190f5e9e92b9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Tue, 15 Jun 2010 14:58:10 +0100
|
|
||||||
Subject: [PATCH 03/10] Refactor virStorageFileGetMetadataFromFD to separate functionality
|
|
||||||
|
|
||||||
The virStorageFileGetMetadataFromFD did two jobs in one. First
|
|
||||||
it probed for storage type, then it extracted metadata for the
|
|
||||||
type. It is desirable to be able to separate these jobs, allowing
|
|
||||||
probing without querying metadata, and querying metadata without
|
|
||||||
probing.
|
|
||||||
|
|
||||||
To prepare for this, split out probing code into a new pair of
|
|
||||||
methods
|
|
||||||
|
|
||||||
virStorageFileProbeFormatFromFD
|
|
||||||
virStorageFileProbeFormat
|
|
||||||
|
|
||||||
* src/util/storage_file.c, src/util/storage_file.h,
|
|
||||||
src/libvirt_private.syms: Introduce virStorageFileProbeFormat
|
|
||||||
and virStorageFileProbeFormatFromFD
|
|
||||||
---
|
|
||||||
src/libvirt_private.syms | 2 +
|
|
||||||
src/util/storage_file.c | 393 ++++++++++++++++++++++++++++++++--------------
|
|
||||||
src/util/storage_file.h | 4 +
|
|
||||||
3 files changed, 281 insertions(+), 118 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/libvirt_private.syms
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/libvirt_private.syms
|
|
||||||
+++ libvirt-0.8.1/src/libvirt_private.syms
|
|
||||||
@@ -619,6 +619,8 @@ virStorageGenerateQcowPassphrase;
|
|
||||||
# storage_file.h
|
|
||||||
virStorageFileFormatTypeToString;
|
|
||||||
virStorageFileFormatTypeFromString;
|
|
||||||
+virStorageFileProbeFormat;
|
|
||||||
+virStorageFileProbeFormatFromFD;
|
|
||||||
virStorageFileGetMetadata;
|
|
||||||
virStorageFileGetMetadataFromFD;
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/util/storage_file.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/storage_file.c
|
|
||||||
+++ libvirt-0.8.1/src/util/storage_file.c
|
|
||||||
@@ -85,8 +85,8 @@ static int vmdk4GetBackingStore(char **,
|
|
||||||
|
|
||||||
|
|
||||||
static struct FileTypeInfo const fileTypeInfo[] = {
|
|
||||||
- [VIR_STORAGE_FILE_RAW] = { NULL, NULL, LV_LITTLE_ENDIAN, 0, 0, 0, 0, 0, 0, NULL },
|
|
||||||
- [VIR_STORAGE_FILE_DIR] = { NULL, NULL, LV_LITTLE_ENDIAN, 0, 0, 0, 0, 0, 0, NULL },
|
|
||||||
+ [VIR_STORAGE_FILE_RAW] = { NULL, NULL, LV_LITTLE_ENDIAN, -1, 0, 0, 0, 0, 0, NULL },
|
|
||||||
+ [VIR_STORAGE_FILE_DIR] = { NULL, NULL, LV_LITTLE_ENDIAN, -1, 0, 0, 0, 0, 0, NULL },
|
|
||||||
[VIR_STORAGE_FILE_BOCHS] = {
|
|
||||||
/*"Bochs Virtual HD Image", */ /* Untested */ NULL,
|
|
||||||
NULL,
|
|
||||||
@@ -390,146 +390,302 @@ absolutePathFromBaseFile(const char *bas
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int
|
|
||||||
+virStorageFileMatchesMagic(int format,
|
|
||||||
+ unsigned char *buf,
|
|
||||||
+ size_t buflen)
|
|
||||||
+{
|
|
||||||
+ int mlen;
|
|
||||||
+
|
|
||||||
+ if (fileTypeInfo[format].magic == NULL)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ /* Validate magic data */
|
|
||||||
+ mlen = strlen(fileTypeInfo[format].magic);
|
|
||||||
+ if (mlen > buflen)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ if (memcmp(buf, fileTypeInfo[format].magic, mlen) != 0)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+virStorageFileMatchesExtension(int format,
|
|
||||||
+ const char *path)
|
|
||||||
+{
|
|
||||||
+ if (fileTypeInfo[format].extension == NULL)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ if (virFileHasSuffix(path, fileTypeInfo[format].extension))
|
|
||||||
+ return 1;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+virStorageFileMatchesVersion(int format,
|
|
||||||
+ unsigned char *buf,
|
|
||||||
+ size_t buflen)
|
|
||||||
+{
|
|
||||||
+ int version;
|
|
||||||
+
|
|
||||||
+ /* Validate version number info */
|
|
||||||
+ if (fileTypeInfo[format].versionOffset == -1)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ if ((fileTypeInfo[format].versionOffset + 4) > buflen)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ if (fileTypeInfo[format].endian == LV_LITTLE_ENDIAN) {
|
|
||||||
+ version =
|
|
||||||
+ (buf[fileTypeInfo[format].versionOffset+3] << 24) |
|
|
||||||
+ (buf[fileTypeInfo[format].versionOffset+2] << 16) |
|
|
||||||
+ (buf[fileTypeInfo[format].versionOffset+1] << 8) |
|
|
||||||
+ (buf[fileTypeInfo[format].versionOffset]);
|
|
||||||
+ } else {
|
|
||||||
+ version =
|
|
||||||
+ (buf[fileTypeInfo[format].versionOffset] << 24) |
|
|
||||||
+ (buf[fileTypeInfo[format].versionOffset+1] << 16) |
|
|
||||||
+ (buf[fileTypeInfo[format].versionOffset+2] << 8) |
|
|
||||||
+ (buf[fileTypeInfo[format].versionOffset+3]);
|
|
||||||
+ }
|
|
||||||
+ if (version != fileTypeInfo[format].versionNumber)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+virStorageFileGetMetadataFromBuf(int format,
|
|
||||||
+ const char *path,
|
|
||||||
+ unsigned char *buf,
|
|
||||||
+ size_t buflen,
|
|
||||||
+ virStorageFileMetadata *meta)
|
|
||||||
+{
|
|
||||||
+ /* XXX we should consider moving virStorageBackendUpdateVolInfo
|
|
||||||
+ * code into this method, for non-magic files
|
|
||||||
+ */
|
|
||||||
+ if (!fileTypeInfo[format].magic) {
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Optionally extract capacity from file */
|
|
||||||
+ if (fileTypeInfo[format].sizeOffset != -1) {
|
|
||||||
+ if ((fileTypeInfo[format].sizeOffset + 8) > buflen)
|
|
||||||
+ return 1;
|
|
||||||
+
|
|
||||||
+ if (fileTypeInfo[format].endian == LV_LITTLE_ENDIAN) {
|
|
||||||
+ meta->capacity =
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+7] << 56) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+6] << 48) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+5] << 40) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+4] << 32) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+3] << 24) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+2] << 16) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+1] << 8) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset]);
|
|
||||||
+ } else {
|
|
||||||
+ meta->capacity =
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset] << 56) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+1] << 48) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+2] << 40) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+3] << 32) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+4] << 24) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+5] << 16) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+6] << 8) |
|
|
||||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+7]);
|
|
||||||
+ }
|
|
||||||
+ /* Avoid unlikely, but theoretically possible overflow */
|
|
||||||
+ if (meta->capacity > (ULLONG_MAX / fileTypeInfo[format].sizeMultiplier))
|
|
||||||
+ return 1;
|
|
||||||
+ meta->capacity *= fileTypeInfo[format].sizeMultiplier;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (fileTypeInfo[format].qcowCryptOffset != -1) {
|
|
||||||
+ int crypt_format;
|
|
||||||
+
|
|
||||||
+ crypt_format =
|
|
||||||
+ (buf[fileTypeInfo[format].qcowCryptOffset] << 24) |
|
|
||||||
+ (buf[fileTypeInfo[format].qcowCryptOffset+1] << 16) |
|
|
||||||
+ (buf[fileTypeInfo[format].qcowCryptOffset+2] << 8) |
|
|
||||||
+ (buf[fileTypeInfo[format].qcowCryptOffset+3]);
|
|
||||||
+ meta->encrypted = crypt_format != 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (fileTypeInfo[format].getBackingStore != NULL) {
|
|
||||||
+ char *backing;
|
|
||||||
+ int backingFormat;
|
|
||||||
+ int ret = fileTypeInfo[format].getBackingStore(&backing,
|
|
||||||
+ &backingFormat,
|
|
||||||
+ buf, buflen);
|
|
||||||
+ if (ret == BACKING_STORE_INVALID)
|
|
||||||
+ return 1;
|
|
||||||
+
|
|
||||||
+ if (ret == BACKING_STORE_ERROR)
|
|
||||||
+ return -1;
|
|
||||||
+
|
|
||||||
+ if (backing != NULL) {
|
|
||||||
+ meta->backingStore = absolutePathFromBaseFile(path, backing);
|
|
||||||
+ VIR_FREE(backing);
|
|
||||||
+ if (meta->backingStore == NULL) {
|
|
||||||
+ virReportOOMError();
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ meta->backingStoreFormat = backingFormat;
|
|
||||||
+ } else {
|
|
||||||
+ meta->backingStore = NULL;
|
|
||||||
+ meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+virStorageFileProbeFormatFromBuf(const char *path,
|
|
||||||
+ unsigned char *buf,
|
|
||||||
+ size_t buflen)
|
|
||||||
+{
|
|
||||||
+ int format = VIR_STORAGE_FILE_RAW;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ /* First check file magic */
|
|
||||||
+ for (i = 0 ; i < VIR_STORAGE_FILE_LAST ; i++) {
|
|
||||||
+ if (virStorageFileMatchesMagic(i, buf, buflen) &&
|
|
||||||
+ virStorageFileMatchesVersion(i, buf, buflen)) {
|
|
||||||
+ format = i;
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* No magic, so check file extension */
|
|
||||||
+ for (i = 0 ; i < VIR_STORAGE_FILE_LAST ; i++) {
|
|
||||||
+ if (virStorageFileMatchesExtension(i, path)) {
|
|
||||||
+ format = i;
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+cleanup:
|
|
||||||
+ return format;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
- * Probe the header of a file to determine what type of disk image
|
|
||||||
- * it is, and info about its capacity if available.
|
|
||||||
+ * virStorageFileProbeFormatFromFD:
|
|
||||||
+ *
|
|
||||||
+ * Probe for the format of 'fd' (which is an open file descriptor
|
|
||||||
+ * pointing to 'path'), returning the detected disk format.
|
|
||||||
+ *
|
|
||||||
+ * Callers are advised never to trust the returned 'format'
|
|
||||||
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
|
||||||
+ * malicious guest can turn a file into any other non-raw
|
|
||||||
+ * format at will.
|
|
||||||
+ *
|
|
||||||
+ * Best option: Don't use this function
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
-virStorageFileGetMetadataFromFD(const char *path,
|
|
||||||
- int fd,
|
|
||||||
- virStorageFileMetadata *meta)
|
|
||||||
+virStorageFileProbeFormatFromFD(const char *path, int fd)
|
|
||||||
{
|
|
||||||
unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
|
|
||||||
- int len, i;
|
|
||||||
+ int len;
|
|
||||||
|
|
||||||
- /* If all else fails, call it a raw file */
|
|
||||||
- meta->format = VIR_STORAGE_FILE_RAW;
|
|
||||||
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
||||||
+ virReportSystemError(errno, _("cannot set to start of '%s'"), path);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if ((len = read(fd, head, sizeof(head))) < 0) {
|
|
||||||
virReportSystemError(errno, _("cannot read header '%s'"), path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* First check file magic */
|
|
||||||
- for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
|
|
||||||
- int mlen;
|
|
||||||
+ return virStorageFileProbeFormatFromBuf(path, head, len);
|
|
||||||
+}
|
|
||||||
|
|
||||||
- if (fileTypeInfo[i].magic == NULL)
|
|
||||||
- continue;
|
|
||||||
+/**
|
|
||||||
+ * virStorageFileProbeFormat:
|
|
||||||
+ *
|
|
||||||
+ * Probe for the format of 'path', returning the detected
|
|
||||||
+ * disk format.
|
|
||||||
+ *
|
|
||||||
+ * Callers are advised never to trust the returned 'format'
|
|
||||||
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
|
||||||
+ * malicious guest can turn a file into any other non-raw
|
|
||||||
+ * format at will.
|
|
||||||
+ *
|
|
||||||
+ * Best option: Don't use this function
|
|
||||||
+ */
|
|
||||||
+int
|
|
||||||
+virStorageFileProbeFormat(const char *path)
|
|
||||||
+{
|
|
||||||
+ int fd, ret;
|
|
||||||
|
|
||||||
- /* Validate magic data */
|
|
||||||
- mlen = strlen(fileTypeInfo[i].magic);
|
|
||||||
- if (mlen > len)
|
|
||||||
- continue;
|
|
||||||
- if (memcmp(head, fileTypeInfo[i].magic, mlen) != 0)
|
|
||||||
- continue;
|
|
||||||
-
|
|
||||||
- /* Validate version number info */
|
|
||||||
- if (fileTypeInfo[i].versionNumber != -1) {
|
|
||||||
- int version;
|
|
||||||
-
|
|
||||||
- if (fileTypeInfo[i].endian == LV_LITTLE_ENDIAN) {
|
|
||||||
- version = (head[fileTypeInfo[i].versionOffset+3] << 24) |
|
|
||||||
- (head[fileTypeInfo[i].versionOffset+2] << 16) |
|
|
||||||
- (head[fileTypeInfo[i].versionOffset+1] << 8) |
|
|
||||||
- head[fileTypeInfo[i].versionOffset];
|
|
||||||
- } else {
|
|
||||||
- version = (head[fileTypeInfo[i].versionOffset] << 24) |
|
|
||||||
- (head[fileTypeInfo[i].versionOffset+1] << 16) |
|
|
||||||
- (head[fileTypeInfo[i].versionOffset+2] << 8) |
|
|
||||||
- head[fileTypeInfo[i].versionOffset+3];
|
|
||||||
- }
|
|
||||||
- if (version != fileTypeInfo[i].versionNumber)
|
|
||||||
- continue;
|
|
||||||
- }
|
|
||||||
+ if ((fd = open(path, O_RDONLY)) < 0) {
|
|
||||||
+ virReportSystemError(errno, _("cannot open file '%s'"), path);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- /* Optionally extract capacity from file */
|
|
||||||
- if (fileTypeInfo[i].sizeOffset != -1) {
|
|
||||||
- if (fileTypeInfo[i].endian == LV_LITTLE_ENDIAN) {
|
|
||||||
- meta->capacity =
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+7] << 56) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+6] << 48) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+5] << 40) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+4] << 32) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+3] << 24) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+2] << 16) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+1] << 8) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset]);
|
|
||||||
- } else {
|
|
||||||
- meta->capacity =
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset] << 56) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+1] << 48) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+2] << 40) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+3] << 32) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+4] << 24) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+5] << 16) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+6] << 8) |
|
|
||||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+7]);
|
|
||||||
- }
|
|
||||||
- /* Avoid unlikely, but theoretically possible overflow */
|
|
||||||
- if (meta->capacity > (ULLONG_MAX / fileTypeInfo[i].sizeMultiplier))
|
|
||||||
- continue;
|
|
||||||
- meta->capacity *= fileTypeInfo[i].sizeMultiplier;
|
|
||||||
- }
|
|
||||||
+ ret = virStorageFileProbeFormatFromFD(path, fd);
|
|
||||||
|
|
||||||
- if (fileTypeInfo[i].qcowCryptOffset != -1) {
|
|
||||||
- int crypt_format;
|
|
||||||
+ close(fd);
|
|
||||||
|
|
||||||
- crypt_format = (head[fileTypeInfo[i].qcowCryptOffset] << 24) |
|
|
||||||
- (head[fileTypeInfo[i].qcowCryptOffset+1] << 16) |
|
|
||||||
- (head[fileTypeInfo[i].qcowCryptOffset+2] << 8) |
|
|
||||||
- head[fileTypeInfo[i].qcowCryptOffset+3];
|
|
||||||
- meta->encrypted = crypt_format != 0;
|
|
||||||
- }
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
|
|
||||||
- /* Validation passed, we know the file format now */
|
|
||||||
- meta->format = i;
|
|
||||||
- if (fileTypeInfo[i].getBackingStore != NULL) {
|
|
||||||
- char *backing;
|
|
||||||
- int backingFormat;
|
|
||||||
-
|
|
||||||
- switch (fileTypeInfo[i].getBackingStore(&backing,
|
|
||||||
- &backingFormat,
|
|
||||||
- head, len)) {
|
|
||||||
- case BACKING_STORE_OK:
|
|
||||||
- break;
|
|
||||||
+/**
|
|
||||||
+ * virStorageFileGetMetadataFromFD:
|
|
||||||
+ *
|
|
||||||
+ * Probe for the format of 'fd' (which is an open file descriptor
|
|
||||||
+ * for the file 'path'), filling 'meta' with the detected
|
|
||||||
+ * format and other associated metadata.
|
|
||||||
+ *
|
|
||||||
+ * Callers are advised never to trust the returned 'meta->format'
|
|
||||||
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
|
||||||
+ * malicious guest can turn a file into any other non-raw
|
|
||||||
+ * format at will.
|
|
||||||
+ */
|
|
||||||
+int
|
|
||||||
+virStorageFileGetMetadataFromFD(const char *path,
|
|
||||||
+ int fd,
|
|
||||||
+ virStorageFileMetadata *meta)
|
|
||||||
+{
|
|
||||||
+ unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
|
|
||||||
+ int len;
|
|
||||||
|
|
||||||
- case BACKING_STORE_INVALID:
|
|
||||||
- continue;
|
|
||||||
+ memset(meta, 0, sizeof (*meta));
|
|
||||||
|
|
||||||
- case BACKING_STORE_ERROR:
|
|
||||||
- return -1;
|
|
||||||
- }
|
|
||||||
- if (backing != NULL) {
|
|
||||||
- meta->backingStore = absolutePathFromBaseFile(path, backing);
|
|
||||||
- VIR_FREE(backing);
|
|
||||||
- if (meta->backingStore == NULL) {
|
|
||||||
- virReportOOMError();
|
|
||||||
- return -1;
|
|
||||||
- }
|
|
||||||
- meta->backingStoreFormat = backingFormat;
|
|
||||||
- } else {
|
|
||||||
- meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- return 0;
|
|
||||||
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
||||||
+ virReportSystemError(errno, _("cannot set to start of '%s'"), path);
|
|
||||||
+ return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* No magic, so check file extension */
|
|
||||||
- for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
|
|
||||||
- if (fileTypeInfo[i].extension == NULL)
|
|
||||||
- continue;
|
|
||||||
-
|
|
||||||
- if (!virFileHasSuffix(path, fileTypeInfo[i].extension))
|
|
||||||
- continue;
|
|
||||||
-
|
|
||||||
- meta->format = i;
|
|
||||||
- return 0;
|
|
||||||
+ if ((len = read(fd, head, sizeof(head))) < 0) {
|
|
||||||
+ virReportSystemError(errno, _("cannot read header '%s'"), path);
|
|
||||||
+ return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- return 0;
|
|
||||||
+ meta->format = virStorageFileProbeFormatFromBuf(path, head, len);
|
|
||||||
+
|
|
||||||
+ return virStorageFileGetMetadataFromBuf(meta->format, path, head, len, meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * virStorageFileGetMetadata:
|
|
||||||
+ *
|
|
||||||
+ * Probe for the format of 'path', filling 'meta' with the detected
|
|
||||||
+ * format and other associated metadata.
|
|
||||||
+ *
|
|
||||||
+ * Callers are advised never to trust the returned 'meta->format'
|
|
||||||
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
|
||||||
+ * malicious guest can turn a file into any other non-raw
|
|
||||||
+ * format at will.
|
|
||||||
+ */
|
|
||||||
int
|
|
||||||
virStorageFileGetMetadata(const char *path,
|
|
||||||
virStorageFileMetadata *meta)
|
|
||||||
Index: libvirt-0.8.1/src/util/storage_file.h
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/storage_file.h
|
|
||||||
+++ libvirt-0.8.1/src/util/storage_file.h
|
|
||||||
@@ -57,6 +57,10 @@ typedef struct _virStorageFileMetadata {
|
|
||||||
# define DEV_BSIZE 512
|
|
||||||
# endif
|
|
||||||
|
|
||||||
+int virStorageFileProbeFormat(const char *path);
|
|
||||||
+int virStorageFileProbeFormatFromFD(const char *path,
|
|
||||||
+ int fd);
|
|
||||||
+
|
|
||||||
int virStorageFileGetMetadata(const char *path,
|
|
||||||
virStorageFileMetadata *meta);
|
|
||||||
int virStorageFileGetMetadataFromFD(const char *path,
|
|
@ -1,218 +0,0 @@
|
|||||||
>From 7b2c30d0af7938df533b85e948918cfdff2e5f01 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Tue, 15 Jun 2010 16:15:51 +0100
|
|
||||||
Subject: [PATCH 04/10] Require format to be passed into virStorageFileGetMetadata
|
|
||||||
|
|
||||||
Require the disk image to be passed into virStorageFileGetMetadata.
|
|
||||||
If this is set to VIR_STORAGE_FILE_AUTO, then the format will be
|
|
||||||
resolved using probing. This makes it easier to control when
|
|
||||||
probing will be used
|
|
||||||
|
|
||||||
* src/qemu/qemu_driver.c, src/qemu/qemu_security_dac.c,
|
|
||||||
src/security/security_selinux.c, src/security/virt-aa-helper.c:
|
|
||||||
Set VIR_STORAGE_FILE_AUTO when calling virStorageFileGetMetadata.
|
|
||||||
* src/storage/storage_backend_fs.c: Probe for disk format before
|
|
||||||
caling virStorageFileGetMetadata.
|
|
||||||
* src/util/storage_file.h, src/util/storage_file.c: Remove format
|
|
||||||
from virStorageFileMeta struct & require it to be passed into
|
|
||||||
method.
|
|
||||||
---
|
|
||||||
src/qemu/qemu_driver.c | 27 +++++++++++++++++++++++----
|
|
||||||
src/qemu/qemu_security_dac.c | 4 +++-
|
|
||||||
src/security/security_selinux.c | 4 +++-
|
|
||||||
src/security/virt-aa-helper.c | 4 +++-
|
|
||||||
src/storage/storage_backend_fs.c | 11 ++++++++---
|
|
||||||
src/util/storage_file.c | 15 ++++++++++++---
|
|
||||||
src/util/storage_file.h | 3 ++-
|
|
||||||
7 files changed, 54 insertions(+), 14 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_driver.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
@@ -9059,8 +9059,10 @@ static int qemuDomainGetBlockInfo(virDom
|
|
||||||
int fd = -1;
|
|
||||||
off_t end;
|
|
||||||
virStorageFileMetadata meta;
|
|
||||||
+ virDomainDiskDefPtr disk = NULL;
|
|
||||||
struct stat sb;
|
|
||||||
int i;
|
|
||||||
+ int format;
|
|
||||||
|
|
||||||
virCheckFlags(0, -1);
|
|
||||||
|
|
||||||
@@ -9086,6 +9088,7 @@ static int qemuDomainGetBlockInfo(virDom
|
|
||||||
if (vm->def->disks[i]->src != NULL &&
|
|
||||||
STREQ (vm->def->disks[i]->src, path)) {
|
|
||||||
ret = 0;
|
|
||||||
+ disk = vm->def->disks[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9108,7 +9111,21 @@ static int qemuDomainGetBlockInfo(virDom
|
|
||||||
|
|
||||||
/* Probe for magic formats */
|
|
||||||
memset(&meta, 0, sizeof(meta));
|
|
||||||
- if (virStorageFileGetMetadataFromFD(path, fd, &meta) < 0)
|
|
||||||
+ if (disk->driverType) {
|
|
||||||
+ if ((format = virStorageFileFormatTypeFromString(disk->driverType)) < 0) {
|
|
||||||
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
+ _("unknown disk format %s for %s"),
|
|
||||||
+ disk->driverType, disk->src);
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if ((format = virStorageFileProbeFormat(disk->src)) < 0)
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (virStorageFileGetMetadataFromFD(path, fd,
|
|
||||||
+ format,
|
|
||||||
+ &meta) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Get info for normal formats */
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_security_dac.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_security_dac.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_security_dac.c
|
|
||||||
@@ -118,7 +118,9 @@ qemuSecurityDACSetSecurityImageLabel(vir
|
|
||||||
|
|
||||||
memset(&meta, 0, sizeof(meta));
|
|
||||||
|
|
||||||
- ret = virStorageFileGetMetadata(path, &meta);
|
|
||||||
+ ret = virStorageFileGetMetadata(path,
|
|
||||||
+ VIR_STORAGE_FILE_AUTO,
|
|
||||||
+ &meta);
|
|
||||||
|
|
||||||
if (path != disk->src)
|
|
||||||
VIR_FREE(path);
|
|
||||||
Index: libvirt-0.8.1/src/security/security_selinux.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/security/security_selinux.c
|
|
||||||
+++ libvirt-0.8.1/src/security/security_selinux.c
|
|
||||||
@@ -431,7 +431,9 @@ SELinuxSetSecurityImageLabel(virDomainOb
|
|
||||||
|
|
||||||
memset(&meta, 0, sizeof(meta));
|
|
||||||
|
|
||||||
- ret = virStorageFileGetMetadata(path, &meta);
|
|
||||||
+ ret = virStorageFileGetMetadata(path,
|
|
||||||
+ VIR_STORAGE_FILE_AUTO,
|
|
||||||
+ &meta);
|
|
||||||
|
|
||||||
if (path != disk->src)
|
|
||||||
VIR_FREE(path);
|
|
||||||
Index: libvirt-0.8.1/src/security/virt-aa-helper.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/security/virt-aa-helper.c
|
|
||||||
+++ libvirt-0.8.1/src/security/virt-aa-helper.c
|
|
||||||
@@ -833,7 +833,9 @@ get_files(vahControl * ctl)
|
|
||||||
|
|
||||||
memset(&meta, 0, sizeof(meta));
|
|
||||||
|
|
||||||
- ret = virStorageFileGetMetadata(path, &meta);
|
|
||||||
+ ret = virStorageFileGetMetadata(path,
|
|
||||||
+ VIR_STORAGE_FILE_AUTO,
|
|
||||||
+ &meta);
|
|
||||||
|
|
||||||
if (path != ctl->def->disks[i]->src)
|
|
||||||
VIR_FREE(path);
|
|
||||||
Index: libvirt-0.8.1/src/storage/storage_backend_fs.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/storage/storage_backend_fs.c
|
|
||||||
+++ libvirt-0.8.1/src/storage/storage_backend_fs.c
|
|
||||||
@@ -77,14 +77,19 @@ virStorageBackendProbeTarget(virStorageV
|
|
||||||
|
|
||||||
memset(&meta, 0, sizeof(meta));
|
|
||||||
|
|
||||||
- if (virStorageFileGetMetadataFromFD(target->path, fd, &meta) < 0) {
|
|
||||||
+ if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) {
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- close(fd);
|
|
||||||
+ if (virStorageFileGetMetadataFromFD(target->path, fd,
|
|
||||||
+ target->format,
|
|
||||||
+ &meta) < 0) {
|
|
||||||
+ close(fd);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- target->format = meta.format;
|
|
||||||
+ close(fd);
|
|
||||||
|
|
||||||
if (backingStore) {
|
|
||||||
*backingStore = meta.backingStore;
|
|
||||||
Index: libvirt-0.8.1/src/util/storage_file.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/storage_file.c
|
|
||||||
+++ libvirt-0.8.1/src/util/storage_file.c
|
|
||||||
@@ -653,6 +653,7 @@ virStorageFileProbeFormat(const char *pa
|
|
||||||
int
|
|
||||||
virStorageFileGetMetadataFromFD(const char *path,
|
|
||||||
int fd,
|
|
||||||
+ int format,
|
|
||||||
virStorageFileMetadata *meta)
|
|
||||||
{
|
|
||||||
unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
|
|
||||||
@@ -670,9 +671,16 @@ virStorageFileGetMetadataFromFD(const ch
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- meta->format = virStorageFileProbeFormatFromBuf(path, head, len);
|
|
||||||
+ if (format == VIR_STORAGE_FILE_AUTO)
|
|
||||||
+ format = virStorageFileProbeFormatFromBuf(path, head, len);
|
|
||||||
|
|
||||||
- return virStorageFileGetMetadataFromBuf(meta->format, path, head, len, meta);
|
|
||||||
+ if (format < 0 ||
|
|
||||||
+ format >= VIR_STORAGE_FILE_LAST) {
|
|
||||||
+ virReportSystemError(EINVAL, _("unknown storage file format %d"), format);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return virStorageFileGetMetadataFromBuf(format, path, head, len, meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -688,6 +696,7 @@ virStorageFileGetMetadataFromFD(const ch
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
virStorageFileGetMetadata(const char *path,
|
|
||||||
+ int format,
|
|
||||||
virStorageFileMetadata *meta)
|
|
||||||
{
|
|
||||||
int fd, ret;
|
|
||||||
@@ -697,7 +706,7 @@ virStorageFileGetMetadata(const char *pa
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ret = virStorageFileGetMetadataFromFD(path, fd, meta);
|
|
||||||
+ ret = virStorageFileGetMetadataFromFD(path, fd, format, meta);
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/util/storage_file.h
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/storage_file.h
|
|
||||||
+++ libvirt-0.8.1/src/util/storage_file.h
|
|
||||||
@@ -46,7 +46,6 @@ enum virStorageFileFormat {
|
|
||||||
VIR_ENUM_DECL(virStorageFileFormat);
|
|
||||||
|
|
||||||
typedef struct _virStorageFileMetadata {
|
|
||||||
- int format;
|
|
||||||
char *backingStore;
|
|
||||||
int backingStoreFormat;
|
|
||||||
unsigned long long capacity;
|
|
||||||
@@ -62,9 +61,11 @@ int virStorageFileProbeFormatFromFD(cons
|
|
||||||
int fd);
|
|
||||||
|
|
||||||
int virStorageFileGetMetadata(const char *path,
|
|
||||||
+ int format,
|
|
||||||
virStorageFileMetadata *meta);
|
|
||||||
int virStorageFileGetMetadataFromFD(const char *path,
|
|
||||||
int fd,
|
|
||||||
+ int format,
|
|
||||||
virStorageFileMetadata *meta);
|
|
||||||
|
|
||||||
#endif /* __VIR_STORAGE_FILE_H__ */
|
|
@ -1,167 +0,0 @@
|
|||||||
>From 494b96317334716f846436a5ec485963411cb4a3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Mon, 14 Jun 2010 18:09:15 +0100
|
|
||||||
Subject: [PATCH 05/10] Add an API for iterating over disk paths
|
|
||||||
|
|
||||||
There is duplicated code which iterates over disk backing stores
|
|
||||||
performing some action. Provide a convenient helper for doing
|
|
||||||
this to eliminate duplication & risk of mistakes with disk format
|
|
||||||
probing
|
|
||||||
|
|
||||||
* src/conf/domain_conf.c, src/conf/domain_conf.h,
|
|
||||||
src/libvirt_private.syms: Add virDomainDiskDefForeachPath()
|
|
||||||
---
|
|
||||||
src/conf/domain_conf.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
src/conf/domain_conf.h | 11 +++++
|
|
||||||
src/libvirt_private.syms | 1 +
|
|
||||||
3 files changed, 111 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/conf/domain_conf.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/conf/domain_conf.c
|
|
||||||
+++ libvirt-0.8.1/src/conf/domain_conf.c
|
|
||||||
@@ -45,6 +45,7 @@
|
|
||||||
#include "macvtap.h"
|
|
||||||
#include "nwfilter_conf.h"
|
|
||||||
#include "ignore-value.h"
|
|
||||||
+#include "storage_file.h"
|
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
|
||||||
|
|
||||||
@@ -6928,4 +6929,102 @@ int virDomainSnapshotHasChildren(virDoma
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
|
|
||||||
+ bool allowProbing,
|
|
||||||
+ bool ignoreOpenFailure,
|
|
||||||
+ virDomainDiskDefPathIterator iter,
|
|
||||||
+ void *opaque)
|
|
||||||
+{
|
|
||||||
+ virHashTablePtr paths;
|
|
||||||
+ int format;
|
|
||||||
+ int ret = -1;
|
|
||||||
+ int depth = 0;
|
|
||||||
+ char *nextpath = NULL;
|
|
||||||
+
|
|
||||||
+ if (!disk->src)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ if (disk->driverType) {
|
|
||||||
+ const char *formatStr = disk->driverType;
|
|
||||||
+ if (STREQ(formatStr, "aio"))
|
|
||||||
+ formatStr = "raw"; /* Xen compat */
|
|
||||||
+
|
|
||||||
+ if ((format = virStorageFileFormatTypeFromString(formatStr)) < 0) {
|
|
||||||
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
+ _("unknown disk format '%s' for %s"),
|
|
||||||
+ disk->driverType, disk->src);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if (allowProbing) {
|
|
||||||
+ format = VIR_STORAGE_FILE_AUTO;
|
|
||||||
+ } else {
|
|
||||||
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
+ _("no disk format for %s and probing is disabled"),
|
|
||||||
+ disk->src);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ paths = virHashCreate(5);
|
|
||||||
+
|
|
||||||
+ do {
|
|
||||||
+ virStorageFileMetadata meta;
|
|
||||||
+ const char *path = nextpath ? nextpath : disk->src;
|
|
||||||
+ int fd;
|
|
||||||
+
|
|
||||||
+ if (iter(disk, path, depth, opaque) < 0)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ if (virHashLookup(paths, path)) {
|
|
||||||
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
+ _("backing store for %s is self-referential"),
|
|
||||||
+ disk->src);
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if ((fd = open(path, O_RDONLY)) < 0) {
|
|
||||||
+ if (ignoreOpenFailure) {
|
|
||||||
+ char ebuf[1024];
|
|
||||||
+ VIR_WARN("Ignoring open failure on %s: %s", path,
|
|
||||||
+ virStrerror(errno, ebuf, sizeof(ebuf)));
|
|
||||||
+ break;
|
|
||||||
+ } else {
|
|
||||||
+ virReportSystemError(errno,
|
|
||||||
+ _("unable to open disk path %s"),
|
|
||||||
+ path);
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (virStorageFileGetMetadataFromFD(path, fd, format, &meta) < 0) {
|
|
||||||
+ close(fd);
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+ close(fd);
|
|
||||||
+
|
|
||||||
+ if (virHashAddEntry(paths, path, (void*)0x1) < 0) {
|
|
||||||
+ virReportOOMError();
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ depth++;
|
|
||||||
+ nextpath = meta.backingStore;
|
|
||||||
+
|
|
||||||
+ format = meta.backingStoreFormat;
|
|
||||||
+
|
|
||||||
+ if (format == VIR_STORAGE_FILE_AUTO &&
|
|
||||||
+ !allowProbing)
|
|
||||||
+ format = VIR_STORAGE_FILE_RAW; /* Stops further recursion */
|
|
||||||
+ } while (nextpath);
|
|
||||||
+
|
|
||||||
+ ret = 0;
|
|
||||||
+
|
|
||||||
+cleanup:
|
|
||||||
+ virHashFree(paths, NULL);
|
|
||||||
+ VIR_FREE(nextpath);
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
#endif /* ! PROXY */
|
|
||||||
Index: libvirt-0.8.1/src/conf/domain_conf.h
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/conf/domain_conf.h
|
|
||||||
+++ libvirt-0.8.1/src/conf/domain_conf.h
|
|
||||||
@@ -1057,6 +1057,17 @@ int virDomainObjListGetInactiveNames(vir
|
|
||||||
int maxnames);
|
|
||||||
|
|
||||||
|
|
||||||
+typedef int (*virDomainDiskDefPathIterator)(virDomainDiskDefPtr disk,
|
|
||||||
+ const char *path,
|
|
||||||
+ unsigned int depth,
|
|
||||||
+ void *opaque);
|
|
||||||
+
|
|
||||||
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
|
|
||||||
+ bool allowProbing,
|
|
||||||
+ bool ignoreOpenFailure,
|
|
||||||
+ virDomainDiskDefPathIterator iter,
|
|
||||||
+ void *opaque);
|
|
||||||
+
|
|
||||||
VIR_ENUM_DECL(virDomainVirt)
|
|
||||||
VIR_ENUM_DECL(virDomainBoot)
|
|
||||||
VIR_ENUM_DECL(virDomainFeature)
|
|
||||||
Index: libvirt-0.8.1/src/libvirt_private.syms
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/libvirt_private.syms
|
|
||||||
+++ libvirt-0.8.1/src/libvirt_private.syms
|
|
||||||
@@ -223,6 +223,7 @@ virDomainSnapshotObjUnref;
|
|
||||||
virDomainSnapshotDefParseString;
|
|
||||||
virDomainSnapshotDefFormat;
|
|
||||||
virDomainSnapshotAssignDef;
|
|
||||||
+virDomainDiskDefForeachPath;
|
|
||||||
|
|
||||||
|
|
||||||
# domain_event.h
|
|
@ -1,273 +0,0 @@
|
|||||||
>From e2ebe4b785eccb930f36f400a22940fa9660a24b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Tue, 15 Jun 2010 16:40:47 +0100
|
|
||||||
Subject: [PATCH 06/10] Convert all disk backing store loops to shared helper API
|
|
||||||
|
|
||||||
Update the QEMU cgroups code, QEMU DAC security driver, SELinux
|
|
||||||
and AppArmour security drivers over to use the shared helper API
|
|
||||||
virDomainDiskDefForeachPath().
|
|
||||||
|
|
||||||
* src/qemu/qemu_driver.c, src/qemu/qemu_security_dac.c,
|
|
||||||
src/security/security_selinux.c, src/security/virt-aa-helper.c:
|
|
||||||
Convert over to use virDomainDiskDefForeachPath()
|
|
||||||
---
|
|
||||||
src/qemu/qemu_driver.c | 161 ++++++++++++++++----------------------
|
|
||||||
src/qemu/qemu_security_dac.c | 47 ++++--------
|
|
||||||
src/security/security_selinux.c | 67 +++++++----------
|
|
||||||
src/security/virt-aa-helper.c | 71 ++++++++----------
|
|
||||||
4 files changed, 142 insertions(+), 204 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_security_dac.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_security_dac.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_security_dac.c
|
|
||||||
@@ -99,47 +99,28 @@ err:
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
+qemuSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
|
|
||||||
+ const char *path,
|
|
||||||
+ unsigned int depth ATTRIBUTE_UNUSED,
|
|
||||||
+ void *opaque ATTRIBUTE_UNUSED)
|
|
||||||
+{
|
|
||||||
+ return qemuSecurityDACSetOwnership(path, driver->user, driver->group);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
qemuSecurityDACSetSecurityImageLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
|
||||||
virDomainDiskDefPtr disk)
|
|
||||||
|
|
||||||
{
|
|
||||||
- const char *path;
|
|
||||||
-
|
|
||||||
if (!driver->privileged || !driver->dynamicOwnership)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
- if (!disk->src)
|
|
||||||
- return 0;
|
|
||||||
-
|
|
||||||
- path = disk->src;
|
|
||||||
- do {
|
|
||||||
- virStorageFileMetadata meta;
|
|
||||||
- int ret;
|
|
||||||
-
|
|
||||||
- memset(&meta, 0, sizeof(meta));
|
|
||||||
-
|
|
||||||
- ret = virStorageFileGetMetadata(path,
|
|
||||||
- VIR_STORAGE_FILE_AUTO,
|
|
||||||
- &meta);
|
|
||||||
-
|
|
||||||
- if (path != disk->src)
|
|
||||||
- VIR_FREE(path);
|
|
||||||
- path = NULL;
|
|
||||||
-
|
|
||||||
- if (ret < 0)
|
|
||||||
- return -1;
|
|
||||||
-
|
|
||||||
- if (meta.backingStore != NULL &&
|
|
||||||
- qemuSecurityDACSetOwnership(meta.backingStore,
|
|
||||||
- driver->user, driver->group) < 0) {
|
|
||||||
- VIR_FREE(meta.backingStore);
|
|
||||||
- return -1;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- path = meta.backingStore;
|
|
||||||
- } while (path != NULL);
|
|
||||||
-
|
|
||||||
- return qemuSecurityDACSetOwnership(disk->src, driver->user, driver->group);
|
|
||||||
+ return virDomainDiskDefForeachPath(disk,
|
|
||||||
+ true,
|
|
||||||
+ false,
|
|
||||||
+ qemuSecurityDACSetSecurityFileLabel,
|
|
||||||
+ NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/security/security_selinux.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/security/security_selinux.c
|
|
||||||
+++ libvirt-0.8.1/src/security/security_selinux.c
|
|
||||||
@@ -411,56 +411,43 @@ SELinuxRestoreSecurityImageLabel(virDoma
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
+SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
|
|
||||||
+ const char *path,
|
|
||||||
+ unsigned int depth,
|
|
||||||
+ void *opaque)
|
|
||||||
+{
|
|
||||||
+ const virSecurityLabelDefPtr secdef = opaque;
|
|
||||||
+
|
|
||||||
+ if (depth == 0) {
|
|
||||||
+ if (disk->shared) {
|
|
||||||
+ return SELinuxSetFilecon(path, default_image_context);
|
|
||||||
+ } else if (disk->readonly) {
|
|
||||||
+ return SELinuxSetFilecon(path, default_content_context);
|
|
||||||
+ } else if (secdef->imagelabel) {
|
|
||||||
+ return SELinuxSetFilecon(path, secdef->imagelabel);
|
|
||||||
+ } else {
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ return SELinuxSetFilecon(path, default_content_context);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
SELinuxSetSecurityImageLabel(virDomainObjPtr vm,
|
|
||||||
virDomainDiskDefPtr disk)
|
|
||||||
|
|
||||||
{
|
|
||||||
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
|
||||||
- const char *path;
|
|
||||||
|
|
||||||
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
- if (!disk->src)
|
|
||||||
- return 0;
|
|
||||||
-
|
|
||||||
- path = disk->src;
|
|
||||||
- do {
|
|
||||||
- virStorageFileMetadata meta;
|
|
||||||
- int ret;
|
|
||||||
-
|
|
||||||
- memset(&meta, 0, sizeof(meta));
|
|
||||||
-
|
|
||||||
- ret = virStorageFileGetMetadata(path,
|
|
||||||
- VIR_STORAGE_FILE_AUTO,
|
|
||||||
- &meta);
|
|
||||||
-
|
|
||||||
- if (path != disk->src)
|
|
||||||
- VIR_FREE(path);
|
|
||||||
- path = NULL;
|
|
||||||
-
|
|
||||||
- if (ret < 0)
|
|
||||||
- break;
|
|
||||||
-
|
|
||||||
- if (meta.backingStore != NULL &&
|
|
||||||
- SELinuxSetFilecon(meta.backingStore,
|
|
||||||
- default_content_context) < 0) {
|
|
||||||
- VIR_FREE(meta.backingStore);
|
|
||||||
- return -1;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- path = meta.backingStore;
|
|
||||||
- } while (path != NULL);
|
|
||||||
-
|
|
||||||
- if (disk->shared) {
|
|
||||||
- return SELinuxSetFilecon(disk->src, default_image_context);
|
|
||||||
- } else if (disk->readonly) {
|
|
||||||
- return SELinuxSetFilecon(disk->src, default_content_context);
|
|
||||||
- } else if (secdef->imagelabel) {
|
|
||||||
- return SELinuxSetFilecon(disk->src, secdef->imagelabel);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return 0;
|
|
||||||
+ return virDomainDiskDefForeachPath(disk,
|
|
||||||
+ true,
|
|
||||||
+ false,
|
|
||||||
+ SELinuxSetSecurityFileLabel,
|
|
||||||
+ secdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/security/virt-aa-helper.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/security/virt-aa-helper.c
|
|
||||||
+++ libvirt-0.8.1/src/security/virt-aa-helper.c
|
|
||||||
@@ -36,7 +36,6 @@
|
|
||||||
#include "uuid.h"
|
|
||||||
#include "hostusb.h"
|
|
||||||
#include "pci.h"
|
|
||||||
-#include "storage_file.h"
|
|
||||||
|
|
||||||
static char *progname;
|
|
||||||
|
|
||||||
@@ -802,6 +801,28 @@ file_iterate_pci_cb(pciDevice *dev ATTRI
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
+add_file_path(virDomainDiskDefPtr disk,
|
|
||||||
+ const char *path,
|
|
||||||
+ unsigned int depth,
|
|
||||||
+ void *opaque)
|
|
||||||
+{
|
|
||||||
+ virBufferPtr buf = opaque;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ if (depth == 0) {
|
|
||||||
+ if (disk->readonly)
|
|
||||||
+ ret = vah_add_file(buf, path, "r");
|
|
||||||
+ else
|
|
||||||
+ ret = vah_add_file(buf, path, "rw");
|
|
||||||
+ } else {
|
|
||||||
+ ret = vah_add_file(buf, path, "r");
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
get_files(vahControl * ctl)
|
|
||||||
{
|
|
||||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
||||||
@@ -822,47 +843,15 @@ get_files(vahControl * ctl)
|
|
||||||
goto clean;
|
|
||||||
}
|
|
||||||
|
|
||||||
- for (i = 0; i < ctl->def->ndisks; i++)
|
|
||||||
- if (ctl->def->disks[i] && ctl->def->disks[i]->src) {
|
|
||||||
- int ret;
|
|
||||||
- const char *path;
|
|
||||||
-
|
|
||||||
- path = ctl->def->disks[i]->src;
|
|
||||||
- do {
|
|
||||||
- virStorageFileMetadata meta;
|
|
||||||
-
|
|
||||||
- memset(&meta, 0, sizeof(meta));
|
|
||||||
-
|
|
||||||
- ret = virStorageFileGetMetadata(path,
|
|
||||||
- VIR_STORAGE_FILE_AUTO,
|
|
||||||
- &meta);
|
|
||||||
-
|
|
||||||
- if (path != ctl->def->disks[i]->src)
|
|
||||||
- VIR_FREE(path);
|
|
||||||
- path = NULL;
|
|
||||||
-
|
|
||||||
- if (ret < 0) {
|
|
||||||
- vah_warning("could not open path, skipping");
|
|
||||||
- continue;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (meta.backingStore != NULL &&
|
|
||||||
- (ret = vah_add_file(&buf, meta.backingStore, "rw")) != 0) {
|
|
||||||
- VIR_FREE(meta.backingStore);
|
|
||||||
- goto clean;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- path = meta.backingStore;
|
|
||||||
- } while (path != NULL);
|
|
||||||
-
|
|
||||||
- if (ctl->def->disks[i]->readonly)
|
|
||||||
- ret = vah_add_file(&buf, ctl->def->disks[i]->src, "r");
|
|
||||||
- else
|
|
||||||
- ret = vah_add_file(&buf, ctl->def->disks[i]->src, "rw");
|
|
||||||
-
|
|
||||||
- if (ret != 0)
|
|
||||||
- goto clean;
|
|
||||||
- }
|
|
||||||
+ for (i = 0; i < ctl->def->ndisks; i++) {
|
|
||||||
+ int ret = virDomainDiskDefForeachPath(ctl->def->disks[i],
|
|
||||||
+ true,
|
|
||||||
+ false,
|
|
||||||
+ add_file_path,
|
|
||||||
+ &buf);
|
|
||||||
+ if (ret != 0)
|
|
||||||
+ goto clean;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
for (i = 0; i < ctl->def->nserials; i++)
|
|
||||||
if (ctl->def->serials[i] && ctl->def->serials[i]->data.file.path)
|
|
File diff suppressed because it is too large
Load Diff
@ -1,385 +0,0 @@
|
|||||||
>From e7db25186de8cb278f2b5f5c51e965129defaa11 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Tue, 15 Jun 2010 17:58:58 +0100
|
|
||||||
Subject: [PATCH 08/10] Disable all disk probing in QEMU driver & add config option to re-enable
|
|
||||||
|
|
||||||
Disk format probing is now disabled by default. A new config
|
|
||||||
option in /etc/qemu/qemu.conf will re-enable it for existing
|
|
||||||
deployments where this causes trouble
|
|
||||||
---
|
|
||||||
src/qemu/libvirtd_qemu.aug | 1 +
|
|
||||||
src/qemu/qemu.conf | 12 ++++++++++++
|
|
||||||
src/qemu/qemu_conf.c | 4 ++++
|
|
||||||
src/qemu/qemu_conf.h | 1 +
|
|
||||||
src/qemu/qemu_driver.c | 36 +++++++++++++++++++++++-------------
|
|
||||||
src/qemu/qemu_security_dac.c | 2 +-
|
|
||||||
src/qemu/test_libvirtd_qemu.aug | 4 ++++
|
|
||||||
src/security/security_apparmor.c | 12 ++++++++----
|
|
||||||
src/security/security_driver.c | 16 ++++++++++++++--
|
|
||||||
src/security/security_driver.h | 10 ++++++++--
|
|
||||||
src/security/security_selinux.c | 9 ++++++---
|
|
||||||
src/security/virt-aa-helper.c | 10 +++++++++-
|
|
||||||
tests/seclabeltest.c | 2 +-
|
|
||||||
13 files changed, 92 insertions(+), 27 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/qemu/libvirtd_qemu.aug
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/libvirtd_qemu.aug
|
|
||||||
+++ libvirt-0.8.1/src/qemu/libvirtd_qemu.aug
|
|
||||||
@@ -38,6 +38,7 @@ module Libvirtd_qemu =
|
|
||||||
| str_entry "save_image_format"
|
|
||||||
| str_entry "hugetlbfs_mount"
|
|
||||||
| bool_entry "relaxed_acs_check"
|
|
||||||
+ | bool_entry "allow_disk_format_probing"
|
|
||||||
|
|
||||||
(* Each enty in the config is one of the following three ... *)
|
|
||||||
let entry = vnc_entry
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu.conf
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu.conf
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu.conf
|
|
||||||
@@ -168,3 +168,15 @@
|
|
||||||
# be assigned to guests.
|
|
||||||
#
|
|
||||||
# relaxed_acs_check = 1
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+# If allow_disk_format_probing is enabled, libvirt will probe disk
|
|
||||||
+# images to attempt to identify their format, when not otherwise
|
|
||||||
+# specified in the XML. This is disabled by default.
|
|
||||||
+#
|
|
||||||
+# WARNING: Enabling probing is a security hole in almost all
|
|
||||||
+# deployments. It is strongly recommended that users update their
|
|
||||||
+# guest XML <disk> elements to include <driver type='XXXX'/>
|
|
||||||
+# elements instead of enabling this option.
|
|
||||||
+# allow_disk_format_probing = 1
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_conf.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_conf.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_conf.c
|
|
||||||
@@ -351,6 +351,10 @@ int qemudLoadDriverConfig(struct qemud_d
|
|
||||||
CHECK_TYPE ("relaxed_acs_check", VIR_CONF_LONG);
|
|
||||||
if (p) driver->relaxedACS = p->l;
|
|
||||||
|
|
||||||
+ p = virConfGetValue (conf, "allow_disk_format_probing");
|
|
||||||
+ CHECK_TYPE ("allow_disk_format_probing", VIR_CONF_LONG);
|
|
||||||
+ if (p) driver->allowDiskFormatProbing = p->l;
|
|
||||||
+
|
|
||||||
virConfFree (conf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_driver.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
@@ -1289,7 +1289,8 @@ qemudSecurityInit(struct qemud_driver *q
|
|
||||||
qemuSecurityDACSetDriver(qemud_drv);
|
|
||||||
|
|
||||||
ret = virSecurityDriverStartup(&security_drv,
|
|
||||||
- qemud_drv->securityDriverName);
|
|
||||||
+ qemud_drv->securityDriverName,
|
|
||||||
+ qemud_drv->allowDiskFormatProbing);
|
|
||||||
if (ret == -1) {
|
|
||||||
VIR_ERROR0(_("Failed to start security driver"));
|
|
||||||
return -1;
|
|
||||||
@@ -9145,8 +9146,15 @@ static int qemuDomainGetBlockInfo(virDom
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
- if ((format = virStorageFileProbeFormat(disk->src)) < 0)
|
|
||||||
+ if (driver->allowDiskFormatProbing) {
|
|
||||||
+ if ((format = virStorageFileProbeFormat(disk->src)) < 0)
|
|
||||||
+ goto cleanup;
|
|
||||||
+ } else {
|
|
||||||
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
+ _("no disk format for %s and probing is disabled"),
|
|
||||||
+ disk->src);
|
|
||||||
goto cleanup;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virStorageFileGetMetadataFromFD(path, fd,
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_security_dac.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_security_dac.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_security_dac.c
|
|
||||||
@@ -118,7 +118,7 @@ qemuSecurityDACSetSecurityImageLabel(vir
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return virDomainDiskDefForeachPath(disk,
|
|
||||||
- true,
|
|
||||||
+ driver->allowDiskFormatProbing,
|
|
||||||
false,
|
|
||||||
qemuSecurityDACSetSecurityFileLabel,
|
|
||||||
NULL);
|
|
||||||
Index: libvirt-0.8.1/src/qemu/test_libvirtd_qemu.aug
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/test_libvirtd_qemu.aug
|
|
||||||
+++ libvirt-0.8.1/src/qemu/test_libvirtd_qemu.aug
|
|
||||||
@@ -97,6 +97,8 @@ save_image_format = \"gzip\"
|
|
||||||
hugetlbfs_mount = \"/dev/hugepages\"
|
|
||||||
|
|
||||||
relaxed_acs_check = 1
|
|
||||||
+
|
|
||||||
+allow_disk_format_probing = 1
|
|
||||||
"
|
|
||||||
|
|
||||||
test Libvirtd_qemu.lns get conf =
|
|
||||||
@@ -204,3 +206,5 @@ relaxed_acs_check = 1
|
|
||||||
{ "hugetlbfs_mount" = "/dev/hugepages" }
|
|
||||||
{ "#empty" }
|
|
||||||
{ "relaxed_acs_check" = "1" }
|
|
||||||
+{ "#empty" }
|
|
||||||
+{ "allow_disk_format_probing" = "1" }
|
|
||||||
Index: libvirt-0.8.1/src/security/security_apparmor.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/security/security_apparmor.c
|
|
||||||
+++ libvirt-0.8.1/src/security/security_apparmor.c
|
|
||||||
@@ -157,6 +157,8 @@ load_profile(virSecurityDriverPtr drv,
|
|
||||||
char *xml = NULL;
|
|
||||||
int pipefd[2];
|
|
||||||
pid_t child;
|
|
||||||
+ const char *probe = virSecurityDriverGetAllowDiskFormatProbing(drv)
|
|
||||||
+ ? "1" : "0";
|
|
||||||
|
|
||||||
if (pipe(pipefd) < -1) {
|
|
||||||
virReportSystemError(errno, "%s", _("unable to create pipe"));
|
|
||||||
@@ -172,19 +174,19 @@ load_profile(virSecurityDriverPtr drv,
|
|
||||||
|
|
||||||
if (create) {
|
|
||||||
const char *const argv[] = {
|
|
||||||
- VIRT_AA_HELPER, "-c", "-u", profile, NULL
|
|
||||||
+ VIRT_AA_HELPER, "-p", probe, "-c", "-u", profile, NULL
|
|
||||||
};
|
|
||||||
ret = virExec(argv, NULL, NULL, &child,
|
|
||||||
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
|
|
||||||
} else if (disk && disk->src) {
|
|
||||||
const char *const argv[] = {
|
|
||||||
- VIRT_AA_HELPER, "-r", "-u", profile, "-f", disk->src, NULL
|
|
||||||
+ VIRT_AA_HELPER, "-p", probe, "-r", "-u", profile, "-f", disk->src, NULL
|
|
||||||
};
|
|
||||||
ret = virExec(argv, NULL, NULL, &child,
|
|
||||||
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
|
|
||||||
} else {
|
|
||||||
const char *const argv[] = {
|
|
||||||
- VIRT_AA_HELPER, "-r", "-u", profile, NULL
|
|
||||||
+ VIRT_AA_HELPER, "-p", probe, "-r", "-u", profile, NULL
|
|
||||||
};
|
|
||||||
ret = virExec(argv, NULL, NULL, &child,
|
|
||||||
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
|
|
||||||
@@ -312,9 +314,11 @@ AppArmorSecurityDriverProbe(void)
|
|
||||||
* currently not used.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
-AppArmorSecurityDriverOpen(virSecurityDriverPtr drv)
|
|
||||||
+AppArmorSecurityDriverOpen(virSecurityDriverPtr drv,
|
|
||||||
+ bool allowDiskFormatProbing)
|
|
||||||
{
|
|
||||||
virSecurityDriverSetDOI(drv, SECURITY_APPARMOR_VOID_DOI);
|
|
||||||
+ virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/security/security_driver.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/security/security_driver.c
|
|
||||||
+++ libvirt-0.8.1/src/security/security_driver.c
|
|
||||||
@@ -56,7 +56,8 @@ virSecurityDriverVerify(virDomainDefPtr
|
|
||||||
|
|
||||||
int
|
|
||||||
virSecurityDriverStartup(virSecurityDriverPtr *drv,
|
|
||||||
- const char *name)
|
|
||||||
+ const char *name,
|
|
||||||
+ bool allowDiskFormatProbing)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ virSecurityDriverStartup(virSecurityDriv
|
|
||||||
switch (tmp->probe()) {
|
|
||||||
case SECURITY_DRIVER_ENABLE:
|
|
||||||
virSecurityDriverInit(tmp);
|
|
||||||
- if (tmp->open(tmp) == -1) {
|
|
||||||
+ if (tmp->open(tmp, allowDiskFormatProbing) == -1) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
*drv = tmp;
|
|
||||||
@@ -125,3 +126,14 @@ virSecurityDriverGetModel(virSecurityDri
|
|
||||||
{
|
|
||||||
return drv->name;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv,
|
|
||||||
+ bool allowDiskFormatProbing)
|
|
||||||
+{
|
|
||||||
+ drv->_private.allowDiskFormatProbing = allowDiskFormatProbing;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv)
|
|
||||||
+{
|
|
||||||
+ return drv->_private.allowDiskFormatProbing;
|
|
||||||
+}
|
|
||||||
Index: libvirt-0.8.1/src/security/security_driver.h
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/security/security_driver.h
|
|
||||||
+++ libvirt-0.8.1/src/security/security_driver.h
|
|
||||||
@@ -33,7 +33,8 @@ typedef struct _virSecurityDriverState v
|
|
||||||
typedef virSecurityDriverState *virSecurityDriverStatePtr;
|
|
||||||
|
|
||||||
typedef virSecurityDriverStatus (*virSecurityDriverProbe) (void);
|
|
||||||
-typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv);
|
|
||||||
+typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv,
|
|
||||||
+ bool allowDiskFormatProbing);
|
|
||||||
typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityDriverPtr drv,
|
|
||||||
virDomainObjPtr vm,
|
|
||||||
virDomainDiskDefPtr disk);
|
|
||||||
@@ -94,12 +95,14 @@ struct _virSecurityDriver {
|
|
||||||
*/
|
|
||||||
struct {
|
|
||||||
char doi[VIR_SECURITY_DOI_BUFLEN];
|
|
||||||
+ bool allowDiskFormatProbing;
|
|
||||||
} _private;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Global methods */
|
|
||||||
int virSecurityDriverStartup(virSecurityDriverPtr *drv,
|
|
||||||
- const char *name);
|
|
||||||
+ const char *name,
|
|
||||||
+ bool allowDiskFormatProbing);
|
|
||||||
|
|
||||||
int
|
|
||||||
virSecurityDriverVerify(virDomainDefPtr def);
|
|
||||||
@@ -112,7 +115,10 @@ virSecurityDriverVerify(virDomainDefPtr
|
|
||||||
void virSecurityDriverInit(virSecurityDriverPtr drv);
|
|
||||||
int virSecurityDriverSetDOI(virSecurityDriverPtr drv,
|
|
||||||
const char *doi);
|
|
||||||
+void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv,
|
|
||||||
+ bool allowDiskFormatProbing);
|
|
||||||
const char *virSecurityDriverGetDOI(virSecurityDriverPtr drv);
|
|
||||||
const char *virSecurityDriverGetModel(virSecurityDriverPtr drv);
|
|
||||||
+bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv);
|
|
||||||
|
|
||||||
#endif /* __VIR_SECURITY_H__ */
|
|
||||||
Index: libvirt-0.8.1/src/security/security_selinux.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/security/security_selinux.c
|
|
||||||
+++ libvirt-0.8.1/src/security/security_selinux.c
|
|
||||||
@@ -266,13 +266,15 @@ SELinuxSecurityDriverProbe(void)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
-SELinuxSecurityDriverOpen(virSecurityDriverPtr drv)
|
|
||||||
+SELinuxSecurityDriverOpen(virSecurityDriverPtr drv,
|
|
||||||
+ bool allowDiskFormatProbing)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Where will the DOI come from? SELinux configuration, or qemu
|
|
||||||
* configuration? For the moment, we'll just set it to "0".
|
|
||||||
*/
|
|
||||||
virSecurityDriverSetDOI(drv, SECURITY_SELINUX_VOID_DOI);
|
|
||||||
+ virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing);
|
|
||||||
return SELinuxInitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -438,18 +440,19 @@ SELinuxSetSecurityFileLabel(virDomainDis
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
-SELinuxSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
|
|
||||||
+SELinuxSetSecurityImageLabel(virSecurityDriverPtr drv,
|
|
||||||
virDomainObjPtr vm,
|
|
||||||
virDomainDiskDefPtr disk)
|
|
||||||
|
|
||||||
{
|
|
||||||
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
|
||||||
+ bool allowDiskFormatProbing = virSecurityDriverGetAllowDiskFormatProbing(drv);
|
|
||||||
|
|
||||||
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return virDomainDiskDefForeachPath(disk,
|
|
||||||
- true,
|
|
||||||
+ allowDiskFormatProbing,
|
|
||||||
false,
|
|
||||||
SELinuxSetSecurityFileLabel,
|
|
||||||
secdef);
|
|
||||||
Index: libvirt-0.8.1/src/security/virt-aa-helper.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/security/virt-aa-helper.c
|
|
||||||
+++ libvirt-0.8.1/src/security/virt-aa-helper.c
|
|
||||||
@@ -40,6 +40,7 @@
|
|
||||||
static char *progname;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
+ bool allowDiskFormatProbing;
|
|
||||||
char uuid[PROFILE_NAME_SIZE]; /* UUID of vm */
|
|
||||||
bool dryrun; /* dry run */
|
|
||||||
char cmd; /* 'c' create
|
|
||||||
@@ -845,7 +846,7 @@ get_files(vahControl * ctl)
|
|
||||||
|
|
||||||
for (i = 0; i < ctl->def->ndisks; i++) {
|
|
||||||
int ret = virDomainDiskDefForeachPath(ctl->def->disks[i],
|
|
||||||
- true,
|
|
||||||
+ ctl->allowDiskFormatProbing,
|
|
||||||
false,
|
|
||||||
add_file_path,
|
|
||||||
&buf);
|
|
||||||
@@ -944,6 +945,7 @@ vahParseArgv(vahControl * ctl, int argc,
|
|
||||||
{
|
|
||||||
int arg, idx = 0;
|
|
||||||
struct option opt[] = {
|
|
||||||
+ {"probing", 1, 0, 'p' },
|
|
||||||
{"add", 0, 0, 'a'},
|
|
||||||
{"create", 0, 0, 'c'},
|
|
||||||
{"dryrun", 0, 0, 'd'},
|
|
||||||
@@ -992,6 +994,12 @@ vahParseArgv(vahControl * ctl, int argc,
|
|
||||||
PROFILE_NAME_SIZE) == NULL)
|
|
||||||
vah_error(ctl, 1, "error copying UUID");
|
|
||||||
break;
|
|
||||||
+ case 'p':
|
|
||||||
+ if (STREQ(optarg, "1"))
|
|
||||||
+ ctl->allowDiskFormatProbing = true;
|
|
||||||
+ else
|
|
||||||
+ ctl->allowDiskFormatProbing = false;
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
vah_error(ctl, 1, "unsupported option");
|
|
||||||
break;
|
|
||||||
Index: libvirt-0.8.1/tests/seclabeltest.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/tests/seclabeltest.c
|
|
||||||
+++ libvirt-0.8.1/tests/seclabeltest.c
|
|
||||||
@@ -15,7 +15,7 @@ main (int argc ATTRIBUTE_UNUSED, char **
|
|
||||||
const char *doi, *model;
|
|
||||||
virSecurityDriverPtr security_drv;
|
|
||||||
|
|
||||||
- ret = virSecurityDriverStartup (&security_drv, "selinux");
|
|
||||||
+ ret = virSecurityDriverStartup (&security_drv, "selinux", false);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "Failed to start security driver");
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_conf.h
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_conf.h
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_conf.h
|
|
||||||
@@ -137,6 +137,7 @@ struct qemud_driver {
|
|
||||||
ebtablesContext *ebtables;
|
|
||||||
|
|
||||||
unsigned int relaxedACS : 1;
|
|
||||||
+ unsigned int allowDiskFormatProbing : 1;
|
|
||||||
|
|
||||||
virCapsPtr caps;
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/tests/secaatest.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/tests/secaatest.c
|
|
||||||
+++ libvirt-0.8.1/tests/secaatest.c
|
|
||||||
@@ -15,7 +15,7 @@ main (int argc ATTRIBUTE_UNUSED, char **
|
|
||||||
const char *doi, *model;
|
|
||||||
virSecurityDriverPtr security_drv;
|
|
||||||
|
|
||||||
- ret = virSecurityDriverStartup (&security_drv, "apparmor");
|
|
||||||
+ ret = virSecurityDriverStartup (&security_drv, "apparmor", false);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "Failed to start security driver");
|
|
@ -1,110 +0,0 @@
|
|||||||
>From f087f0656f882be305783e24d55921b57fbbcb97 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Mon, 14 Jun 2010 16:08:55 +0100
|
|
||||||
Subject: [PATCH 09/10] Add ability to set a default driver name/type when parsing disks
|
|
||||||
|
|
||||||
Record a default driver name/type in capabilities struct. Use this
|
|
||||||
when parsing disks if value is not set in XML config.
|
|
||||||
|
|
||||||
* src/conf/capabilities.h: Record default driver name/type for disks
|
|
||||||
* src/conf/domain_conf.c: Fallback to default driver name/type
|
|
||||||
when parsing disks
|
|
||||||
* src/qemu/qemu_driver.c: Set default driver name/type to raw
|
|
||||||
---
|
|
||||||
src/conf/capabilities.h | 2 ++
|
|
||||||
src/conf/domain_conf.c | 21 ++++++++++++++++++---
|
|
||||||
src/qemu/qemu_driver.c | 8 ++++++++
|
|
||||||
3 files changed, 28 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/conf/capabilities.h
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/conf/capabilities.h
|
|
||||||
+++ libvirt-0.8.1/src/conf/capabilities.h
|
|
||||||
@@ -120,6 +120,8 @@ struct _virCaps {
|
|
||||||
virCapsGuestPtr *guests;
|
|
||||||
unsigned char macPrefix[VIR_MAC_PREFIX_BUFLEN];
|
|
||||||
unsigned int emulatorRequired : 1;
|
|
||||||
+ const char *defaultDiskDriverName;
|
|
||||||
+ const char *defaultDiskDriverType;
|
|
||||||
void *(*privateDataAllocFunc)(void);
|
|
||||||
void (*privateDataFreeFunc)(void *);
|
|
||||||
int (*privateDataXMLFormat)(virBufferPtr, void *);
|
|
||||||
Index: libvirt-0.8.1/src/conf/domain_conf.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/conf/domain_conf.c
|
|
||||||
+++ libvirt-0.8.1/src/conf/domain_conf.c
|
|
||||||
@@ -1366,7 +1366,8 @@ virDomainDiskDefAssignAddress(virDomainD
|
|
||||||
* @param node XML nodeset to parse for disk definition
|
|
||||||
*/
|
|
||||||
static virDomainDiskDefPtr
|
|
||||||
-virDomainDiskDefParseXML(xmlNodePtr node,
|
|
||||||
+virDomainDiskDefParseXML(virCapsPtr caps,
|
|
||||||
+ xmlNodePtr node,
|
|
||||||
int flags) {
|
|
||||||
virDomainDiskDefPtr def;
|
|
||||||
xmlNodePtr cur;
|
|
||||||
@@ -1595,6 +1596,16 @@ virDomainDiskDefParseXML(xmlNodePtr node
|
|
||||||
def->serial = serial;
|
|
||||||
serial = NULL;
|
|
||||||
|
|
||||||
+ if (!def->driverType &&
|
|
||||||
+ caps->defaultDiskDriverType &&
|
|
||||||
+ !(def->driverType = strdup(caps->defaultDiskDriverType)))
|
|
||||||
+ goto no_memory;
|
|
||||||
+
|
|
||||||
+ if (!def->driverName &&
|
|
||||||
+ caps->defaultDiskDriverName &&
|
|
||||||
+ !(def->driverName = strdup(caps->defaultDiskDriverName)))
|
|
||||||
+ goto no_memory;
|
|
||||||
+
|
|
||||||
if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE
|
|
||||||
&& virDomainDiskDefAssignAddress(def) < 0)
|
|
||||||
goto error;
|
|
||||||
@@ -1615,6 +1626,9 @@ cleanup:
|
|
||||||
|
|
||||||
return def;
|
|
||||||
|
|
||||||
+no_memory:
|
|
||||||
+ virReportOOMError();
|
|
||||||
+
|
|
||||||
error:
|
|
||||||
virDomainDiskDefFree(def);
|
|
||||||
def = NULL;
|
|
||||||
@@ -3521,7 +3535,7 @@ virDomainDeviceDefPtr virDomainDeviceDef
|
|
||||||
|
|
||||||
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
|
||||||
dev->type = VIR_DOMAIN_DEVICE_DISK;
|
|
||||||
- if (!(dev->data.disk = virDomainDiskDefParseXML(node, flags)))
|
|
||||||
+ if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, flags)))
|
|
||||||
goto error;
|
|
||||||
} else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) {
|
|
||||||
dev->type = VIR_DOMAIN_DEVICE_FS;
|
|
||||||
@@ -4028,7 +4042,8 @@ static virDomainDefPtr virDomainDefParse
|
|
||||||
if (n && VIR_ALLOC_N(def->disks, n) < 0)
|
|
||||||
goto no_memory;
|
|
||||||
for (i = 0 ; i < n ; i++) {
|
|
||||||
- virDomainDiskDefPtr disk = virDomainDiskDefParseXML(nodes[i],
|
|
||||||
+ virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps,
|
|
||||||
+ nodes[i],
|
|
||||||
flags);
|
|
||||||
if (!disk)
|
|
||||||
goto error;
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_driver.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
@@ -1324,6 +1324,14 @@ qemuCreateCapabilities(virCapsPtr oldcap
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (driver->allowDiskFormatProbing) {
|
|
||||||
+ caps->defaultDiskDriverName = NULL;
|
|
||||||
+ caps->defaultDiskDriverType = NULL;
|
|
||||||
+ } else {
|
|
||||||
+ caps->defaultDiskDriverName = "qemu";
|
|
||||||
+ caps->defaultDiskDriverType = "raw";
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Domain XML parser hooks */
|
|
||||||
caps->privateDataAllocFunc = qemuDomainObjPrivateAlloc;
|
|
||||||
caps->privateDataFreeFunc = qemuDomainObjPrivateFree;
|
|
@ -1,288 +0,0 @@
|
|||||||
>From 6883117e3c6a6cabd760b6e6a468b69ad7b02839 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Wed, 16 Jun 2010 14:14:05 +0100
|
|
||||||
Subject: [PATCH 10/10] Rewrite qemu-img backing store format handling
|
|
||||||
|
|
||||||
When creating qcow2 files with a backing store, it is important
|
|
||||||
to set an explicit format to prevent QEMU probing. The storage
|
|
||||||
backend was only doing this if it found a 'kvm-img' binary. This
|
|
||||||
is wrong because plenty of kvm-img binaries don't support an
|
|
||||||
explicit format, and plenty of 'qemu-img' binaries do support
|
|
||||||
a format. The result was that most qcow2 files were not getting
|
|
||||||
a backing store format.
|
|
||||||
|
|
||||||
This patch runs 'qemu-img -h' to check for the two support
|
|
||||||
argument formats
|
|
||||||
|
|
||||||
'-o backing_format=raw'
|
|
||||||
'-F raw'
|
|
||||||
|
|
||||||
and use whichever option it finds
|
|
||||||
|
|
||||||
* src/storage/storage_backend.c: Query binary to determine
|
|
||||||
how to set the backing store format
|
|
||||||
---
|
|
||||||
src/storage/storage_backend.c | 214 +++++++++++++++++++++++++++++------------
|
|
||||||
1 files changed, 152 insertions(+), 62 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/storage/storage_backend.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/storage/storage_backend.c
|
|
||||||
+++ libvirt-0.8.1/src/storage/storage_backend.c
|
|
||||||
@@ -563,6 +563,69 @@ static int virStorageBackendCreateExecCo
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+enum {
|
|
||||||
+ QEMU_IMG_BACKING_FORMAT_NONE = 0,
|
|
||||||
+ QEMU_IMG_BACKING_FORMAT_FLAG,
|
|
||||||
+ QEMU_IMG_BACKING_FORMAT_OPTIONS,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
|
|
||||||
+{
|
|
||||||
+ const char *const qemuarg[] = { qemuimg, "-h", NULL };
|
|
||||||
+ const char *const qemuenv[] = { "LC_ALL=C", NULL };
|
|
||||||
+ pid_t child = 0;
|
|
||||||
+ int status;
|
|
||||||
+ int newstdout = -1;
|
|
||||||
+ char *help = NULL;
|
|
||||||
+ enum { MAX_HELP_OUTPUT_SIZE = 1024*8 };
|
|
||||||
+ int len;
|
|
||||||
+ char *start;
|
|
||||||
+ char *end;
|
|
||||||
+ char *tmp;
|
|
||||||
+ int ret = -1;
|
|
||||||
+
|
|
||||||
+ if (virExec(qemuarg, qemuenv, NULL,
|
|
||||||
+ &child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ if ((len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help)) < 0) {
|
|
||||||
+ virReportSystemError(errno,
|
|
||||||
+ _("Unable to read '%s -h' output"),
|
|
||||||
+ qemuimg);
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ start = strstr(help, " create ");
|
|
||||||
+ end = strstr(start, "\n");
|
|
||||||
+ if ((tmp = strstr(start, "-F fmt")) && tmp < end)
|
|
||||||
+ ret = QEMU_IMG_BACKING_FORMAT_FLAG;
|
|
||||||
+ else if ((tmp = strstr(start, "[-o options]")) && tmp < end)
|
|
||||||
+ ret = QEMU_IMG_BACKING_FORMAT_OPTIONS;
|
|
||||||
+ else
|
|
||||||
+ ret = QEMU_IMG_BACKING_FORMAT_NONE;
|
|
||||||
+
|
|
||||||
+cleanup:
|
|
||||||
+ VIR_FREE(help);
|
|
||||||
+ close(newstdout);
|
|
||||||
+rewait:
|
|
||||||
+ if (child) {
|
|
||||||
+ if (waitpid(child, &status, 0) != child) {
|
|
||||||
+ if (errno == EINTR)
|
|
||||||
+ goto rewait;
|
|
||||||
+
|
|
||||||
+ VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
|
|
||||||
+ WEXITSTATUS(status), (unsigned long)child);
|
|
||||||
+ }
|
|
||||||
+ if (WEXITSTATUS(status) != 0) {
|
|
||||||
+ VIR_WARN("Unexpected exit status '%d', qemu probably failed",
|
|
||||||
+ WEXITSTATUS(status));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
static int
|
|
||||||
virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|
||||||
virStoragePoolObjPtr pool,
|
|
||||||
@@ -570,10 +633,9 @@ virStorageBackendCreateQemuImg(virConnec
|
|
||||||
virStorageVolDefPtr inputvol,
|
|
||||||
unsigned int flags ATTRIBUTE_UNUSED)
|
|
||||||
{
|
|
||||||
- int ret;
|
|
||||||
+ int ret = -1;
|
|
||||||
char size[100];
|
|
||||||
char *create_tool;
|
|
||||||
- short use_kvmimg;
|
|
||||||
|
|
||||||
const char *type = virStorageFileFormatTypeToString(vol->target.format);
|
|
||||||
const char *backingType = vol->backingStore.path ?
|
|
||||||
@@ -584,41 +646,10 @@ virStorageBackendCreateQemuImg(virConnec
|
|
||||||
const char *inputPath = inputvol ? inputvol->target.path : NULL;
|
|
||||||
/* Treat input block devices as 'raw' format */
|
|
||||||
const char *inputType = inputPath ?
|
|
||||||
- virStorageFileFormatTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ? VIR_STORAGE_FILE_RAW : inputvol->target.format) :
|
|
||||||
- NULL;
|
|
||||||
-
|
|
||||||
- const char **imgargv;
|
|
||||||
- /* The extra NULL field is for indicating encryption (-e). */
|
|
||||||
- const char *imgargvnormal[] = {
|
|
||||||
- NULL, "create",
|
|
||||||
- "-f", type,
|
|
||||||
- vol->target.path,
|
|
||||||
- size,
|
|
||||||
- NULL,
|
|
||||||
- NULL
|
|
||||||
- };
|
|
||||||
- /* Extra NULL fields are for including "backingType" when using
|
|
||||||
- * kvm-img (-F backingType), and for indicating encryption (-e).
|
|
||||||
- */
|
|
||||||
- const char *imgargvbacking[] = {
|
|
||||||
- NULL, "create",
|
|
||||||
- "-f", type,
|
|
||||||
- "-b", vol->backingStore.path,
|
|
||||||
- vol->target.path,
|
|
||||||
- size,
|
|
||||||
- NULL,
|
|
||||||
- NULL,
|
|
||||||
- NULL,
|
|
||||||
- NULL
|
|
||||||
- };
|
|
||||||
- const char *convargv[] = {
|
|
||||||
- NULL, "convert",
|
|
||||||
- "-f", inputType,
|
|
||||||
- "-O", type,
|
|
||||||
- inputPath,
|
|
||||||
- vol->target.path,
|
|
||||||
- NULL,
|
|
||||||
- };
|
|
||||||
+ virStorageFileFormatTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ?
|
|
||||||
+ VIR_STORAGE_FILE_RAW :
|
|
||||||
+ inputvol->target.format) :
|
|
||||||
+ NULL;
|
|
||||||
|
|
||||||
if (type == NULL) {
|
|
||||||
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
@@ -692,44 +723,103 @@ virStorageBackendCreateQemuImg(virConnec
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- if ((create_tool = virFindFileInPath("kvm-img")) != NULL)
|
|
||||||
- use_kvmimg = 1;
|
|
||||||
- else if ((create_tool = virFindFileInPath("qemu-img")) != NULL)
|
|
||||||
- use_kvmimg = 0;
|
|
||||||
- else {
|
|
||||||
+ /* Size in KB */
|
|
||||||
+ snprintf(size, sizeof(size), "%lluK", vol->capacity/1024);
|
|
||||||
+
|
|
||||||
+ /* KVM is usually ahead of qemu on features, so try that first */
|
|
||||||
+ create_tool = virFindFileInPath("kvm-img");
|
|
||||||
+ if (!create_tool)
|
|
||||||
+ create_tool = virFindFileInPath("qemu-img");
|
|
||||||
+
|
|
||||||
+ if (!create_tool) {
|
|
||||||
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("unable to find kvm-img or qemu-img"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputvol) {
|
|
||||||
- convargv[0] = create_tool;
|
|
||||||
- imgargv = convargv;
|
|
||||||
+ const char *imgargv[] = {
|
|
||||||
+ create_tool,
|
|
||||||
+ "convert",
|
|
||||||
+ "-f", inputType,
|
|
||||||
+ "-O", type,
|
|
||||||
+ inputPath,
|
|
||||||
+ vol->target.path,
|
|
||||||
+ NULL,
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
|
|
||||||
} else if (vol->backingStore.path) {
|
|
||||||
- imgargvbacking[0] = create_tool;
|
|
||||||
- if (use_kvmimg) {
|
|
||||||
- imgargvbacking[6] = "-F";
|
|
||||||
- imgargvbacking[7] = backingType;
|
|
||||||
- imgargvbacking[8] = vol->target.path;
|
|
||||||
- imgargvbacking[9] = size;
|
|
||||||
+ const char *imgargv[] = {
|
|
||||||
+ create_tool,
|
|
||||||
+ "create",
|
|
||||||
+ "-f", type,
|
|
||||||
+ "-b", vol->backingStore.path,
|
|
||||||
+ NULL,
|
|
||||||
+ NULL,
|
|
||||||
+ NULL,
|
|
||||||
+ NULL,
|
|
||||||
+ NULL,
|
|
||||||
+ NULL
|
|
||||||
+ };
|
|
||||||
+ int imgformat = virStorageBackendQEMUImgBackingFormat(create_tool);
|
|
||||||
+ char *optflag = NULL;
|
|
||||||
+ if (imgformat < 0)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ switch (imgformat) {
|
|
||||||
+ case QEMU_IMG_BACKING_FORMAT_FLAG:
|
|
||||||
+ imgargv[6] = "-F";
|
|
||||||
+ imgargv[7] = backingType;
|
|
||||||
+ imgargv[8] = vol->target.path;
|
|
||||||
+ imgargv[9] = size;
|
|
||||||
+ if (vol->target.encryption != NULL)
|
|
||||||
+ imgargv[10] = "-e";
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case QEMU_IMG_BACKING_FORMAT_OPTIONS:
|
|
||||||
+ if (virAsprintf(&optflag, "backing_fmt=%s", backingType) < 0) {
|
|
||||||
+ virReportOOMError();
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+ imgargv[6] = "-o";
|
|
||||||
+ imgargv[7] = optflag;
|
|
||||||
+ imgargv[8] = vol->target.path;
|
|
||||||
+ imgargv[9] = size;
|
|
||||||
+ if (vol->target.encryption != NULL)
|
|
||||||
+ imgargv[10] = "-e";
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ default:
|
|
||||||
+ VIR_INFO("Unable to set backing store format for %s with %s",
|
|
||||||
+ vol->target.path, create_tool);
|
|
||||||
+ imgargv[6] = vol->target.path;
|
|
||||||
+ imgargv[7] = size;
|
|
||||||
if (vol->target.encryption != NULL)
|
|
||||||
- imgargvbacking[10] = "-e";
|
|
||||||
- } else if (vol->target.encryption != NULL)
|
|
||||||
- imgargvbacking[8] = "-e";
|
|
||||||
- imgargv = imgargvbacking;
|
|
||||||
+ imgargv[8] = "-e";
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
|
|
||||||
+ VIR_FREE(optflag);
|
|
||||||
} else {
|
|
||||||
- imgargvnormal[0] = create_tool;
|
|
||||||
- imgargv = imgargvnormal;
|
|
||||||
+ /* The extra NULL field is for indicating encryption (-e). */
|
|
||||||
+ const char *imgargv[] = {
|
|
||||||
+ create_tool,
|
|
||||||
+ "create",
|
|
||||||
+ "-f", type,
|
|
||||||
+ vol->target.path,
|
|
||||||
+ size,
|
|
||||||
+ NULL,
|
|
||||||
+ NULL
|
|
||||||
+ };
|
|
||||||
if (vol->target.encryption != NULL)
|
|
||||||
imgargv[6] = "-e";
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
|
|
||||||
- /* Size in KB */
|
|
||||||
- snprintf(size, sizeof(size), "%lluK", vol->capacity/1024);
|
|
||||||
+ ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
|
|
||||||
- VIR_FREE(imgargv[0]);
|
|
||||||
+ cleanup:
|
|
||||||
+ VIR_FREE(create_tool);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,262 +0,0 @@
|
|||||||
From 02318d5d46e1952294c20b41427dea124cbebb0a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel P. Berrange <berrange@redhat.com>
|
|
||||||
Date: Thu, 10 Jun 2010 12:50:38 -0400
|
|
||||||
Subject: [PATCH] Apply a source port mapping to virtual network masquerading
|
|
||||||
|
|
||||||
IPtables will seek to preserve the source port unchanged when
|
|
||||||
doing masquerading, if possible. NFS has a pseudo-security
|
|
||||||
option where it checks for the source port <= 1023 before
|
|
||||||
allowing a mount request. If an admin has used this to make the
|
|
||||||
host OS trusted for mounts, the default iptables behaviour will
|
|
||||||
potentially allow NAT'd guests access too. This needs to be
|
|
||||||
stopped.
|
|
||||||
|
|
||||||
With this change, the iptables -t nat -L -n -v rules for the
|
|
||||||
default network will be
|
|
||||||
|
|
||||||
Chain POSTROUTING (policy ACCEPT 95 packets, 9163 bytes)
|
|
||||||
pkts bytes target prot opt in out source destination
|
|
||||||
14 840 MASQUERADE tcp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
|
|
||||||
75 5752 MASQUERADE udp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
|
|
||||||
0 0 MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24
|
|
||||||
|
|
||||||
* src/network/bridge_driver.c: Add masquerade rules for TCP
|
|
||||||
and UDP protocols
|
|
||||||
* src/util/iptables.c, src/util/iptables.c: Add source port
|
|
||||||
mappings for TCP & UDP protocols when masquerading.
|
|
||||||
---
|
|
||||||
src/network/bridge_driver.c | 73 ++++++++++++++++++++++++++++++++++++++++--
|
|
||||||
src/util/iptables.c | 70 +++++++++++++++++++++++++++++------------
|
|
||||||
src/util/iptables.h | 6 ++-
|
|
||||||
3 files changed, 122 insertions(+), 27 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/network/bridge_driver.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/network/bridge_driver.c
|
|
||||||
+++ libvirt-0.8.1/src/network/bridge_driver.c
|
|
||||||
@@ -638,18 +638,75 @@ networkAddMasqueradingIptablesRules(stru
|
|
||||||
goto masqerr2;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * Enable masquerading.
|
|
||||||
+ *
|
|
||||||
+ * We need to end up with 3 rules in the table in this order
|
|
||||||
+ *
|
|
||||||
+ * 1. protocol=tcp with sport mapping restricton
|
|
||||||
+ * 2. protocol=udp with sport mapping restricton
|
|
||||||
+ * 3. generic any protocol
|
|
||||||
+ *
|
|
||||||
+ * The sport mappings are required, because default IPtables
|
|
||||||
+ * MASQUERADE is maintain port number unchanged where possible.
|
|
||||||
+ *
|
|
||||||
+ * NFS can be configured to only "trust" port numbers < 1023.
|
|
||||||
+ *
|
|
||||||
+ * Guests using NAT thus need to be prevented from having port
|
|
||||||
+ * numbers < 1023, otherwise they can bypass the NFS "security"
|
|
||||||
+ * check on the source port number.
|
|
||||||
+ *
|
|
||||||
+ * Since we use '--insert' to add rules to the header of the
|
|
||||||
+ * chain, we actually need to add them in the reverse of the
|
|
||||||
+ * order just mentioned !
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+ /* First the generic masquerade rule for other protocols */
|
|
||||||
/* enable masquerading */
|
|
||||||
if ((err = iptablesAddForwardMasquerade(driver->iptables,
|
|
||||||
network->def->network,
|
|
||||||
- network->def->forwardDev))) {
|
|
||||||
+ network->def->forwardDev,
|
|
||||||
+ NULL))) {
|
|
||||||
virReportSystemError(err,
|
|
||||||
_("failed to add iptables rule to enable masquerading to '%s'\n"),
|
|
||||||
network->def->forwardDev ? network->def->forwardDev : NULL);
|
|
||||||
goto masqerr3;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* UDP with a source port restriction */
|
|
||||||
+ if ((err = iptablesAddForwardMasquerade(driver->iptables,
|
|
||||||
+ network->def->network,
|
|
||||||
+ network->def->forwardDev,
|
|
||||||
+ "udp"))) {
|
|
||||||
+ virReportSystemError(err,
|
|
||||||
+ _("failed to add iptables rule to enable UDP masquerading to '%s'"),
|
|
||||||
+ network->def->forwardDev ? network->def->forwardDev : NULL);
|
|
||||||
+ goto masqerr4;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* TCP with a source port restriction */
|
|
||||||
+ if ((err = iptablesAddForwardMasquerade(driver->iptables,
|
|
||||||
+ network->def->network,
|
|
||||||
+ network->def->forwardDev,
|
|
||||||
+ "tcp"))) {
|
|
||||||
+ virReportSystemError(err,
|
|
||||||
+ _("failed to add iptables rule to enable TCP masquerading to '%s'"),
|
|
||||||
+ network->def->forwardDev ? network->def->forwardDev : NULL);
|
|
||||||
+ goto masqerr5;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
+ masqerr5:
|
|
||||||
+ iptablesRemoveForwardMasquerade(driver->iptables,
|
|
||||||
+ network->def->network,
|
|
||||||
+ network->def->forwardDev,
|
|
||||||
+ "udp");
|
|
||||||
+ masqerr4:
|
|
||||||
+ iptablesRemoveForwardMasquerade(driver->iptables,
|
|
||||||
+ network->def->network,
|
|
||||||
+ network->def->forwardDev,
|
|
||||||
+ NULL);
|
|
||||||
masqerr3:
|
|
||||||
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
|
||||||
network->def->network,
|
|
||||||
@@ -801,8 +858,17 @@ networkRemoveIptablesRules(struct networ
|
|
||||||
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
|
|
||||||
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
|
|
||||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
||||||
- network->def->network,
|
|
||||||
- network->def->forwardDev);
|
|
||||||
+ network->def->network,
|
|
||||||
+ network->def->forwardDev,
|
|
||||||
+ "tcp");
|
|
||||||
+ iptablesRemoveForwardMasquerade(driver->iptables,
|
|
||||||
+ network->def->network,
|
|
||||||
+ network->def->forwardDev,
|
|
||||||
+ "udp");
|
|
||||||
+ iptablesRemoveForwardMasquerade(driver->iptables,
|
|
||||||
+ network->def->network,
|
|
||||||
+ network->def->forwardDev,
|
|
||||||
+ NULL);
|
|
||||||
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
|
||||||
network->def->network,
|
|
||||||
network->def->bridge,
|
|
||||||
Index: libvirt-0.8.1/src/util/iptables.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/iptables.c
|
|
||||||
+++ libvirt-0.8.1/src/util/iptables.c
|
|
||||||
@@ -692,25 +692,49 @@ iptablesRemoveForwardRejectIn(iptablesCo
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
iptablesForwardMasquerade(iptablesContext *ctx,
|
|
||||||
- const char *network,
|
|
||||||
- const char *physdev,
|
|
||||||
- int action)
|
|
||||||
+ const char *network,
|
|
||||||
+ const char *physdev,
|
|
||||||
+ const char *protocol,
|
|
||||||
+ int action)
|
|
||||||
{
|
|
||||||
- if (physdev && physdev[0]) {
|
|
||||||
- return iptablesAddRemoveRule(ctx->nat_postrouting,
|
|
||||||
- action,
|
|
||||||
- "--source", network,
|
|
||||||
- "!", "--destination", network,
|
|
||||||
- "--out-interface", physdev,
|
|
||||||
- "--jump", "MASQUERADE",
|
|
||||||
- NULL);
|
|
||||||
+ if (protocol && protocol[0]) {
|
|
||||||
+ if (physdev && physdev[0]) {
|
|
||||||
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
|
|
||||||
+ action,
|
|
||||||
+ "--source", network,
|
|
||||||
+ "-p", protocol,
|
|
||||||
+ "!", "--destination", network,
|
|
||||||
+ "--out-interface", physdev,
|
|
||||||
+ "--jump", "MASQUERADE",
|
|
||||||
+ "--to-ports", "1024-65535",
|
|
||||||
+ NULL);
|
|
||||||
+ } else {
|
|
||||||
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
|
|
||||||
+ action,
|
|
||||||
+ "--source", network,
|
|
||||||
+ "-p", protocol,
|
|
||||||
+ "!", "--destination", network,
|
|
||||||
+ "--jump", "MASQUERADE",
|
|
||||||
+ "--to-ports", "1024-65535",
|
|
||||||
+ NULL);
|
|
||||||
+ }
|
|
||||||
} else {
|
|
||||||
- return iptablesAddRemoveRule(ctx->nat_postrouting,
|
|
||||||
- action,
|
|
||||||
- "--source", network,
|
|
||||||
- "!", "--destination", network,
|
|
||||||
- "--jump", "MASQUERADE",
|
|
||||||
- NULL);
|
|
||||||
+ if (physdev && physdev[0]) {
|
|
||||||
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
|
|
||||||
+ action,
|
|
||||||
+ "--source", network,
|
|
||||||
+ "!", "--destination", network,
|
|
||||||
+ "--out-interface", physdev,
|
|
||||||
+ "--jump", "MASQUERADE",
|
|
||||||
+ NULL);
|
|
||||||
+ } else {
|
|
||||||
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
|
|
||||||
+ action,
|
|
||||||
+ "--source", network,
|
|
||||||
+ "!", "--destination", network,
|
|
||||||
+ "--jump", "MASQUERADE",
|
|
||||||
+ NULL);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -719,6 +743,7 @@ iptablesForwardMasquerade(iptablesContex
|
|
||||||
* @ctx: pointer to the IP table context
|
|
||||||
* @network: the source network name
|
|
||||||
* @physdev: the physical input device or NULL
|
|
||||||
+ * @protocol: the network protocol or NULL
|
|
||||||
*
|
|
||||||
* Add rules to the IP table context to allow masquerading
|
|
||||||
* network @network on @physdev. This allow the bridge to
|
|
||||||
@@ -729,9 +754,10 @@ iptablesForwardMasquerade(iptablesContex
|
|
||||||
int
|
|
||||||
iptablesAddForwardMasquerade(iptablesContext *ctx,
|
|
||||||
const char *network,
|
|
||||||
- const char *physdev)
|
|
||||||
+ const char *physdev,
|
|
||||||
+ const char *protocol)
|
|
||||||
{
|
|
||||||
- return iptablesForwardMasquerade(ctx, network, physdev, ADD);
|
|
||||||
+ return iptablesForwardMasquerade(ctx, network, physdev, protocol, ADD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -739,6 +765,7 @@ iptablesAddForwardMasquerade(iptablesCon
|
|
||||||
* @ctx: pointer to the IP table context
|
|
||||||
* @network: the source network name
|
|
||||||
* @physdev: the physical input device or NULL
|
|
||||||
+ * @protocol: the network protocol or NULL
|
|
||||||
*
|
|
||||||
* Remove rules from the IP table context to stop masquerading
|
|
||||||
* network @network on @physdev. This stops the bridge from
|
|
||||||
@@ -749,7 +776,8 @@ iptablesAddForwardMasquerade(iptablesCon
|
|
||||||
int
|
|
||||||
iptablesRemoveForwardMasquerade(iptablesContext *ctx,
|
|
||||||
const char *network,
|
|
||||||
- const char *physdev)
|
|
||||||
+ const char *physdev,
|
|
||||||
+ const char *protocol)
|
|
||||||
{
|
|
||||||
- return iptablesForwardMasquerade(ctx, network, physdev, REMOVE);
|
|
||||||
+ return iptablesForwardMasquerade(ctx, network, physdev, protocol, REMOVE);
|
|
||||||
}
|
|
||||||
Index: libvirt-0.8.1/src/util/iptables.h
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/iptables.h
|
|
||||||
+++ libvirt-0.8.1/src/util/iptables.h
|
|
||||||
@@ -85,9 +85,11 @@ int iptablesRemoveForwardRe
|
|
||||||
|
|
||||||
int iptablesAddForwardMasquerade (iptablesContext *ctx,
|
|
||||||
const char *network,
|
|
||||||
- const char *physdev);
|
|
||||||
+ const char *physdev,
|
|
||||||
+ const char *protocol);
|
|
||||||
int iptablesRemoveForwardMasquerade (iptablesContext *ctx,
|
|
||||||
const char *network,
|
|
||||||
- const char *physdev);
|
|
||||||
+ const char *physdev,
|
|
||||||
+ const char *protocol);
|
|
||||||
|
|
||||||
#endif /* __QEMUD_IPTABLES_H__ */
|
|
@ -1,29 +0,0 @@
|
|||||||
commit ce49cfb48ad5e9cac79819d0ccde4394c237af25
|
|
||||||
Author: Eric Blake <eblake@redhat.com>
|
|
||||||
Date: Wed Jun 2 09:03:57 2010 -0600
|
|
||||||
|
|
||||||
bitmap: reject zero-size bitmap
|
|
||||||
|
|
||||||
* src/util/bitmap.c (virBitmapAlloc): Tighten sanity check.
|
|
||||||
|
|
||||||
diff --git a/src/util/bitmap.c b/src/util/bitmap.c
|
|
||||||
index 69094a5..44edb49 100644
|
|
||||||
--- a/src/util/bitmap.c
|
|
||||||
+++ b/src/util/bitmap.c
|
|
||||||
@@ -1,6 +1,7 @@
|
|
||||||
/*
|
|
||||||
* bitmap.h: Simple bitmap operations
|
|
||||||
*
|
|
||||||
+ * Copyright (C) 2010 Red Hat, Inc.
|
|
||||||
* Copyright (C) 2010 Novell, Inc.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
@@ -58,7 +59,7 @@ virBitmapPtr virBitmapAlloc(size_t size)
|
|
||||||
virBitmapPtr bitmap;
|
|
||||||
size_t sz;
|
|
||||||
|
|
||||||
- if (SIZE_MAX - VIR_BITMAP_BITS_PER_UNIT < size)
|
|
||||||
+ if (SIZE_MAX - VIR_BITMAP_BITS_PER_UNIT < size || size == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
sz = (size + VIR_BITMAP_BITS_PER_UNIT - 1) /
|
|
@ -1,59 +0,0 @@
|
|||||||
If VM startup fails early enough (can't find a referenced USB device),
|
|
||||||
libvirtd will crash trying to clear the VNC port bit, since port = 0,
|
|
||||||
which overflows us out of the bitmap bounds.
|
|
||||||
|
|
||||||
Fix this by being more defensive in the bitmap operations, and only
|
|
||||||
clearing a previously set VNC port.
|
|
||||||
|
|
||||||
v2: Add safety check to all relevant bitmap ops.
|
|
||||||
|
|
||||||
Signed-off-by: Cole Robinson <crobinso@redhat.com>
|
|
||||||
---
|
|
||||||
src/qemu/qemu_driver.c | 2 +-
|
|
||||||
src/util/bitmap.c | 6 +++---
|
|
||||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_driver.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
@@ -3635,7 +3635,7 @@ retry:
|
|
||||||
if ((vm->def->ngraphics == 1) &&
|
|
||||||
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
|
|
||||||
vm->def->graphics[0]->data.vnc.autoport &&
|
|
||||||
- vm->def->graphics[0]->data.vnc.port != -1) {
|
|
||||||
+ vm->def->graphics[0]->data.vnc.port >= QEMU_VNC_PORT_MIN) {
|
|
||||||
if (virBitmapClearBit(driver->reservedVNCPorts,
|
|
||||||
vm->def->graphics[0]->data.vnc.port - \
|
|
||||||
QEMU_VNC_PORT_MIN) < 0) {
|
|
||||||
Index: libvirt-0.8.1/src/util/bitmap.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/util/bitmap.c
|
|
||||||
+++ libvirt-0.8.1/src/util/bitmap.c
|
|
||||||
@@ -101,7 +101,7 @@ void virBitmapFree(virBitmapPtr bitmap)
|
|
||||||
*/
|
|
||||||
int virBitmapSetBit(virBitmapPtr bitmap, size_t b)
|
|
||||||
{
|
|
||||||
- if (b > bitmap->size - 1)
|
|
||||||
+ if (bitmap->size <= b)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] |= (1 << VIR_BITMAP_BIT_OFFSET(b));
|
|
||||||
@@ -119,7 +119,7 @@ int virBitmapSetBit(virBitmapPtr bitmap,
|
|
||||||
*/
|
|
||||||
int virBitmapClearBit(virBitmapPtr bitmap, size_t b)
|
|
||||||
{
|
|
||||||
- if (b > bitmap->size - 1)
|
|
||||||
+ if (bitmap->size <= b)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] &= ~(1 << VIR_BITMAP_BIT_OFFSET(b));
|
|
||||||
@@ -141,7 +141,7 @@ int virBitmapGetBit(virBitmapPtr bitmap,
|
|
||||||
{
|
|
||||||
uint32_t bit;
|
|
||||||
|
|
||||||
- if (b > bitmap->size - 1)
|
|
||||||
+ if (bitmap->size <= b)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
bit = bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] &
|
|
@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:037256df745a96ba141dbfc4e4197e8bc16c51f21c834f4f89c599c379792698
|
|
||||||
size 7706670
|
|
3
libvirt-0.8.3.tar.bz2
Normal file
3
libvirt-0.8.3.tar.bz2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:759f4957e6f2b905857897a84e36cbe73f7dc3a5150637430ff086c3e2b414b4
|
||||||
|
size 8250164
|
@ -1,3 +1,12 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Aug 6 21:53:21 MDT 2010 - jfehlig@novell.com
|
||||||
|
|
||||||
|
- Update to libvirt 0.8.3
|
||||||
|
- Support vSphere 4.1
|
||||||
|
- Qemu arbitrary monitor commands
|
||||||
|
- Qemu Monitor API entry point
|
||||||
|
- lots of improvements and bug fixes
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Fri Jul 9 14:35:04 MDT 2010 - jfehlig@novell.com
|
Fri Jul 9 14:35:04 MDT 2010 - jfehlig@novell.com
|
||||||
|
|
||||||
|
54
libvirt.spec
54
libvirt.spec
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# spec file for package libvirt (Version 0.8.1)
|
# spec file for package libvirt (Version 0.8.3)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||||
#
|
#
|
||||||
@ -44,6 +44,7 @@
|
|||||||
%define with_udev 0
|
%define with_udev 0
|
||||||
%define with_hal 0
|
%define with_hal 0
|
||||||
%define with_yajl 0
|
%define with_yajl 0
|
||||||
|
%define with_macvtap 0
|
||||||
|
|
||||||
# Xen is available only on i386 x86_64
|
# Xen is available only on i386 x86_64
|
||||||
%ifnarch %ix86 x86_64
|
%ifnarch %ix86 x86_64
|
||||||
@ -110,14 +111,17 @@ BuildRequires: PolicyKit-devel >= 0.6
|
|||||||
%if %{with_phyp}
|
%if %{with_phyp}
|
||||||
BuildRequires: libssh2-devel
|
BuildRequires: libssh2-devel
|
||||||
%endif
|
%endif
|
||||||
|
%if %{with_macvtap}
|
||||||
|
BuildRequires: libnl-devel
|
||||||
|
%endif
|
||||||
# Only for directory ownership:
|
# Only for directory ownership:
|
||||||
BuildRequires: gtk-doc
|
BuildRequires: gtk-doc
|
||||||
Url: http://libvirt.org/
|
Url: http://libvirt.org/
|
||||||
License: LGPLv2.1+
|
License: LGPLv2.1+
|
||||||
Group: Development/Libraries/C and C++
|
Group: Development/Libraries/C and C++
|
||||||
AutoReqProv: yes
|
AutoReqProv: yes
|
||||||
Version: 0.8.1
|
Version: 0.8.3
|
||||||
Release: 2
|
Release: 1
|
||||||
Summary: A C toolkit to interract with the virtualization capabilities of Linux
|
Summary: A C toolkit to interract with the virtualization capabilities of Linux
|
||||||
# The client side, i.e. shared libs and virsh are in a subpackage
|
# The client side, i.e. shared libs and virsh are in a subpackage
|
||||||
Requires: %{name}-client = %{version}-%{release}
|
Requires: %{name}-client = %{version}-%{release}
|
||||||
@ -141,25 +145,6 @@ Requires: PolicyKit >= 0.6
|
|||||||
Source0: %{name}-%{version}.tar.bz2
|
Source0: %{name}-%{version}.tar.bz2
|
||||||
Source1: libvirtd.init
|
Source1: libvirtd.init
|
||||||
# Upstream patches
|
# Upstream patches
|
||||||
Patch0: remote-rm-unused-field.patch
|
|
||||||
Patch1: vnc-race-1.patch
|
|
||||||
Patch2: vnc-race-2.patch
|
|
||||||
Patch3: vnc-race-3.patch
|
|
||||||
Patch4: bitmap-alloc.patch
|
|
||||||
Patch5: bitmap-fixes.patch
|
|
||||||
Patch6: xend-content-buf.patch
|
|
||||||
Patch7: xend-content-buf-fix.patch
|
|
||||||
Patch8: CVE-2010-223x-0001.patch
|
|
||||||
Patch9: CVE-2010-223x-0002.patch
|
|
||||||
Patch10: CVE-2010-223x-0003.patch
|
|
||||||
Patch11: CVE-2010-223x-0004.patch
|
|
||||||
Patch12: CVE-2010-223x-0005.patch
|
|
||||||
Patch13: CVE-2010-223x-0006.patch
|
|
||||||
Patch14: CVE-2010-223x-0007.patch
|
|
||||||
Patch15: CVE-2010-223x-0008.patch
|
|
||||||
Patch16: CVE-2010-223x-0009.patch
|
|
||||||
Patch17: CVE-2010-223x-0010.patch
|
|
||||||
Patch18: CVE-2010-2242-nat.patch
|
|
||||||
# Need to go upstream
|
# Need to go upstream
|
||||||
Patch100: xen-name-for-devid.patch
|
Patch100: xen-name-for-devid.patch
|
||||||
Patch102: clone.patch
|
Patch102: clone.patch
|
||||||
@ -272,25 +257,6 @@ Authors:
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q
|
||||||
%patch0 -p1
|
|
||||||
%patch1 -p1
|
|
||||||
%patch2 -p1
|
|
||||||
%patch3 -p1
|
|
||||||
%patch4 -p1
|
|
||||||
%patch5 -p1
|
|
||||||
%patch6 -p1
|
|
||||||
%patch7 -p1
|
|
||||||
%patch8 -p1
|
|
||||||
%patch9 -p1
|
|
||||||
%patch10 -p1
|
|
||||||
%patch11 -p1
|
|
||||||
%patch12 -p1
|
|
||||||
%patch13 -p1
|
|
||||||
%patch14 -p1
|
|
||||||
%patch15 -p1
|
|
||||||
%patch16 -p1
|
|
||||||
%patch17 -p1
|
|
||||||
%patch18 -p1
|
|
||||||
%patch100 -p1
|
%patch100 -p1
|
||||||
%patch102
|
%patch102
|
||||||
%patch103 -p1
|
%patch103 -p1
|
||||||
@ -351,6 +317,9 @@ Authors:
|
|||||||
%if ! %{with_yajl}
|
%if ! %{with_yajl}
|
||||||
%define _without_yajl --without-yajl
|
%define _without_yajl --without-yajl
|
||||||
%endif
|
%endif
|
||||||
|
%if ! %{with_macvtap}
|
||||||
|
%define _without_macvtap --without-macvtap
|
||||||
|
%endif
|
||||||
autoreconf -f -i
|
autoreconf -f -i
|
||||||
export CFLAGS="$RPM_OPT_FLAGS"
|
export CFLAGS="$RPM_OPT_FLAGS"
|
||||||
%configure --disable-static --with-pic \
|
%configure --disable-static --with-pic \
|
||||||
@ -372,6 +341,7 @@ export CFLAGS="$RPM_OPT_FLAGS"
|
|||||||
%{?_without_hal} \
|
%{?_without_hal} \
|
||||||
%{?_without_udev} \
|
%{?_without_udev} \
|
||||||
%{?_without_yajl} \
|
%{?_without_yajl} \
|
||||||
|
%{?_without_macvtap} \
|
||||||
--without-xen-proxy \
|
--without-xen-proxy \
|
||||||
--libexecdir=%{_libdir}/%{name} \
|
--libexecdir=%{_libdir}/%{name} \
|
||||||
--with-init-script=none \
|
--with-init-script=none \
|
||||||
@ -497,6 +467,7 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%if 0%{with_storage_disk}
|
%if 0%{with_storage_disk}
|
||||||
%{_libdir}/%{name}/libvirt_parthelper
|
%{_libdir}/%{name}/libvirt_parthelper
|
||||||
%endif
|
%endif
|
||||||
|
%doc %{_mandir}/man8/libvirtd.8*
|
||||||
|
|
||||||
%files client -f %{name}.lang
|
%files client -f %{name}.lang
|
||||||
%defattr(-, root, root)
|
%defattr(-, root, root)
|
||||||
@ -525,6 +496,7 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%{_datadir}/libvirt/schemas/storageencryption.rng
|
%{_datadir}/libvirt/schemas/storageencryption.rng
|
||||||
%{_datadir}/libvirt/cpu_map.xml
|
%{_datadir}/libvirt/cpu_map.xml
|
||||||
%{_datadir}/libvirt/schemas/nwfilter.rng
|
%{_datadir}/libvirt/schemas/nwfilter.rng
|
||||||
|
%{_datadir}/libvirt/schemas/domainsnapshot.rng
|
||||||
%config(noreplace) %{_sysconfdir}/sasl2/libvirt.conf
|
%config(noreplace) %{_sysconfdir}/sasl2/libvirt.conf
|
||||||
|
|
||||||
%files devel
|
%files devel
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
commit 34a7f3f6be9c63ac3d4c4604c1fb2482a4e5053b
|
|
||||||
Author: Matthew Booth <mbooth@redhat.com>
|
|
||||||
Date: Fri May 7 16:38:05 2010 +0200
|
|
||||||
|
|
||||||
Remove unused nwfilter field from struct remote_error
|
|
||||||
|
|
||||||
Change 965466c1 added a new field to struct remote_error, which broke
|
|
||||||
the RPC protocol. Fortunately the new field is unused, so this change
|
|
||||||
simply removes it again.
|
|
||||||
|
|
||||||
* src/remote/remote_protocol.(c|h|x): Remove remote_nwfilter from struct
|
|
||||||
remote_error
|
|
||||||
|
|
||||||
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c
|
|
||||||
index 187281d..972bf52 100644
|
|
||||||
--- a/src/remote/remote_protocol.c
|
|
||||||
+++ b/src/remote/remote_protocol.c
|
|
||||||
@@ -227,8 +227,6 @@ xdr_remote_error (XDR *xdrs, remote_error *objp)
|
|
||||||
return FALSE;
|
|
||||||
if (!xdr_remote_network (xdrs, &objp->net))
|
|
||||||
return FALSE;
|
|
||||||
- if (!xdr_remote_nwfilter (xdrs, &objp->nwfilter))
|
|
||||||
- return FALSE;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h
|
|
||||||
index 6f01da7..a600af6 100644
|
|
||||||
--- a/src/remote/remote_protocol.h
|
|
||||||
+++ b/src/remote/remote_protocol.h
|
|
||||||
@@ -143,7 +143,6 @@ struct remote_error {
|
|
||||||
int int1;
|
|
||||||
int int2;
|
|
||||||
remote_network net;
|
|
||||||
- remote_nwfilter nwfilter;
|
|
||||||
};
|
|
||||||
typedef struct remote_error remote_error;
|
|
||||||
|
|
||||||
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
|
|
||||||
index 8000ee0..1ce488c 100644
|
|
||||||
--- a/src/remote/remote_protocol.x
|
|
||||||
+++ b/src/remote/remote_protocol.x
|
|
||||||
@@ -266,7 +266,6 @@ struct remote_error {
|
|
||||||
int int1;
|
|
||||||
int int2;
|
|
||||||
remote_network net;
|
|
||||||
- remote_nwfilter nwfilter;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Authentication types available thus far.... */
|
|
281
vnc-race-1.patch
281
vnc-race-1.patch
@ -1,281 +0,0 @@
|
|||||||
commit 2f32d7afd5bd71f79c0e756c87813702065c6d1a
|
|
||||||
Author: Jim Fehlig <jfehlig@novell.com>
|
|
||||||
Date: Thu May 20 22:23:48 2010 -0600
|
|
||||||
|
|
||||||
Add simple bitmap operations to utils
|
|
||||||
|
|
||||||
V2:
|
|
||||||
- Move bitmap impl to src/util/bitmap.[ch]
|
|
||||||
- Use CHAR_BIT instead of explicit '8'
|
|
||||||
- Use size_t instead of unsigned int
|
|
||||||
- Fix calculation of bitmap size in virBitmapAlloc
|
|
||||||
- Ensure bit is within range of map in the set, clear, and get
|
|
||||||
operations
|
|
||||||
- Use bool in virBitmapGetBit
|
|
||||||
- Add virBitmapFree to free-like funcs in cfg.mk
|
|
||||||
|
|
||||||
V3:
|
|
||||||
- Check for overflow in virBitmapAlloc
|
|
||||||
- Fix copy and paste bug in virBitmapAlloc
|
|
||||||
- Use size_t in prototypes
|
|
||||||
- Add ATTRIBUTE_NONNULL in prototypes where appropriate
|
|
||||||
and remove NULL check from impl
|
|
||||||
|
|
||||||
V4:
|
|
||||||
- Add ATTRIBUTE_RETURN_CHECK in prototypes where appropriate.
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/Makefile.am
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/Makefile.am
|
|
||||||
+++ libvirt-0.8.1/src/Makefile.am
|
|
||||||
@@ -50,6 +50,7 @@ augeastest_DATA =
|
|
||||||
# helper APIs for various purposes
|
|
||||||
UTIL_SOURCES = \
|
|
||||||
util/authhelper.c util/authhelper.h \
|
|
||||||
+ util/bitmap.c util/bitmap.h \
|
|
||||||
util/bridge.c util/bridge.h \
|
|
||||||
util/buf.c util/buf.h \
|
|
||||||
util/conf.c util/conf.h \
|
|
||||||
Index: libvirt-0.8.1/src/libvirt_private.syms
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/libvirt_private.syms
|
|
||||||
+++ libvirt-0.8.1/src/libvirt_private.syms
|
|
||||||
@@ -4,6 +4,14 @@
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
+# bitmap.h
|
|
||||||
+virBitmapAlloc;
|
|
||||||
+virBitmapFree;
|
|
||||||
+virBitmapSetBit;
|
|
||||||
+virBitmapClearBit;
|
|
||||||
+virBitmapGetBit;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
# buf.h
|
|
||||||
virBufferVSprintf;
|
|
||||||
virBufferEscapeString;
|
|
||||||
Index: libvirt-0.8.1/src/util/bitmap.c
|
|
||||||
===================================================================
|
|
||||||
--- /dev/null
|
|
||||||
+++ libvirt-0.8.1/src/util/bitmap.c
|
|
||||||
@@ -0,0 +1,151 @@
|
|
||||||
+/*
|
|
||||||
+ * bitmap.h: Simple bitmap operations
|
|
||||||
+ *
|
|
||||||
+ * Copyright (C) 2010 Novell, Inc.
|
|
||||||
+ *
|
|
||||||
+ * This library is free software; you can redistribute it and/or
|
|
||||||
+ * modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ * License as published by the Free Software Foundation; either
|
|
||||||
+ * version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+ *
|
|
||||||
+ * This library is distributed in the hope that it will be useful,
|
|
||||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ * Lesser General Public License for more details.
|
|
||||||
+ *
|
|
||||||
+ * You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ * License along with this library; if not, write to the Free Software
|
|
||||||
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
+ *
|
|
||||||
+ * Author: Jim Fehlig <jfehlig@novell.com>
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <config.h>
|
|
||||||
+
|
|
||||||
+#include <limits.h>
|
|
||||||
+#include <stdint.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <sys/types.h>
|
|
||||||
+
|
|
||||||
+#include "bitmap.h"
|
|
||||||
+#include "memory.h"
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+struct _virBitmap {
|
|
||||||
+ size_t size;
|
|
||||||
+ uint32_t *map;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#define VIR_BITMAP_BITS_PER_UNIT (sizeof(uint32_t) * CHAR_BIT)
|
|
||||||
+#define VIR_BITMAP_UNIT_OFFSET(b) ((b) / VIR_BITMAP_BITS_PER_UNIT)
|
|
||||||
+#define VIR_BITMAP_BIT_OFFSET(b) ((b) % VIR_BITMAP_BITS_PER_UNIT)
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * virBitmapAlloc:
|
|
||||||
+ * @size: number of bits
|
|
||||||
+ *
|
|
||||||
+ * Allocate a bitmap capable of containing @size bits.
|
|
||||||
+ *
|
|
||||||
+ * Returns a pointer to the allocated bitmap or NULL if
|
|
||||||
+ * memory cannot be allocated.
|
|
||||||
+ */
|
|
||||||
+virBitmapPtr virBitmapAlloc(size_t size)
|
|
||||||
+{
|
|
||||||
+ virBitmapPtr bitmap;
|
|
||||||
+ size_t sz;
|
|
||||||
+
|
|
||||||
+ if (SIZE_MAX - VIR_BITMAP_BITS_PER_UNIT < size)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ sz = (size + VIR_BITMAP_BITS_PER_UNIT - 1) /
|
|
||||||
+ VIR_BITMAP_BITS_PER_UNIT;
|
|
||||||
+
|
|
||||||
+ if (VIR_ALLOC(bitmap) < 0)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ if (VIR_ALLOC_N(bitmap->map, sz) < 0) {
|
|
||||||
+ VIR_FREE(bitmap);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return bitmap;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * virBitmapFree:
|
|
||||||
+ * @bitmap: previously allocated bitmap
|
|
||||||
+ *
|
|
||||||
+ * Free @bitmap previously allocated by virBitmapAlloc.
|
|
||||||
+ */
|
|
||||||
+void virBitmapFree(virBitmapPtr bitmap)
|
|
||||||
+{
|
|
||||||
+ if (bitmap) {
|
|
||||||
+ VIR_FREE(bitmap->map);
|
|
||||||
+ VIR_FREE(bitmap);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * virBitmapSetBit:
|
|
||||||
+ * @bitmap: Pointer to bitmap
|
|
||||||
+ * @b: bit position to set
|
|
||||||
+ *
|
|
||||||
+ * Set bit position @b in @bitmap
|
|
||||||
+ *
|
|
||||||
+ * Returns 0 on if bit is successfully set, -1 on error.
|
|
||||||
+ */
|
|
||||||
+int virBitmapSetBit(virBitmapPtr bitmap, size_t b)
|
|
||||||
+{
|
|
||||||
+ if (b > bitmap->size - 1)
|
|
||||||
+ return -1;
|
|
||||||
+
|
|
||||||
+ bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] |= (1 << VIR_BITMAP_BIT_OFFSET(b));
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * virBitmapClearBit:
|
|
||||||
+ * @bitmap: Pointer to bitmap
|
|
||||||
+ * @b: bit position to clear
|
|
||||||
+ *
|
|
||||||
+ * Clear bit position @b in @bitmap
|
|
||||||
+ *
|
|
||||||
+ * Returns 0 on if bit is successfully clear, -1 on error.
|
|
||||||
+ */
|
|
||||||
+int virBitmapClearBit(virBitmapPtr bitmap, size_t b)
|
|
||||||
+{
|
|
||||||
+ if (b > bitmap->size - 1)
|
|
||||||
+ return -1;
|
|
||||||
+
|
|
||||||
+ bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] &= ~(1 << VIR_BITMAP_BIT_OFFSET(b));
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * virBitmapGetBit:
|
|
||||||
+ * @bitmap: Pointer to bitmap
|
|
||||||
+ * @b: bit position to get
|
|
||||||
+ * @result: bool pointer to receive bit setting
|
|
||||||
+ *
|
|
||||||
+ * Get setting of bit position @b in @bitmap and store in @result
|
|
||||||
+ *
|
|
||||||
+ * On success, @result will contain the setting of @b and 0 is
|
|
||||||
+ * returned. On failure, -1 is returned and @result is unchanged.
|
|
||||||
+ */
|
|
||||||
+int virBitmapGetBit(virBitmapPtr bitmap, size_t b, bool *result)
|
|
||||||
+{
|
|
||||||
+ uint32_t bit;
|
|
||||||
+
|
|
||||||
+ if (b > bitmap->size - 1)
|
|
||||||
+ return -1;
|
|
||||||
+
|
|
||||||
+ bit = bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] &
|
|
||||||
+ (1 << VIR_BITMAP_BIT_OFFSET(b));
|
|
||||||
+
|
|
||||||
+ *result = bit != 0;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
Index: libvirt-0.8.1/src/util/bitmap.h
|
|
||||||
===================================================================
|
|
||||||
--- /dev/null
|
|
||||||
+++ libvirt-0.8.1/src/util/bitmap.h
|
|
||||||
@@ -0,0 +1,63 @@
|
|
||||||
+/*
|
|
||||||
+ * bitmap.h: Simple bitmap operations
|
|
||||||
+ *
|
|
||||||
+ * Copyright (C) 2010 Novell, Inc.
|
|
||||||
+ *
|
|
||||||
+ * This library is free software; you can redistribute it and/or
|
|
||||||
+ * modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ * License as published by the Free Software Foundation; either
|
|
||||||
+ * version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+ *
|
|
||||||
+ * This library is distributed in the hope that it will be useful,
|
|
||||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ * Lesser General Public License for more details.
|
|
||||||
+ *
|
|
||||||
+ * You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ * License along with this library; if not, write to the Free Software
|
|
||||||
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
+ *
|
|
||||||
+ * Author: Jim Fehlig <jfehlig@novell.com>
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#ifndef __BITMAP_H__
|
|
||||||
+# define __BITMAP_H__
|
|
||||||
+
|
|
||||||
+#include "internal.h"
|
|
||||||
+
|
|
||||||
+#include <stdbool.h>
|
|
||||||
+#include <sys/types.h>
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+typedef struct _virBitmap virBitmap;
|
|
||||||
+typedef virBitmap *virBitmapPtr;
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Allocate a bitmap capable of containing @size bits.
|
|
||||||
+ */
|
|
||||||
+virBitmapPtr virBitmapAlloc(size_t size) ATTRIBUTE_RETURN_CHECK;
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Free previously allocated bitmap
|
|
||||||
+ */
|
|
||||||
+void virBitmapFree(virBitmapPtr bitmap);
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Set bit position @b in @bitmap
|
|
||||||
+ */
|
|
||||||
+int virBitmapSetBit(virBitmapPtr bitmap, size_t b)
|
|
||||||
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Clear bit position @b in @bitmap
|
|
||||||
+ */
|
|
||||||
+int virBitmapClearBit(virBitmapPtr bitmap, size_t b)
|
|
||||||
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Get setting of bit position @b in @bitmap and store in @result
|
|
||||||
+ */
|
|
||||||
+int virBitmapGetBit(virBitmapPtr bitmap, size_t b, bool *result)
|
|
||||||
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK;
|
|
||||||
+
|
|
||||||
+#endif
|
|
@ -1,29 +0,0 @@
|
|||||||
commit c020f6203e3735a531135bc4321415ce5520fbde
|
|
||||||
Author: Jim Fehlig <jfehlig@novell.com>
|
|
||||||
Date: Thu May 20 22:25:16 2010 -0600
|
|
||||||
|
|
||||||
Add defines for QEMU_VNC_PORT_{MIN,MAX} and use them
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_driver.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
@@ -89,6 +89,9 @@
|
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_QEMU
|
|
||||||
|
|
||||||
+#define QEMU_VNC_PORT_MIN 5900
|
|
||||||
+#define QEMU_VNC_PORT_MAX 65535
|
|
||||||
+
|
|
||||||
/* Only 1 job is allowed at any time
|
|
||||||
* A job includes *all* monitor commands, even those just querying
|
|
||||||
* information, not merely actions */
|
|
||||||
@@ -2607,7 +2610,7 @@ qemuInitPCIAddresses(struct qemud_driver
|
|
||||||
static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
- for (i = 5900 ; i < 65535 ; i++) {
|
|
||||||
+ for (i = QEMU_VNC_PORT_MIN; i < QEMU_VNC_PORT_MAX; i++) {
|
|
||||||
int fd;
|
|
||||||
int reuse = 1;
|
|
||||||
struct sockaddr_in addr;
|
|
130
vnc-race-3.patch
130
vnc-race-3.patch
@ -1,130 +0,0 @@
|
|||||||
commit ba196952f57f2cb22be75fa5a4f363035a111103
|
|
||||||
Author: Jim Fehlig <jfehlig@novell.com>
|
|
||||||
Date: Fri May 21 07:52:09 2010 -0600
|
|
||||||
|
|
||||||
Fix race in finding available vnc port
|
|
||||||
|
|
||||||
The qemu driver contains a subtle race in the logic to find next
|
|
||||||
available vnc port. Currently it iterates through all available ports
|
|
||||||
and returns the first for which bind(2) succeeds. However it is possible
|
|
||||||
that a previously issued port has not yet been bound by qemu, resulting
|
|
||||||
in the same port used for a subsequent domain.
|
|
||||||
|
|
||||||
This patch addresses the race by using a simple bitmap to "reserve" the
|
|
||||||
ports allocated by libvirt.
|
|
||||||
|
|
||||||
V2:
|
|
||||||
- Put port bitmap in struct qemud_driver
|
|
||||||
- Initialize bitmap in qemudStartup
|
|
||||||
|
|
||||||
V3:
|
|
||||||
- Check for failure of virBitmapGetBit
|
|
||||||
- Additional check for port != -1 before calling virbitmapClearBit
|
|
||||||
|
|
||||||
V4:
|
|
||||||
- Check for failure of virBitmap{Set,Clear}Bit
|
|
||||||
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_conf.h
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_conf.h
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_conf.h
|
|
||||||
@@ -39,6 +39,7 @@
|
|
||||||
# include "pci.h"
|
|
||||||
# include "cpu_conf.h"
|
|
||||||
# include "driver.h"
|
|
||||||
+# include "bitmap.h"
|
|
||||||
|
|
||||||
# define qemudDebug(fmt, ...) do {} while(0)
|
|
||||||
|
|
||||||
@@ -153,6 +154,8 @@ struct qemud_driver {
|
|
||||||
char *saveImageFormat;
|
|
||||||
|
|
||||||
pciDeviceList *activePciHostdevs;
|
|
||||||
+
|
|
||||||
+ virBitmapPtr reservedVNCPorts;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet;
|
|
||||||
Index: libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
===================================================================
|
|
||||||
--- libvirt-0.8.1.orig/src/qemu/qemu_driver.c
|
|
||||||
+++ libvirt-0.8.1/src/qemu/qemu_driver.c
|
|
||||||
@@ -1479,6 +1479,11 @@ qemudStartup(int privileged) {
|
|
||||||
virEventAddTimeout(-1, qemuDomainEventFlush, qemu_driver, NULL)) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
+ /* Allocate bitmap for vnc port reservation */
|
|
||||||
+ if ((qemu_driver->reservedVNCPorts =
|
|
||||||
+ virBitmapAlloc(QEMU_VNC_PORT_MAX - QEMU_VNC_PORT_MIN)) == NULL)
|
|
||||||
+ goto out_of_memory;
|
|
||||||
+
|
|
||||||
if (privileged) {
|
|
||||||
if (virAsprintf(&qemu_driver->logDir,
|
|
||||||
"%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
|
|
||||||
@@ -1775,6 +1780,7 @@ qemudShutdown(void) {
|
|
||||||
virCapabilitiesFree(qemu_driver->caps);
|
|
||||||
|
|
||||||
virDomainObjListDeinit(&qemu_driver->domains);
|
|
||||||
+ virBitmapFree(qemu_driver->reservedVNCPorts);
|
|
||||||
|
|
||||||
VIR_FREE(qemu_driver->securityDriverName);
|
|
||||||
VIR_FREE(qemu_driver->logDir);
|
|
||||||
@@ -2607,13 +2613,22 @@ qemuInitPCIAddresses(struct qemud_driver
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
|
|
||||||
+static int qemudNextFreeVNCPort(struct qemud_driver *driver) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = QEMU_VNC_PORT_MIN; i < QEMU_VNC_PORT_MAX; i++) {
|
|
||||||
int fd;
|
|
||||||
int reuse = 1;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
+ bool used = false;
|
|
||||||
+
|
|
||||||
+ if (virBitmapGetBit(driver->reservedVNCPorts,
|
|
||||||
+ i - QEMU_VNC_PORT_MIN, &used) < 0)
|
|
||||||
+ VIR_DEBUG("virBitmapGetBit failed on bit %d", i - QEMU_VNC_PORT_MIN);
|
|
||||||
+
|
|
||||||
+ if (used)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(i);
|
|
||||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
@@ -2629,6 +2644,12 @@ static int qemudNextFreeVNCPort(struct q
|
|
||||||
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
|
|
||||||
/* Not in use, lets grab it */
|
|
||||||
close(fd);
|
|
||||||
+ /* Add port to bitmap of reserved ports */
|
|
||||||
+ if (virBitmapSetBit(driver->reservedVNCPorts,
|
|
||||||
+ i - QEMU_VNC_PORT_MIN) < 0) {
|
|
||||||
+ VIR_DEBUG("virBitmapSetBit failed on bit %d",
|
|
||||||
+ i - QEMU_VNC_PORT_MIN);
|
|
||||||
+ }
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
@@ -3608,6 +3629,21 @@ retry:
|
|
||||||
|
|
||||||
qemudRemoveDomainStatus(driver, vm);
|
|
||||||
|
|
||||||
+ /* Remove VNC port from port reservation bitmap, but only if it was
|
|
||||||
+ reserved by the driver (autoport=yes)
|
|
||||||
+ */
|
|
||||||
+ if ((vm->def->ngraphics == 1) &&
|
|
||||||
+ vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
|
|
||||||
+ vm->def->graphics[0]->data.vnc.autoport &&
|
|
||||||
+ vm->def->graphics[0]->data.vnc.port != -1) {
|
|
||||||
+ if (virBitmapClearBit(driver->reservedVNCPorts,
|
|
||||||
+ vm->def->graphics[0]->data.vnc.port - \
|
|
||||||
+ QEMU_VNC_PORT_MIN) < 0) {
|
|
||||||
+ VIR_DEBUG("virBitmapClearBit failed on bit %d",
|
|
||||||
+ vm->def->graphics[0]->data.vnc.port - QEMU_VNC_PORT_MIN);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
vm->pid = -1;
|
|
||||||
vm->def->id = -1;
|
|
||||||
vm->state = VIR_DOMAIN_SHUTOFF;
|
|
@ -1,79 +0,0 @@
|
|||||||
commit b1eb7f2e987d21b1711e86e5cb63a69abfce82f1
|
|
||||||
Author: Jim Fehlig <jfehlig@linux-ypgk.site>
|
|
||||||
Date: Fri Jun 4 10:04:03 2010 -0600
|
|
||||||
|
|
||||||
Fixes for commit 211dd1e9
|
|
||||||
|
|
||||||
Fixes for issues in commit 211dd1e9 noted by by Jim Meyering.
|
|
||||||
|
|
||||||
1. Allocate content buffer of size content_length + 1 to ensure
|
|
||||||
NUL-termination.
|
|
||||||
2. Limit content buffer size to 64k
|
|
||||||
3. Fix whitespace issue
|
|
||||||
|
|
||||||
V2:
|
|
||||||
- Add comment to clarify allocation of content buffer
|
|
||||||
- Add ATTRIBUTE_NONNULL where appropriate
|
|
||||||
- User NULLSTR macro
|
|
||||||
|
|
||||||
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
|
|
||||||
index 0c1a738..51cad92 100644
|
|
||||||
--- a/src/xen/xend_internal.c
|
|
||||||
+++ b/src/xen/xend_internal.c
|
|
||||||
@@ -68,6 +68,7 @@
|
|
||||||
# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#define XEND_RCV_BUF_MAX_LEN 65536
|
|
||||||
|
|
||||||
#ifndef PROXY
|
|
||||||
static int
|
|
||||||
@@ -310,7 +311,7 @@ istartswith(const char *haystack, const char *needle)
|
|
||||||
* Returns the HTTP return code and @content is set to the
|
|
||||||
* allocated memory containing HTTP content.
|
|
||||||
*/
|
|
||||||
-static int
|
|
||||||
+static int ATTRIBUTE_NONNULL (2)
|
|
||||||
xend_req(int fd, char **content)
|
|
||||||
{
|
|
||||||
char buffer[4096];
|
|
||||||
@@ -330,7 +331,19 @@ xend_req(int fd, char **content)
|
|
||||||
if (content_length > 0) {
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
- if (VIR_ALLOC_N(*content, content_length) < 0 ) {
|
|
||||||
+ if (content_length > XEND_RCV_BUF_MAX_LEN) {
|
|
||||||
+ virXendError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
+ _("Xend returned HTTP Content-Length of %d, "
|
|
||||||
+ "which exceeds maximum of %d"),
|
|
||||||
+ content_length,
|
|
||||||
+ XEND_RCV_BUF_MAX_LEN);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Allocate one byte beyond the end of the largest buffer we will read.
|
|
||||||
+ Combined with the fact that VIR_ALLOC_N zeros the returned buffer,
|
|
||||||
+ this guarantees that "content" will always be NUL-terminated. */
|
|
||||||
+ if (VIR_ALLOC_N(*content, content_length + 1) < 0 ) {
|
|
||||||
virReportOOMError();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
@@ -353,7 +366,7 @@ xend_req(int fd, char **content)
|
|
||||||
*
|
|
||||||
* Returns the HTTP return code or -1 in case or error.
|
|
||||||
*/
|
|
||||||
-static int
|
|
||||||
+static int ATTRIBUTE_NONNULL(3)
|
|
||||||
xend_get(virConnectPtr xend, const char *path,
|
|
||||||
char **content)
|
|
||||||
{
|
|
||||||
@@ -379,8 +392,7 @@ xend_get(virConnectPtr xend, const char *path,
|
|
||||||
((ret != 404) || (!STRPREFIX(path, "/xend/domain/")))) {
|
|
||||||
virXendError(VIR_ERR_GET_FAILED,
|
|
||||||
_("%d status from xen daemon: %s:%s"),
|
|
||||||
- ret, path,
|
|
||||||
- content ? *content: "NULL");
|
|
||||||
+ ret, path, NULLSTR(*content));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
@ -1,244 +0,0 @@
|
|||||||
commit 211dd1e9c54a9ba92e2e648acacbc18981374073
|
|
||||||
Author: Jim Fehlig <jfehlig@novell.com>
|
|
||||||
Date: Wed Jun 2 18:07:17 2010 -0600
|
|
||||||
|
|
||||||
Allocate buffer to hold xend response
|
|
||||||
|
|
||||||
There are cases when a response from xend can exceed 4096 bytes, in
|
|
||||||
which case anything beyond 4096 is ignored. This patch changes the
|
|
||||||
current fixed-size, stack-allocated buffer to a dynamically allocated
|
|
||||||
buffer based on Content-Length in HTTP header.
|
|
||||||
|
|
||||||
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
|
|
||||||
index e763bad..0c1a738 100644
|
|
||||||
--- a/src/xen/xend_internal.c
|
|
||||||
+++ b/src/xen/xend_internal.c
|
|
||||||
@@ -302,17 +302,19 @@ istartswith(const char *haystack, const char *needle)
|
|
||||||
* xend_req:
|
|
||||||
* @fd: the file descriptor
|
|
||||||
* @content: the buffer to store the content
|
|
||||||
- * @n_content: the size of the buffer
|
|
||||||
*
|
|
||||||
* Read the HTTP response from a Xen Daemon request.
|
|
||||||
+ * If the response contains content, memory is allocated to
|
|
||||||
+ * hold the content.
|
|
||||||
*
|
|
||||||
- * Returns the HTTP return code.
|
|
||||||
+ * Returns the HTTP return code and @content is set to the
|
|
||||||
+ * allocated memory containing HTTP content.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
-xend_req(int fd, char *content, size_t n_content)
|
|
||||||
+xend_req(int fd, char **content)
|
|
||||||
{
|
|
||||||
char buffer[4096];
|
|
||||||
- int content_length = -1;
|
|
||||||
+ int content_length = 0;
|
|
||||||
int retcode = 0;
|
|
||||||
|
|
||||||
while (sreads(fd, buffer, sizeof(buffer)) > 0) {
|
|
||||||
@@ -325,19 +327,17 @@ xend_req(int fd, char *content, size_t n_content)
|
|
||||||
retcode = atoi(buffer + 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (content_length > -1) {
|
|
||||||
+ if (content_length > 0) {
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
- if ((unsigned int) content_length > (n_content + 1))
|
|
||||||
- content_length = n_content - 1;
|
|
||||||
+ if (VIR_ALLOC_N(*content, content_length) < 0 ) {
|
|
||||||
+ virReportOOMError();
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- ret = sread(fd, content, content_length);
|
|
||||||
+ ret = sread(fd, *content, content_length);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
-
|
|
||||||
- content[ret] = 0;
|
|
||||||
- } else {
|
|
||||||
- content[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return retcode;
|
|
||||||
@@ -348,7 +348,6 @@ xend_req(int fd, char *content, size_t n_content)
|
|
||||||
* @xend: pointer to the Xen Daemon structure
|
|
||||||
* @path: the path used for the HTTP request
|
|
||||||
* @content: the buffer to store the content
|
|
||||||
- * @n_content: the size of the buffer
|
|
||||||
*
|
|
||||||
* Do an HTTP GET RPC with the Xen Daemon
|
|
||||||
*
|
|
||||||
@@ -356,7 +355,7 @@ xend_req(int fd, char *content, size_t n_content)
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
xend_get(virConnectPtr xend, const char *path,
|
|
||||||
- char *content, size_t n_content)
|
|
||||||
+ char **content)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
int s = do_connect(xend);
|
|
||||||
@@ -373,14 +372,15 @@ xend_get(virConnectPtr xend, const char *path,
|
|
||||||
"Accept-Encoding: identity\r\n"
|
|
||||||
"Content-Type: application/x-www-form-urlencoded\r\n" "\r\n");
|
|
||||||
|
|
||||||
- ret = xend_req(s, content, n_content);
|
|
||||||
+ ret = xend_req(s, content);
|
|
||||||
close(s);
|
|
||||||
|
|
||||||
if (((ret < 0) || (ret >= 300)) &&
|
|
||||||
((ret != 404) || (!STRPREFIX(path, "/xend/domain/")))) {
|
|
||||||
virXendError(VIR_ERR_GET_FAILED,
|
|
||||||
_("%d status from xen daemon: %s:%s"),
|
|
||||||
- ret, path, content);
|
|
||||||
+ ret, path,
|
|
||||||
+ content ? *content: "NULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
@@ -392,8 +392,6 @@ xend_get(virConnectPtr xend, const char *path,
|
|
||||||
* @xend: pointer to the Xen Daemon structure
|
|
||||||
* @path: the path used for the HTTP request
|
|
||||||
* @ops: the information sent for the POST
|
|
||||||
- * @content: the buffer to store the content
|
|
||||||
- * @n_content: the size of the buffer
|
|
||||||
*
|
|
||||||
* Do an HTTP POST RPC with the Xen Daemon, this usually makes changes at the
|
|
||||||
* Xen level.
|
|
||||||
@@ -401,10 +399,10 @@ xend_get(virConnectPtr xend, const char *path,
|
|
||||||
* Returns the HTTP return code or -1 in case or error.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
-xend_post(virConnectPtr xend, const char *path, const char *ops,
|
|
||||||
- char *content, size_t n_content)
|
|
||||||
+xend_post(virConnectPtr xend, const char *path, const char *ops)
|
|
||||||
{
|
|
||||||
char buffer[100];
|
|
||||||
+ char *err_buf = NULL;
|
|
||||||
int ret;
|
|
||||||
int s = do_connect(xend);
|
|
||||||
|
|
||||||
@@ -425,26 +423,28 @@ xend_post(virConnectPtr xend, const char *path, const char *ops,
|
|
||||||
swrites(s, "\r\n\r\n");
|
|
||||||
swrites(s, ops);
|
|
||||||
|
|
||||||
- ret = xend_req(s, content, n_content);
|
|
||||||
+ ret = xend_req(s, &err_buf);
|
|
||||||
close(s);
|
|
||||||
|
|
||||||
if ((ret < 0) || (ret >= 300)) {
|
|
||||||
virXendError(VIR_ERR_POST_FAILED,
|
|
||||||
- _("xend_post: error from xen daemon: %s"), content);
|
|
||||||
- } else if ((ret == 202) && (strstr(content, "failed") != NULL)) {
|
|
||||||
+ _("xend_post: error from xen daemon: %s"), err_buf);
|
|
||||||
+ } else if ((ret == 202) && err_buf && (strstr(err_buf, "failed") != NULL)) {
|
|
||||||
virXendError(VIR_ERR_POST_FAILED,
|
|
||||||
- _("xend_post: error from xen daemon: %s"), content);
|
|
||||||
+ _("xend_post: error from xen daemon: %s"), err_buf);
|
|
||||||
ret = -1;
|
|
||||||
- } else if (((ret >= 200) && (ret <= 202)) && (strstr(content, "xend.err") != NULL)) {
|
|
||||||
+ } else if (((ret >= 200) && (ret <= 202)) && err_buf &&
|
|
||||||
+ (strstr(err_buf, "xend.err") != NULL)) {
|
|
||||||
/* This is to catch case of things like 'virsh dump Domain-0 foo'
|
|
||||||
* which returns a success code, but the word 'xend.err'
|
|
||||||
* in body to indicate error :-(
|
|
||||||
*/
|
|
||||||
virXendError(VIR_ERR_POST_FAILED,
|
|
||||||
- _("xend_post: error from xen daemon: %s"), content);
|
|
||||||
+ _("xend_post: error from xen daemon: %s"), err_buf);
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ VIR_FREE(err_buf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* ! PROXY */
|
|
||||||
@@ -487,8 +487,6 @@ http2unix(int ret)
|
|
||||||
* xend_op_ext:
|
|
||||||
* @xend: pointer to the Xen Daemon structure
|
|
||||||
* @path: path for the object
|
|
||||||
- * @error: buffer for the error output
|
|
||||||
- * @n_error: size of @error
|
|
||||||
* @key: the key for the operation
|
|
||||||
* @ap: input values to pass to the operation
|
|
||||||
*
|
|
||||||
@@ -497,8 +495,7 @@ http2unix(int ret)
|
|
||||||
* Returns 0 in case of success, -1 in case of failure.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
-xend_op_ext(virConnectPtr xend, const char *path, char *error,
|
|
||||||
- size_t n_error, const char *key, va_list ap)
|
|
||||||
+xend_op_ext(virConnectPtr xend, const char *path, const char *key, va_list ap)
|
|
||||||
{
|
|
||||||
const char *k = key, *v;
|
|
||||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
||||||
@@ -524,7 +521,7 @@ xend_op_ext(virConnectPtr xend, const char *path, char *error,
|
|
||||||
}
|
|
||||||
|
|
||||||
content = virBufferContentAndReset(&buf);
|
|
||||||
- ret = http2unix(xend_post(xend, path, content, error, n_error));
|
|
||||||
+ ret = http2unix(xend_post(xend, path, content));
|
|
||||||
VIR_FREE(content);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
@@ -535,8 +532,6 @@ xend_op_ext(virConnectPtr xend, const char *path, char *error,
|
|
||||||
* xend_op:
|
|
||||||
* @xend: pointer to the Xen Daemon structure
|
|
||||||
* @name: the domain name target of this operation
|
|
||||||
- * @error: buffer for the error output
|
|
||||||
- * @n_error: size of @error
|
|
||||||
* @key: the key for the operation
|
|
||||||
* @ap: input values to pass to the operation
|
|
||||||
* @...: input values to pass to the operation
|
|
||||||
@@ -550,14 +545,13 @@ static int ATTRIBUTE_SENTINEL
|
|
||||||
xend_op(virConnectPtr xend, const char *name, const char *key, ...)
|
|
||||||
{
|
|
||||||
char buffer[1024];
|
|
||||||
- char error[1024];
|
|
||||||
va_list ap;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
snprintf(buffer, sizeof(buffer), "/xend/domain/%s", name);
|
|
||||||
|
|
||||||
va_start(ap, key);
|
|
||||||
- ret = xend_op_ext(xend, buffer, error, sizeof(error), key, ap);
|
|
||||||
+ ret = xend_op_ext(xend, buffer, key, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
@@ -581,21 +575,29 @@ static struct sexpr *sexpr_get(virConnectPtr xend, const char *fmt, ...)
|
|
||||||
static struct sexpr *
|
|
||||||
sexpr_get(virConnectPtr xend, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
- char buffer[4096];
|
|
||||||
+ char *buffer = NULL;
|
|
||||||
char path[1024];
|
|
||||||
va_list ap;
|
|
||||||
int ret;
|
|
||||||
+ struct sexpr *res = NULL;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vsnprintf(path, sizeof(path), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
- ret = xend_get(xend, path, buffer, sizeof(buffer));
|
|
||||||
+ ret = xend_get(xend, path, &buffer);
|
|
||||||
ret = http2unix(ret);
|
|
||||||
if (ret == -1)
|
|
||||||
- return NULL;
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ if (buffer == NULL)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ res = string2sexpr(buffer);
|
|
||||||
|
|
||||||
- return string2sexpr(buffer);
|
|
||||||
+cleanup:
|
|
||||||
+ VIR_FREE(buffer);
|
|
||||||
+ return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
Loading…
Reference in New Issue
Block a user