Markus Armbruster dfed210
It is possible for a guest with a raw formatted disk image to write a
Markus Armbruster dfed210
header to that disk image describing another format (such as qcow).
Markus Armbruster dfed210
Stopping and subsequent restart of the guest will cause QEMU to detect
Markus Armbruster dfed210
that format, and could allow the guest to read any host file.
Markus Armbruster dfed210
Markus Armbruster dfed210
The patch extends the backend device description in xenstore by an
Markus Armbruster dfed210
optional format node.  It makes xend force the raw format there,
Markus Armbruster dfed210
unless enable-image-format-probing is true in its configuration.
Markus Armbruster dfed210
Markus Armbruster dfed210
This protects everybody from the vulnerability by default, but breaks
Markus Armbruster dfed210
images with formats other than raw.  None of our tools creates such
Markus Armbruster dfed210
images.  People who somehow created them themselves can choose to
Markus Armbruster dfed210
switch back to format auto-detection, relinquishing protection.
Markus Armbruster dfed210
Markus Armbruster dfed210
diff -rup --exclude '*~' a/tools/examples/xend-config.sxp b/tools/examples/xend-config.sxp
Markus Armbruster dfed210
--- a/tools/examples/xend-config.sxp	2008-04-22 18:53:55.000000000 +0200
Markus Armbruster dfed210
+++ b/tools/examples/xend-config.sxp	2008-05-05 14:19:07.000000000 +0200
Markus Armbruster dfed210
@@ -240,3 +240,8 @@
Markus Armbruster dfed210
 
Markus Armbruster dfed210
 # Script to run when the label of a resource has changed.
Markus Armbruster dfed210
 #(resource-label-change-script '')
Markus Armbruster dfed210
+
Markus Armbruster dfed210
+# Allow probing of disk image file format.  This is insecure!  It lets
Markus Armbruster dfed210
+# a malicious domU read any file in dom0.  Applies only to fully
Markus Armbruster dfed210
+# virtual domUs.  Required for using formats other than raw.
Markus Armbruster dfed210
+#(enable-image-format-probing no)
Markus Armbruster dfed210
diff -rup --exclude '*~' a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c
Markus Armbruster dfed210
--- a/tools/ioemu/xenstore.c	2008-01-16 19:34:59.000000000 +0100
Markus Armbruster dfed210
+++ b/tools/ioemu/xenstore.c	2008-05-05 14:28:34.000000000 +0200
Markus Armbruster dfed210
@@ -83,8 +83,10 @@ void xenstore_parse_domain_config(int do
Markus Armbruster dfed210
     char *buf = NULL, *path;
Markus Armbruster dfed210
     char *fpath = NULL, *bpath = NULL,
Markus Armbruster dfed210
         *dev = NULL, *params = NULL, *type = NULL, *drv = NULL;
Markus Armbruster dfed210
+    char *format = NULL;
Markus Armbruster dfed210
     int i, is_scsi, is_hdN = 0;
Markus Armbruster dfed210
     unsigned int len, num, hd_index;
Markus Armbruster dfed210
+    BlockDriver *bdrv;
Markus Armbruster dfed210
 
Markus Armbruster dfed210
     for(i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++)
Markus Armbruster dfed210
         media_filename[i] = NULL;
Markus Armbruster dfed210
@@ -185,6 +187,19 @@ void xenstore_parse_domain_config(int do
Markus Armbruster dfed210
             fprintf(logfile, "Strip off blktap sub-type prefix to %s\n", params); 
Markus Armbruster dfed210
         }
Markus Armbruster dfed210
 
Markus Armbruster dfed210
+	if (pasprintf(&buf, "%s/format", bpath) == -1)
Markus Armbruster dfed210
+	    continue;
Markus Armbruster dfed210
+	free(format);
Markus Armbruster dfed210
+	format = xs_read(xsh, XBT_NULL, buf, &len;;
Markus Armbruster dfed210
+	if (format) {
Markus Armbruster dfed210
+	    bdrv = bdrv_find_format(format);
Markus Armbruster dfed210
+	    if (!bdrv) {
Markus Armbruster dfed210
+		fprintf(logfile, "invalid format '%s' for %s\n", format, bpath);
Markus Armbruster dfed210
+		continue;
Markus Armbruster dfed210
+	    }
Markus Armbruster dfed210
+	} else
Markus Armbruster dfed210
+	    bdrv = NULL;
Markus Armbruster dfed210
+
Markus Armbruster dfed210
         /* 
Markus Armbruster dfed210
          * check if device has a phantom vbd; the phantom is hooked
Markus Armbruster dfed210
          * to the frontend device (for ease of cleanup), so lookup 
Markus Armbruster dfed210
@@ -218,8 +233,8 @@ void xenstore_parse_domain_config(int do
Markus Armbruster dfed210
         }
Markus Armbruster dfed210
         /* open device now if media present */
Markus Armbruster dfed210
         if (params[0]) {
Markus Armbruster dfed210
-            if (bdrv_open(bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)],
Markus Armbruster dfed210
-                          params, 0 /* snapshot */) < 0)
Markus Armbruster dfed210
+            if (bdrv_open2(bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)],
Markus Armbruster dfed210
+			   params, 0 /* snapshot */, drv) < 0)
Markus Armbruster dfed210
                 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
Markus Armbruster dfed210
                         params);
Markus Armbruster dfed210
         }
Markus Armbruster dfed210
@@ -242,6 +257,7 @@ void xenstore_parse_domain_config(int do
Markus Armbruster dfed210
  out:
Markus Armbruster dfed210
     free(type);
Markus Armbruster dfed210
     free(params);
Markus Armbruster dfed210
+    free(format);
Markus Armbruster dfed210
     free(dev);
Markus Armbruster dfed210
     free(bpath);
Markus Armbruster dfed210
     free(buf);
Markus Armbruster dfed210
diff -rup --exclude '*~' a/tools/python/xen/xend/XendOptions.py b/tools/python/xen/xend/XendOptions.py
Markus Armbruster dfed210
--- a/tools/python/xen/xend/XendOptions.py	2008-01-16 19:34:59.000000000 +0100
Markus Armbruster dfed210
+++ b/tools/python/xen/xend/XendOptions.py	2008-05-05 14:36:23.000000000 +0200
Markus Armbruster dfed210
@@ -314,6 +314,9 @@ class XendOptions:
Markus Armbruster dfed210
     def get_vnc_x509_verify(self):
Markus Armbruster dfed210
         return self.get_config_string('vnc-x509-verify', self.xend_vnc_x509_verify)
Markus Armbruster dfed210
 
Markus Armbruster dfed210
+    def get_enable_image_format_probing(self):
Markus Armbruster dfed210
+        return self.get_config_bool('enable-image-format-probing', 'no')
Markus Armbruster dfed210
+
Markus Armbruster dfed210
 
Markus Armbruster dfed210
 class XendOptionsFile(XendOptions):
Markus Armbruster dfed210
 
Markus Armbruster dfed210
diff -rup --exclude '*~' a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py
Markus Armbruster dfed210
--- a/tools/python/xen/xend/server/blkif.py	2008-01-16 19:34:59.000000000 +0100
Markus Armbruster dfed210
+++ b/tools/python/xen/xend/server/blkif.py	2008-05-05 14:36:22.000000000 +0200
Markus Armbruster dfed210
@@ -21,6 +21,7 @@ import string
Markus Armbruster dfed210
 
Markus Armbruster dfed210
 from xen.util import blkif
Markus Armbruster dfed210
 import xen.util.xsm.xsm as security
Markus Armbruster dfed210
+from xen.xend import XendOptions
Markus Armbruster dfed210
 from xen.xend.XendError import VmError
Markus Armbruster dfed210
 from xen.xend.server.DevController import DevController
Markus Armbruster dfed210
 
Markus Armbruster dfed210
@@ -75,6 +76,10 @@ class BlkifController(DevController):
Markus Armbruster dfed210
         if security.on():
Markus Armbruster dfed210
             self.do_access_control(config, uname)
Markus Armbruster dfed210
 
Markus Armbruster dfed210
+        xoptions = XendOptions.instance()
Markus Armbruster dfed210
+        if not xoptions.get_enable_image_format_probing():
Markus Armbruster dfed210
+            back.update({'format' : 'raw'})
Markus Armbruster dfed210
+
Markus Armbruster dfed210
         devid = blkif.blkdev_name_to_number(dev)
Markus Armbruster dfed210
         if devid is None:
Markus Armbruster dfed210
             raise VmError('Unable to find number for device (%s)' % (dev))