[xen] Fix privilege escalation from untrusted guest, remove unused Requires:

myoung myoung at fedoraproject.org
Mon May 9 22:17:00 UTC 2011


commit f1397f37927368acbf47514c810809d546b35fb2
Author: Michael Young <m.a.young at durham.ac.uk>
Date:   Mon May 9 23:14:32 2011 +0100

    Fix privilege escalation from untrusted guest, remove unused Requires:

 cve-2011-1583-4.1.patch |  217 +++++++++++++++++++++++++++++++++++++++++++++++
 xen.spec                |   13 +++-
 2 files changed, 228 insertions(+), 2 deletions(-)
---
diff --git a/cve-2011-1583-4.1.patch b/cve-2011-1583-4.1.patch
new file mode 100644
index 0000000..e3f4e8c
--- /dev/null
+++ b/cve-2011-1583-4.1.patch
@@ -0,0 +1,217 @@
+diff -r dbf2ddf652dc tools/libxc/xc_dom_bzimageloader.c
+--- a/tools/libxc/xc_dom_bzimageloader.c	Thu Apr 07 15:26:58 2011 +0100
++++ b/tools/libxc/xc_dom_bzimageloader.c	Thu Apr 21 12:05:57 2011 +0100
+@@ -82,8 +82,29 @@ static int xc_try_bzip2_decode(
+     for ( ; ; )
+     {
+         ret = BZ2_bzDecompress(&stream);
+-        if ( (stream.avail_out == 0) || (ret != BZ_OK) )
++        if ( ret == BZ_STREAM_END )
+         {
++            DOMPRINTF("BZIP2: Saw data stream end");
++            retval = 0;
++            break;
++        }
++        if ( ret != BZ_OK )
++        {
++            DOMPRINTF("BZIP2: error %d", ret);
++            free(out_buf);
++            goto bzip2_cleanup;
++        }
++
++        if ( stream.avail_out == 0 )
++        {
++            /* Protect against output buffer overflow */
++            if ( outsize > INT_MAX / 2 )
++            {
++                DOMPRINTF("BZIP2: output buffer overflow");
++                free(out_buf);
++                goto bzip2_cleanup;
++            }
++
+             tmp_buf = realloc(out_buf, outsize * 2);
+             if ( tmp_buf == NULL )
+             {
+@@ -97,16 +118,18 @@ static int xc_try_bzip2_decode(
+             stream.avail_out = (outsize * 2) - outsize;
+             outsize *= 2;
+         }
+-
+-        if ( ret != BZ_OK )
++        else if ( stream.avail_in == 0 )
+         {
+-            if ( ret == BZ_STREAM_END )
+-            {
+-                DOMPRINTF("BZIP2: Saw data stream end");
+-                retval = 0;
+-                break;
+-            }
+-            DOMPRINTF("BZIP2: error");
++            /*
++             * If there is output buffer available then this indicates
++             * that BZ2_bzDecompress would like more input data to be
++             * provided.  However our complete input buffer is in
++             * memory and provided upfront so if avail_in is zero this
++             * actually indicates a truncated input.
++             */
++            DOMPRINTF("BZIP2: not enough input");
++            free(out_buf);
++            goto bzip2_cleanup;
+         }
+     }
+ 
+@@ -180,31 +203,14 @@ static int xc_try_lzma_decode(
+     for ( ; ; )
+     {
+         ret = lzma_code(&stream, action);
+-        if ( (stream.avail_out == 0) || (ret != LZMA_OK) )
++        if ( ret == LZMA_STREAM_END )
+         {
+-            tmp_buf = realloc(out_buf, outsize * 2);
+-            if ( tmp_buf == NULL )
+-            {
+-                DOMPRINTF("LZMA: Failed to realloc memory");
+-                free(out_buf);
+-                goto lzma_cleanup;
+-            }
+-            out_buf = tmp_buf;
+-
+-            stream.next_out = out_buf + outsize;
+-            stream.avail_out = (outsize * 2) - outsize;
+-            outsize *= 2;
++            DOMPRINTF("LZMA: Saw data stream end");
++            retval = 0;
++            break;
+         }
+-
+         if ( ret != LZMA_OK )
+         {
+-            if ( ret == LZMA_STREAM_END )
+-            {
+-                DOMPRINTF("LZMA: Saw data stream end");
+-                retval = 0;
+-                break;
+-            }
+-
+             switch ( ret )
+             {
+             case LZMA_MEM_ERROR:
+@@ -238,7 +244,32 @@ static int xc_try_lzma_decode(
+             }
+             DOMPRINTF("%s: LZMA decompression error %s",
+                       __FUNCTION__, msg);
+-            break;
++            free(out_buf);
++            goto lzma_cleanup;
++        }
++
++        if ( stream.avail_out == 0 )
++        {
++            /* Protect against output buffer overflow */
++            if ( outsize > INT_MAX / 2 )
++            {
++                DOMPRINTF("LZMA: output buffer overflow");
++                free(out_buf);
++                goto lzma_cleanup;
++            }
++
++            tmp_buf = realloc(out_buf, outsize * 2);
++            if ( tmp_buf == NULL )
++            {
++                DOMPRINTF("LZMA: Failed to realloc memory");
++                free(out_buf);
++                goto lzma_cleanup;
++            }
++            out_buf = tmp_buf;
++
++            stream.next_out = out_buf + outsize;
++            stream.avail_out = (outsize * 2) - outsize;
++            outsize *= 2;
+         }
+     }
+ 
+@@ -489,18 +520,18 @@ struct setup_header {
+ 
+ extern struct xc_dom_loader elf_loader;
+ 
+-static unsigned int payload_offset(struct setup_header *hdr)
++static int check_magic(struct xc_dom_image *dom, const void *magic, size_t len)
+ {
+-    unsigned int off;
++    if (len > dom->kernel_size)
++        return 0;
+ 
+-    off = (hdr->setup_sects + 1) * 512;
+-    off += hdr->payload_offset;
+-    return off;
++    return (memcmp(dom->kernel_blob, magic, len) == 0);
+ }
+ 
+ static int xc_dom_probe_bzimage_kernel(struct xc_dom_image *dom)
+ {
+     struct setup_header *hdr;
++    uint64_t payload_offset, payload_length;
+     int ret;
+ 
+     if ( dom->kernel_blob == NULL )
+@@ -533,10 +564,30 @@ static int xc_dom_probe_bzimage_kernel(s
+         return -EINVAL;
+     }
+ 
+-    dom->kernel_blob = dom->kernel_blob + payload_offset(hdr);
+-    dom->kernel_size = hdr->payload_length;
+ 
+-    if ( memcmp(dom->kernel_blob, "\037\213", 2) == 0 )
++    /* upcast to 64 bits to avoid overflow */
++    /* setup_sects is u8 and so cannot overflow */
++    payload_offset = (hdr->setup_sects + 1) * 512;
++    payload_offset += hdr->payload_offset;
++    payload_length = hdr->payload_length;
++
++    if ( payload_offset >= dom->kernel_size )
++    {
++        xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: payload offset overflow",
++                     __FUNCTION__);
++        return -EINVAL;
++    }
++    if ( (payload_offset + payload_length) > dom->kernel_size )
++    {
++        xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: payload length overflow",
++                     __FUNCTION__);
++        return -EINVAL;
++    }
++
++    dom->kernel_blob = dom->kernel_blob + payload_offset;
++    dom->kernel_size = payload_length;
++
++    if ( check_magic(dom, "\037\213", 2) )
+     {
+         ret = xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
+         if ( ret == -1 )
+@@ -546,7 +597,7 @@ static int xc_dom_probe_bzimage_kernel(s
+             return -EINVAL;
+         }
+     }
+-    else if ( memcmp(dom->kernel_blob, "\102\132\150", 3) == 0 )
++    else if ( check_magic(dom, "\102\132\150", 3) )
+     {
+         ret = xc_try_bzip2_decode(dom, &dom->kernel_blob, &dom->kernel_size);
+         if ( ret < 0 )
+@@ -557,7 +608,7 @@ static int xc_dom_probe_bzimage_kernel(s
+             return -EINVAL;
+         }
+     }
+-    else if ( memcmp(dom->kernel_blob, "\135\000", 2) == 0 )
++    else if ( check_magic(dom, "\135\000", 2) )
+     {
+         ret = xc_try_lzma_decode(dom, &dom->kernel_blob, &dom->kernel_size);
+         if ( ret < 0 )
+@@ -568,7 +619,7 @@ static int xc_dom_probe_bzimage_kernel(s
+             return -EINVAL;
+         }
+     }
+-    else if ( memcmp(dom->kernel_blob, "\x89LZO", 5) == 0 )
++    else if ( check_magic(dom, "\x89LZO", 5) )
+     {
+         ret = xc_try_lzo1x_decode(dom, &dom->kernel_blob, &dom->kernel_size);
+         if ( ret < 0 )
diff --git a/xen.spec b/xen.spec
index 608c49c..455c57e 100644
--- a/xen.spec
+++ b/xen.spec
@@ -6,7 +6,7 @@
 Summary: Xen is a virtual machine monitor
 Name:    xen
 Version: 4.1.0
-Release: 1%{?dist}
+Release: 2%{?dist}
 Group:   Development/Libraries
 License: GPLv2+ and LGPLv2+ and BSD
 URL:     http://xen.org/
@@ -42,6 +42,7 @@ Patch20: localgcc451fix.patch
 Patch23: grub-ext4-support.patch
 Patch26: localgcc46fix.patch
 Patch28: pygrubfix.patch
+Patch29: cve-2011-1583-4.1.patch
 
 Patch100: xen-configure-xend.patch
 
@@ -105,7 +106,8 @@ which manage Xen virtual machines.
 Summary: Core Xen runtime environment
 Group: Development/Libraries
 Requires: xen-libs = %{version}-%{release}
-Requires: /usr/bin/qemu-img /usr/bin/qemu-nbd
+#Requires: /usr/bin/qemu-img /usr/bin/qemu-nbd
+Requires: /usr/bin/qemu-img
 # Ensure we at least have a suitable kernel installed, though we can't
 # force user to actually boot it.
 Requires: xen-hypervisor-abi = %{hv_abi}
@@ -166,6 +168,7 @@ to build the xen packages.
 %patch20 -p1
 %patch26 -p1
 %patch28 -p1
+%patch29 -p1
 
 %patch100 -p1
 
@@ -531,6 +534,12 @@ rm -rf %{buildroot}
 %doc licensedir/*
 
 %changelog
+* Mon May 09 2011 Michael Young <m.a.young at durham.ac.uk> - 4.1.0-2
+- Overflows in kernel decompression can allow root on xen PV guest to gain
+  privileged access to base domain, or access to xen configuration info.
+  Lack of error checking could allow DoS attack from guest [CVE-2011-1583]
+- Don't require /usr/bin/qemu-nbd as it isn't used at present.
+
 * Fri Mar 25 2011 Michael Young <m.a.young at durham.ac.uk> - 4.1.0-1
 - update to 4.1.0 final
 


More information about the scm-commits mailing list