rpms/xen/F-7 xen-pvfb-bogus-update.patch, NONE, 1.1 xen-pvfb-validate-fb.patch, NONE, 1.1 xen-qemu-block-no-auto-format.patch, NONE, 1.1 xen.spec, 1.190, 1.191

Markus Armbruster (armbru) fedora-extras-commits at redhat.com
Wed May 14 15:55:42 UTC 2008


Author: armbru

Update of /cvs/pkgs/rpms/xen/F-7
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv24079

Modified Files:
	xen.spec 
Added Files:
	xen-pvfb-bogus-update.patch xen-pvfb-validate-fb.patch 
	xen-qemu-block-no-auto-format.patch 
Log Message:
Disable QEMU image format auto-detection (CVE-2008-2004)
Fix PVFB to validate frame buffer description (CVE-2008-1943)
Fix PVFB to cope with bogus update requests (CVE-2008-1944)



xen-pvfb-bogus-update.patch:

--- NEW FILE xen-pvfb-bogus-update.patch ---
Derived from
# HG changeset patch
# User Keir Fraser <keir.fraser at citrix.com>
# Date 1195232023 0
# Node ID 614dad9f8fdcda21b5e0083cce3320b17bfcefdd
# Parent  1ad85cdcca3d99130ce3a74ab3203a3f14c25858
pvfb: PVFB SDL backend chokes on bogus screen updates

Bogus screen update requests from buggy or malicous frontend make SDL
crash.  The VNC backend silently ignores them.  Catch and log them.

Signed-off-by: Markus Armbruster <armbru at redhat.com>

diff --exclude '*~' -rup a/tools/xenfb/oldxenfb.c b/tools/xenfb/oldxenfb.c
--- a/tools/xenfb/oldxenfb.c	2008-05-05 15:56:06.000000000 +0200
+++ b/tools/xenfb/oldxenfb.c	2008-05-05 15:57:08.000000000 +0200
@@ -20,7 +20,8 @@
 
 #include "xenfb.h"
 
-// FIXME defend against malicious frontend?
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
 
 struct xenfb_device {
 	const char *devicetype;
@@ -529,14 +530,28 @@ static void xenfb_on_fb_event32(struct x
 	rmb();			/* ensure we see ring contents up to prod */
 	for (cons = page->out_cons; cons != prod; cons++) {
 		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
+		int x, y, w, h;
 
 		switch (event->type) {
 		case XENFB_TYPE_UPDATE:
-                    if (xenfb->pub.update)
-			xenfb->pub.update(&xenfb->pub,
-					  event->update.x, event->update.y,
-					  event->update.width, event->update.height);
-                    break;
+			x = MAX(event->update.x, 0);
+			y = MAX(event->update.y, 0);
+			w = MIN(event->update.width, xenfb->pub.width - x);
+			h = MIN(event->update.height, xenfb->pub.height - y);
+			if (w < 0 || h < 0) {
+				fprintf(stderr, "%s bogus update ignored\n",
+					xenfb->fb.nodename);
+				break;
+			}
+			if (x != event->update.x || y != event->update.y
+			    || w != event->update.width
+			    || h != event->update.height) {
+				fprintf(stderr, "%s bogus update clipped\n",
+					xenfb->fb.nodename);
+			}
+			if (xenfb->pub.update)
+				xenfb->pub.update(&xenfb->pub, x, y, w, h);
+			break;
 		}
 	}
 	mb();			/* ensure we're done with ring contents */
@@ -555,14 +570,28 @@ static void xenfb_on_fb_event64(struct x
 	rmb();			/* ensure we see ring contents up to prod */
 	for (cons = page->out_cons; cons != prod; cons++) {
 		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
+		int x, y, w, h;
 
 		switch (event->type) {
 		case XENFB_TYPE_UPDATE:
-                    if (xenfb->pub.update)
-			xenfb->pub.update(&xenfb->pub,
-					  event->update.x, event->update.y,
-					  event->update.width, event->update.height);
-                    break;
+			x = MAX(event->update.x, 0);
+			y = MAX(event->update.y, 0);
+			w = MIN(event->update.width, xenfb->pub.width - x);
+			h = MIN(event->update.height, xenfb->pub.height - y);
+			if (w < 0 || h < 0) {
+				fprintf(stderr, "%s bogus update ignored\n",
+					xenfb->fb.nodename);
+				break;
+			}
+			if (x != event->update.x || y != event->update.y
+			    || w != event->update.width
+			    || h != event->update.height) {
+				fprintf(stderr, "%s bogus update clipped\n",
+					xenfb->fb.nodename);
+			}
+			if (xenfb->pub.update)
+				xenfb->pub.update(&xenfb->pub, x, y, w, h);
+			break;
 		}
 	}
 	mb();			/* ensure we're done with ring contents */
diff --exclude '*~' -rup a/tools/xenfb/xenfb.c b/tools/xenfb/xenfb.c
--- a/tools/xenfb/xenfb.c	2008-05-05 15:56:06.000000000 +0200
+++ b/tools/xenfb/xenfb.c	2008-05-05 15:57:19.000000000 +0200
@@ -21,7 +21,8 @@
 
 #include "xenfb.h"
 
-// FIXME defend against malicious frontend?
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
 
 struct xenfb_device {
 	const char *devicetype;
@@ -734,14 +735,28 @@ static void xenfb_on_fb_event(struct xen
 	rmb();			/* ensure we see ring contents up to prod */
 	for (cons = page->out_cons; cons != prod; cons++) {
 		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
+		int x, y, w, h;
 
 		switch (event->type) {
 		case XENFB_TYPE_UPDATE:
-                    if (xenfb->pub.update)
-			xenfb->pub.update(&xenfb->pub,
-					  event->update.x, event->update.y,
-					  event->update.width, event->update.height);
-                    break;
+			x = MAX(event->update.x, 0);
+			y = MAX(event->update.y, 0);
+			w = MIN(event->update.width, xenfb->pub.width - x);
+			h = MIN(event->update.height, xenfb->pub.height - y);
+			if (w < 0 || h < 0) {
+				fprintf(stderr, "%s bogus update ignored\n",
+					xenfb->fb.nodename);
+				break;
+			}
+			if (x != event->update.x || y != event->update.y
+			    || w != event->update.width
+			    || h != event->update.height) {
+				fprintf(stderr, "%s bogus update clipped\n",
+					xenfb->fb.nodename);
+			}
+			if (xenfb->pub.update)
+				xenfb->pub.update(&xenfb->pub, x, y, w, h);
+			break;
 		}
 	}
 	mb();			/* ensure we're done with ring contents */

xen-pvfb-validate-fb.patch:

--- NEW FILE xen-pvfb-validate-fb.patch ---
Derived from
# HG changeset patch
# User Keir Fraser <keir.fraser at citrix.com>
# Date 1210687697 -3600
# Node ID 53195719f7621110dab7a97a2bca292b73baa715
# Parent  65eec0554f39049eab354abe1ee4c305f6d1e0aa
ioemu: Fix PVFB backend to validate frontend's frame buffer description

diff --exclude '*~' -rup a/tools/xenfb/oldxenfb.c b/tools/xenfb/oldxenfb.c
--- a/tools/xenfb/oldxenfb.c	2008-05-05 15:52:35.000000000 +0200
+++ b/tools/xenfb/oldxenfb.c	2008-05-05 15:47:37.000000000 +0200
@@ -405,6 +405,54 @@ static void xenfb_dev_fatal(struct xenfb
 	xenfb_switch_state(dev, XenbusStateClosing);
 }
 
+static int xenfb_configure_fb(struct xenfb_private *xenfb,
+			      int width, int height, int depth,
+			      size_t fb_len, int row_stride)
+{
+	size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd);
+	size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz;
+	size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;
+	size_t fb_len_lim = fb_pages * XC_PAGE_SIZE;
+	int max_width, max_height;
+
+	if (fb_len > fb_len_lim) {
+		fprintf(stderr,
+			"FB: frontend fb size %zu limited to %zu\n",
+			fb_len, fb_len_lim);
+	}
+	if (depth != 8 && depth != 16 && depth != 24 && depth != 32) {
+		fprintf(stderr,
+			"FB: can't handle frontend fb depth %d\n",
+			depth);
+		return -1;
+	}
+	if (row_stride < 0 || row_stride > fb_len) {
+		fprintf(stderr,
+			"FB: invalid frontend stride %d\n", row_stride);
+		return -1;
+	}
+	max_width = row_stride / (depth / 8);
+	if (width < 0 || width > max_width) {
+		fprintf(stderr,
+			"FB: invalid frontend width %d limited to %d\n",
+			width, max_width);
+		width = max_width;
+	}
+	max_height = fb_len / row_stride;
+	if (height < 0 || height > max_height) {
+		fprintf(stderr,
+			"FB: invalid frontend height %d limited to %d\n",
+			height, max_height);
+		height = max_height;
+	}
+	xenfb->fb_len = fb_len;
+	xenfb->pub.row_stride = row_stride;
+	xenfb->pub.depth = depth;
+	xenfb->pub.width = width;
+	xenfb->pub.height = height;
+	return 0;
+}
+
 int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
 {
 	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
@@ -432,14 +480,14 @@ int xenfb_attach_dom(struct xenfb *xenfb
 			    xenfb->protocol) < 0)
 		xenfb->protocol[0] = '\0';
 
-	/* TODO check for permitted ranges */
 	fb_page = xenfb->fb.page;
-	xenfb->pub.depth = fb_page->depth;
-	xenfb->pub.width = fb_page->width;
-	xenfb->pub.height = fb_page->height;
-	/* TODO check for consistency with the above */
-	xenfb->fb_len = fb_page->mem_length;
-	xenfb->pub.row_stride = fb_page->line_length;
+	if (xenfb_configure_fb(xenfb,
+			       fb_page->width, fb_page->height, fb_page->depth,
+			       fb_page->mem_length, fb_page->line_length)
+	    < 0) {
+		errno = EINVAL;
+		goto error;
+	}
 
 	if (xenfb_map_fb(xenfb, domid) < 0)
 		goto error;
diff --exclude '*~' -rup a/tools/xenfb/xenfb.c b/tools/xenfb/xenfb.c
--- a/tools/xenfb/xenfb.c	2008-05-05 15:52:35.000000000 +0200
+++ b/tools/xenfb/xenfb.c	2008-05-05 15:46:57.000000000 +0200
@@ -570,6 +570,54 @@ static void xenfb_dev_fatal(struct xenfb
 	xenfb_switch_state(dev, XenbusStateClosing);
 }
 
+static int xenfb_configure_fb(struct xenfb_private *xenfb,
+			      int width, int height, int depth,
+			      size_t fb_len, int row_stride)
+{
+	size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd);
+	size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz;
+	size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;
+	size_t fb_len_lim = fb_pages * XC_PAGE_SIZE;
+	int max_width, max_height;
+
+	if (fb_len > fb_len_lim) {
+		fprintf(stderr,
+			"FB: frontend fb size %zu limited to %zu\n",
+			fb_len, fb_len_lim);
+	}
+	if (depth != 8 && depth != 16 && depth != 24 && depth != 32) {
+		fprintf(stderr,
+			"FB: can't handle frontend fb depth %d\n",
+			depth);
+		return -1;
+	}
+	if (row_stride < 0 || row_stride > fb_len) {
+		fprintf(stderr,
+			"FB: invalid frontend stride %d\n", row_stride);
+		return -1;
+	}
+	max_width = row_stride / (depth / 8);
+	if (width < 0 || width > max_width) {
+		fprintf(stderr,
+			"FB: invalid frontend width %d limited to %d\n",
+			width, max_width);
+		width = max_width;
+	}
+	max_height = fb_len / row_stride;
+	if (height < 0 || height > max_height) {
+		fprintf(stderr,
+			"FB: invalid frontend height %d limited to %d\n",
+			height, max_height);
+		height = max_height;
+	}
+	xenfb->fb_len = fb_len;
+	xenfb->pub.row_stride = row_stride;
+	xenfb->pub.depth = depth;
+	xenfb->pub.width = width;
+	xenfb->pub.height = height;
+	return 0;
+}
+
 int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
 {
 	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
@@ -630,14 +678,14 @@ int xenfb_attach_dom(struct xenfb *xenfb
 		xenfb->protocol[0] = '\0';
 	xenfb_xs_printf(xsh, xenfb->fb.nodename, "request-update", "1");
 
-	/* TODO check for permitted ranges */
 	fb_page = xenfb->fb.page;
-	xenfb->pub.depth = fb_page->depth;
-	xenfb->pub.width = fb_page->width;
-	xenfb->pub.height = fb_page->height;
-	/* TODO check for consistency with the above */
-	xenfb->fb_len = fb_page->mem_length;
-	xenfb->pub.row_stride = fb_page->line_length;
+	if (xenfb_configure_fb(xenfb,
+			       fb_page->width, fb_page->height, fb_page->depth,
+			       fb_page->mem_length, fb_page->line_length)
+	    < 0) {
+		errno = EINVAL;
+		goto error;
+	}
 
 	if (xenfb_map_fb(xenfb, domid) < 0)
 		goto error;

xen-qemu-block-no-auto-format.patch:

--- NEW FILE xen-qemu-block-no-auto-format.patch ---
It is possible for a guest with a raw formatted disk image to write a
header to that disk image describing another format (such as qcow).
Stopping and subsequent restart of the guest will cause QEMU to detect
that format, and could allow the guest to read any host file.

The patch extends the backend device description in xenstore by an
optional format node.  It makes xend force the raw format there,
unless enable-image-format-probing is true in its configuration.

This protects everybody from the vulnerability by default, but breaks
images with formats other than raw.  None of our tools creates such
images.  People who somehow created them themselves can choose to
switch back to format auto-detection, relinquishing protection.

diff --exclude '*~' -rup a/tools/examples/xend-config.sxp b/tools/examples/xend-config.sxp
--- a/tools/examples/xend-config.sxp	2008-05-05 15:49:05.000000000 +0200
+++ b/tools/examples/xend-config.sxp	2008-05-05 15:51:34.000000000 +0200
@@ -207,4 +207,7 @@
 # when not specififed in VM's configuration
 #(keymap 'en-us')
 
-
+# Allow probing of disk image file format.  This is insecure!  It lets
+# a malicious domU read any file in dom0.  Applies only to fully
+# virtual domUs.  Required for using formats other than raw.
+#(enable-image-format-probing no)
diff --exclude '*~' -rup a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c	2007-11-15 00:35:27.000000000 +0100
+++ b/tools/ioemu/xenstore.c	2008-05-05 15:50:49.000000000 +0200
@@ -82,9 +82,10 @@ void xenstore_parse_domain_config(int do
     char **e = NULL;
     char *buf = NULL, *path;
     char *fpath = NULL, *bpath = NULL,
-        *dev = NULL, *params = NULL, *type = NULL;
+        *dev = NULL, *params = NULL, *type = NULL, *format = NULL;
     int i, is_scsi;
     unsigned int len, num, hd_index;
+    BlockDriver *drv;
 
     for(i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++)
         media_filename[i] = NULL;
@@ -140,6 +141,18 @@ void xenstore_parse_domain_config(int do
         params = xs_read(xsh, XBT_NULL, buf, &len);
         if (params == NULL)
             continue;
+        if (pasprintf(&buf, "%s/format", bpath) == -1)
+            continue;
+        free(format);
+        format = xs_read(xsh, XBT_NULL, buf, &len);
+        if (format) {
+            drv = bdrv_find_format(format);
+	    if (!drv) {
+		fprintf(logfile, "invalid format '%s' for %s\n", format, bpath);
+		continue;
+	    }
+	} else
+	    drv = NULL;
         /* 
          * check if device has a phantom vbd; the phantom is hooked
          * to the frontend device (for ease of cleanup), so lookup 
@@ -173,8 +186,8 @@ void xenstore_parse_domain_config(int do
         }
         /* open device now if media present */
         if (params[0]) {
-            if (bdrv_open(bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)],
-                          params, 0 /* snapshot */) < 0)
+            if (bdrv_open2(bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)],
+			   params, 0 /* snapshot */, drv) < 0)
                 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
                         params);
         }
@@ -189,6 +202,7 @@ void xenstore_parse_domain_config(int do
 
  out:
     free(type);
+    free(format);
     free(params);
     free(dev);
     free(bpath);
diff --exclude '*~' -rup a/tools/python/xen/xend/XendOptions.py b/tools/python/xen/xend/XendOptions.py
--- a/tools/python/xen/xend/XendOptions.py	2007-11-15 00:35:27.000000000 +0100
+++ b/tools/python/xen/xend/XendOptions.py	2008-05-05 15:50:49.000000000 +0200
@@ -127,6 +127,9 @@ class XendOptions:
         """
         print >>sys.stderr, "xend [ERROR]", fmt % args
 
+    def get_enable_image_format_probing(self):
+        return self.get_config_bool('enable-image-format-probing', 'no')
+
 
     def configure(self):
         self.set_config()
diff --exclude '*~' -rup a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py
--- a/tools/python/xen/xend/server/blkif.py	2008-05-05 15:49:05.000000000 +0200
+++ b/tools/python/xen/xend/server/blkif.py	2008-05-05 15:50:49.000000000 +0200
@@ -21,6 +21,7 @@ import string
 
 from xen.util import blkif
 from xen.util import security
+from xen.xend import XendOptions
 from xen.xend.XendError import VmError
 from xen.xend.server.DevController import DevController
 
@@ -78,6 +79,10 @@ class BlkifController(DevController):
                          'acm_ssidref': str(ssidref),
                          'acm_policy' : policy})
 
+        xoptions = XendOptions.instance()
+        if not xoptions.get_enable_image_format_probing():
+            back.update({'format' : 'raw'})
+
         devid = blkif.blkdev_name_to_number(dev)
         if devid is None:
             raise VmError('Unable to find number for device (%s)' % (dev))


Index: xen.spec
===================================================================
RCS file: /cvs/pkgs/rpms/xen/F-7/xen.spec,v
retrieving revision 1.190
retrieving revision 1.191
diff -u -r1.190 -r1.191
--- xen.spec	28 Feb 2008 00:59:25 -0000	1.190
+++ xen.spec	14 May 2008 15:55:02 -0000	1.191
@@ -3,7 +3,7 @@
 Summary: Xen is a virtual machine monitor
 Name:    xen
 Version: 3.1.2
-Release: 2%{dist}
+Release: 3%{dist}
 Group:   Development/Libraries
 License: GPL
 URL:     http://www.cl.cam.ac.uk/Research/SRG/netos/xen/index.html
@@ -33,6 +33,10 @@
 Patch152: xen-pvfb-no-hvm.patch
 Patch153: xen-pvfb-compat-32-on-64.patch
 
+Patch168: xen-pvfb-validate-fb.patch
+Patch169: xen-pvfb-bogus-update.patch
+Patch170: xen-qemu-block-no-auto-format.patch
+
 Patch251: pygrub-manykernels.patch
 
 # Performance fix for listing domains
@@ -131,6 +135,11 @@
 %patch152 -p1
 %patch153 -p1
 
+# QEMU security fixes
+%patch168 -p1
+%patch169 -p1
+%patch170 -p1
+
 # upstream patches
 %patch251 -p1
 
@@ -270,6 +279,11 @@
 %{_libdir}/*.a
 
 %changelog
+* Wed May 14 2008 Markus Armbruster <armbru at redhat.com> - 3.1.2-3.fc7
+- Disable QEMU image format auto-detection (CVE-2008-2004)
+- Fix PVFB to validate frame buffer description (CVE-2008-1943)
+- Fix PVFB to cope with bogus update requests (CVE-2008-1944)
+
 * Sat Feb 23 2008 Daniel P. Berrange <berrange at redhat.com> - 3.1.2-2.fc7
 - Fix block device extents check (rhbz #433560)
 




More information about the scm-commits mailing list