From 1ef04ffe523881303a0e17e70f5b64db9f54aec0 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: May 14 2008 16:08:56 +0000 Subject: Disable QEMU image format auto-detection (CVE-2008-2004) Fix PVFB to validate frame buffer description (CVE-2008-1943) --- diff --git a/xen-pvfb-validate-fb.patch b/xen-pvfb-validate-fb.patch new file mode 100644 index 0000000..965671b --- /dev/null +++ b/xen-pvfb-validate-fb.patch @@ -0,0 +1,109 @@ +Derived from +# HG changeset patch +# User Keir Fraser +# Date 1210687697 -3600 +# Node ID 53195719f7621110dab7a97a2bca292b73baa715 +# Parent 65eec0554f39049eab354abe1ee4c305f6d1e0aa +ioemu: Fix PVFB backend to validate frontend's frame buffer description + +diff -rup a/tools/ioemu/hw/xenfb.c b/tools/ioemu/hw/xenfb.c +--- a/tools/ioemu/hw/xenfb.c 2008-04-22 18:51:35.000000000 +0200 ++++ b/tools/ioemu/hw/xenfb.c 2008-04-22 18:52:07.000000000 +0200 +@@ -23,8 +23,6 @@ + #define BTN_LEFT 0x110 /* from */ + #endif + +-// FIXME defend against malicious frontend? +- + struct xenfb; + + struct xenfb_device { +@@ -476,6 +474,55 @@ void xenfb_shutdown(struct xenfb *xenfb) + free(xenfb); + } + ++static int xenfb_configure_fb(struct xenfb *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->row_stride = row_stride; ++ xenfb->depth = depth; ++ xenfb->width = width; ++ xenfb->height = height; ++ fprintf(stderr, "Framebuffer %dx%dx%d stride %d\n", ++ width, height, depth, row_stride); ++ return 0; ++} + + static void xenfb_on_fb_event(struct xenfb *xenfb) + { +@@ -506,7 +553,6 @@ static void xenfb_on_fb_event(struct xen + || h != event->update.height) { + fprintf(stderr, "%s bogus update clipped\n", + xenfb->fb.nodename); +- break; + } + xenfb_guest_copy(xenfb, x, y, w, h); + break; +@@ -686,16 +732,15 @@ static int xenfb_read_frontend_fb_config + xenfb->protocol[0] = '\0'; + xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1"); + +- /* TODO check for permitted ranges */ + fb_page = xenfb->fb.page; +- xenfb->depth = fb_page->depth; +- xenfb->width = fb_page->width; +- xenfb->height = fb_page->height; +- /* TODO check for consistency with the above */ +- xenfb->fb_len = fb_page->mem_length; +- xenfb->row_stride = fb_page->line_length; +- fprintf(stderr, "Framebuffer depth %d width %d height %d line %d\n", +- fb_page->depth, fb_page->width, fb_page->height, 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; ++ return -1; ++ } ++ + if (xenfb_map_fb(xenfb, xenfb->fb.otherend_id) < 0) + return -1; + diff --git a/xen-qemu-block-no-auto-format.patch b/xen-qemu-block-no-auto-format.patch new file mode 100644 index 0000000..ace04ae --- /dev/null +++ b/xen-qemu-block-no-auto-format.patch @@ -0,0 +1,114 @@ +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 -rup --exclude '*~' a/tools/examples/xend-config.sxp b/tools/examples/xend-config.sxp +--- a/tools/examples/xend-config.sxp 2008-04-22 18:53:55.000000000 +0200 ++++ b/tools/examples/xend-config.sxp 2008-05-05 14:19:07.000000000 +0200 +@@ -240,3 +240,8 @@ + + # Script to run when the label of a resource has changed. + #(resource-label-change-script '') ++ ++# 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 -rup --exclude '*~' a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c +--- a/tools/ioemu/xenstore.c 2008-01-16 19:34:59.000000000 +0100 ++++ b/tools/ioemu/xenstore.c 2008-05-05 14:28:34.000000000 +0200 +@@ -83,8 +83,10 @@ void xenstore_parse_domain_config(int do + char *buf = NULL, *path; + char *fpath = NULL, *bpath = NULL, + *dev = NULL, *params = NULL, *type = NULL, *drv = NULL; ++ char *format = NULL; + int i, is_scsi, is_hdN = 0; + unsigned int len, num, hd_index; ++ BlockDriver *bdrv; + + for(i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++) + media_filename[i] = NULL; +@@ -185,6 +187,19 @@ void xenstore_parse_domain_config(int do + fprintf(logfile, "Strip off blktap sub-type prefix to %s\n", params); + } + ++ if (pasprintf(&buf, "%s/format", bpath) == -1) ++ continue; ++ free(format); ++ format = xs_read(xsh, XBT_NULL, buf, &len); ++ if (format) { ++ bdrv = bdrv_find_format(format); ++ if (!bdrv) { ++ fprintf(logfile, "invalid format '%s' for %s\n", format, bpath); ++ continue; ++ } ++ } else ++ bdrv = NULL; ++ + /* + * check if device has a phantom vbd; the phantom is hooked + * to the frontend device (for ease of cleanup), so lookup +@@ -218,8 +233,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); + } +@@ -242,6 +257,7 @@ void xenstore_parse_domain_config(int do + out: + free(type); + free(params); ++ free(format); + free(dev); + free(bpath); + free(buf); +diff -rup --exclude '*~' a/tools/python/xen/xend/XendOptions.py b/tools/python/xen/xend/XendOptions.py +--- a/tools/python/xen/xend/XendOptions.py 2008-01-16 19:34:59.000000000 +0100 ++++ b/tools/python/xen/xend/XendOptions.py 2008-05-05 14:36:23.000000000 +0200 +@@ -314,6 +314,9 @@ class XendOptions: + def get_vnc_x509_verify(self): + return self.get_config_string('vnc-x509-verify', self.xend_vnc_x509_verify) + ++ def get_enable_image_format_probing(self): ++ return self.get_config_bool('enable-image-format-probing', 'no') ++ + + class XendOptionsFile(XendOptions): + +diff -rup --exclude '*~' 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-01-16 19:34:59.000000000 +0100 ++++ b/tools/python/xen/xend/server/blkif.py 2008-05-05 14:36:22.000000000 +0200 +@@ -21,6 +21,7 @@ import string + + from xen.util import blkif + import xen.util.xsm.xsm as security ++from xen.xend import XendOptions + from xen.xend.XendError import VmError + from xen.xend.server.DevController import DevController + +@@ -75,6 +76,10 @@ class BlkifController(DevController): + if security.on(): + self.do_access_control(config, uname) + ++ 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)) diff --git a/xen.spec b/xen.spec index bf39ea9..cea82b9 100644 --- a/xen.spec +++ b/xen.spec @@ -2,7 +2,7 @@ # Always set these 3 tags %define base_version 3.2.0 -%define base_release 10 +%define base_release 11 # Hypervisor ABI %define hv_abi 3.2 @@ -76,6 +76,8 @@ Patch17: xen-3.2.0-qemu-evtchn-fd.patch Patch18: xen-qemu-logfile.patch Patch36: xen-qemu-bootmenu.patch +Patch37: xen-pvfb-validate-fb.patch +Patch38: xen-qemu-block-no-auto-format.patch # Patches to modify the default config of xend Patch100: xen-config-dom0-minmem.patch @@ -178,6 +180,9 @@ which manage Xen virtual machines. %patch36 -p1 +%patch37 -p1 +%patch38 -p1 + # config patches %patch100 -p1 %patch102 -p1 @@ -457,6 +462,10 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/*.a %changelog +* Wed May 14 2008 Markus Armbruster - 3.2.0-11.fc10 +- Disable QEMU image format auto-detection (CVE-2008-2004) +- Fix PVFB to validate frame buffer description (CVE-2008-1943) + * Wed Feb 27 2008 Daniel P. Berrange - 3.2.0-10.fc9 - Fix block device checks for extendable disk formats