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
|
||||
|
||||
|
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.
|
||||
#
|
||||
@ -44,6 +44,7 @@
|
||||
%define with_udev 0
|
||||
%define with_hal 0
|
||||
%define with_yajl 0
|
||||
%define with_macvtap 0
|
||||
|
||||
# Xen is available only on i386 x86_64
|
||||
%ifnarch %ix86 x86_64
|
||||
@ -110,14 +111,17 @@ BuildRequires: PolicyKit-devel >= 0.6
|
||||
%if %{with_phyp}
|
||||
BuildRequires: libssh2-devel
|
||||
%endif
|
||||
%if %{with_macvtap}
|
||||
BuildRequires: libnl-devel
|
||||
%endif
|
||||
# Only for directory ownership:
|
||||
BuildRequires: gtk-doc
|
||||
Url: http://libvirt.org/
|
||||
License: LGPLv2.1+
|
||||
Group: Development/Libraries/C and C++
|
||||
AutoReqProv: yes
|
||||
Version: 0.8.1
|
||||
Release: 2
|
||||
Version: 0.8.3
|
||||
Release: 1
|
||||
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
|
||||
Requires: %{name}-client = %{version}-%{release}
|
||||
@ -141,25 +145,6 @@ Requires: PolicyKit >= 0.6
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
Source1: libvirtd.init
|
||||
# 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
|
||||
Patch100: xen-name-for-devid.patch
|
||||
Patch102: clone.patch
|
||||
@ -272,25 +257,6 @@ Authors:
|
||||
|
||||
%prep
|
||||
%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
|
||||
%patch102
|
||||
%patch103 -p1
|
||||
@ -351,6 +317,9 @@ Authors:
|
||||
%if ! %{with_yajl}
|
||||
%define _without_yajl --without-yajl
|
||||
%endif
|
||||
%if ! %{with_macvtap}
|
||||
%define _without_macvtap --without-macvtap
|
||||
%endif
|
||||
autoreconf -f -i
|
||||
export CFLAGS="$RPM_OPT_FLAGS"
|
||||
%configure --disable-static --with-pic \
|
||||
@ -372,6 +341,7 @@ export CFLAGS="$RPM_OPT_FLAGS"
|
||||
%{?_without_hal} \
|
||||
%{?_without_udev} \
|
||||
%{?_without_yajl} \
|
||||
%{?_without_macvtap} \
|
||||
--without-xen-proxy \
|
||||
--libexecdir=%{_libdir}/%{name} \
|
||||
--with-init-script=none \
|
||||
@ -497,6 +467,7 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%if 0%{with_storage_disk}
|
||||
%{_libdir}/%{name}/libvirt_parthelper
|
||||
%endif
|
||||
%doc %{_mandir}/man8/libvirtd.8*
|
||||
|
||||
%files client -f %{name}.lang
|
||||
%defattr(-, root, root)
|
||||
@ -525,6 +496,7 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{_datadir}/libvirt/schemas/storageencryption.rng
|
||||
%{_datadir}/libvirt/cpu_map.xml
|
||||
%{_datadir}/libvirt/schemas/nwfilter.rng
|
||||
%{_datadir}/libvirt/schemas/domainsnapshot.rng
|
||||
%config(noreplace) %{_sysconfdir}/sasl2/libvirt.conf
|
||||
|
||||
%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