VUL-0: multiple issues in libvirt
OBS-URL: https://build.opensuse.org/package/show/Virtualization/libvirt?expand=0&rev=60
This commit is contained in:
parent
118ab4ae54
commit
274bce922a
339
CVE-2010-223x-0001.patch
Normal file
339
CVE-2010-223x-0001.patch
Normal file
@ -0,0 +1,339 @@
|
||||
>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;
|
158
CVE-2010-223x-0002.patch
Normal file
158
CVE-2010-223x-0002.patch
Normal file
@ -0,0 +1,158 @@
|
||||
>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;
|
||||
}
|
||||
|
486
CVE-2010-223x-0003.patch
Normal file
486
CVE-2010-223x-0003.patch
Normal file
@ -0,0 +1,486 @@
|
||||
>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,
|
218
CVE-2010-223x-0004.patch
Normal file
218
CVE-2010-223x-0004.patch
Normal file
@ -0,0 +1,218 @@
|
||||
>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__ */
|
167
CVE-2010-223x-0005.patch
Normal file
167
CVE-2010-223x-0005.patch
Normal file
@ -0,0 +1,167 @@
|
||||
>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
|
273
CVE-2010-223x-0006.patch
Normal file
273
CVE-2010-223x-0006.patch
Normal file
@ -0,0 +1,273 @@
|
||||
>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)
|
1058
CVE-2010-223x-0007.patch
Normal file
1058
CVE-2010-223x-0007.patch
Normal file
File diff suppressed because it is too large
Load Diff
385
CVE-2010-223x-0008.patch
Normal file
385
CVE-2010-223x-0008.patch
Normal file
@ -0,0 +1,385 @@
|
||||
>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");
|
110
CVE-2010-223x-0009.patch
Normal file
110
CVE-2010-223x-0009.patch
Normal file
@ -0,0 +1,110 @@
|
||||
>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;
|
288
CVE-2010-223x-0010.patch
Normal file
288
CVE-2010-223x-0010.patch
Normal file
@ -0,0 +1,288 @@
|
||||
>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;
|
||||
}
|
262
CVE-2010-2242-nat.patch
Normal file
262
CVE-2010-2242-nat.patch
Normal file
@ -0,0 +1,262 @@
|
||||
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,3 +1,11 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Jul 9 14:35:04 MDT 2010 - jfehlig@novell.com
|
||||
|
||||
- VUL-0: multiple issues in libvirt
|
||||
CVE-2010-223x-000[1-0].patch, CVE-2010-223x-0010.patch,
|
||||
CVE-2010-2242-nat.patch
|
||||
bnc#618155
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Jun 25 09:02:38 MDT 2010 - jfehlig@novell.com
|
||||
|
||||
|
27
libvirt.spec
27
libvirt.spec
@ -96,6 +96,9 @@ BuildRequires: avahi-devel
|
||||
%if %{with_selinux}
|
||||
BuildRequires: libselinux-devel
|
||||
%endif
|
||||
%if %{with_apparmor}
|
||||
BuildRequires: libapparmor-devel
|
||||
%endif
|
||||
%if %{with_numactl}
|
||||
BuildRequires: libnuma-devel
|
||||
%endif
|
||||
@ -114,7 +117,7 @@ License: LGPLv2.1+
|
||||
Group: Development/Libraries/C and C++
|
||||
AutoReqProv: yes
|
||||
Version: 0.8.1
|
||||
Release: 3
|
||||
Release: 2
|
||||
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}
|
||||
@ -146,6 +149,17 @@ 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
|
||||
@ -266,6 +280,17 @@ Authors:
|
||||
%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
|
||||
|
Loading…
Reference in New Issue
Block a user