Blob Blame History Raw
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-04-25 15:42:56.000000000 +0200
+++ b/tools/examples/xend-config.sxp	2008-05-05 14:48:34.000000000 +0200
@@ -236,3 +236,8 @@
 # checking uncomment this:
 #
 # (vnc-x509-verify 1)
+
+# 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	2008-04-25 15:42:56.000000000 +0200
+++ b/tools/ioemu/xenstore.c	2008-05-05 14:50:17.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	2008-04-25 15:42:56.000000000 +0200
+++ b/tools/python/xen/xend/XendOptions.py	2008-05-05 14:48:48.000000000 +0200
@@ -299,6 +299,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 --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-04-25 15:42:56.000000000 +0200
+++ b/tools/python/xen/xend/server/blkif.py	2008-05-05 14:50:16.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))