[xen/f13] Fix privilege escalation from untrusted guest

myoung myoung at fedoraproject.org
Sat May 21 19:05:35 UTC 2011


commit aa59e33e2c642b02ebe02d4d53bdcb7d2f61bccf
Author: Michael Young <m.a.young at durham.ac.uk>
Date:   Sat May 21 20:04:08 2011 +0100

    Fix privilege escalation from untrusted guest

 cve-2011-1583-4.0.patch |  208 +++++++++++++++++++++++++++++++++++++++++++++++
 xen.spec                |    9 ++-
 2 files changed, 216 insertions(+), 1 deletions(-)
---
diff --git a/cve-2011-1583-4.0.patch b/cve-2011-1583-4.0.patch
new file mode 100644
index 0000000..bc431c5
--- /dev/null
+++ b/cve-2011-1583-4.0.patch
@@ -0,0 +1,208 @@
+diff -r dbbc61c48da4 tools/libxc/xc_dom_bzimageloader.c
+--- a/tools/libxc/xc_dom_bzimageloader.c	Wed Apr 13 09:48:17 2011 +0100
++++ b/tools/libxc/xc_dom_bzimageloader.c	Thu Apr 21 11:57:06 2011 +0100
+@@ -68,8 +68,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 )
+         {
++            xc_dom_printf("BZIP2: Saw data stream end\n");
++            retval = 0;
++            break;
++        }
++        if ( ret != BZ_OK )
++        {
++            xc_dom_printf("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 )
++            {
++                xc_dom_printf("BZIP2: output buffer overflow\n");
++                free(out_buf);
++                goto bzip2_cleanup;
++            }
++
+             tmp_buf = realloc(out_buf, outsize * 2);
+             if ( tmp_buf == NULL )
+             {
+@@ -83,16 +104,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 )
+-            {
+-                xc_dom_printf("BZIP2: Saw data stream end\n");
+-                retval = 0;
+-                break;
+-            }
+-            xc_dom_printf("BZIP2: error\n");
++            /*
++             * 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.
++             */
++            xc_dom_printf("BZIP2: not enough input\n");
++            free(out_buf);
++            goto bzip2_cleanup;
+         }
+     }
+ 
+@@ -187,31 +210,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 )
+-            {
+-                xc_dom_printf("LZMA: Failed to realloc memory\n");
+-                free(out_buf);
+-                goto lzma_cleanup;
+-            }
+-            out_buf = tmp_buf;
+-
+-            stream.next_out = out_buf + outsize;
+-            stream.avail_out = (outsize * 2) - outsize;
+-            outsize *= 2;
++            xc_dom_printf("LZMA: Saw data stream end\n");
++            retval = 0;
++            break;
+         }
+-
+         if ( ret != LZMA_OK )
+         {
+-            if ( ret == LZMA_STREAM_END )
+-            {
+-                xc_dom_printf("LZMA: Saw data stream end\n");
+-                retval = 0;
+-                break;
+-            }
+-
+             switch ( ret )
+             {
+             case LZMA_MEM_ERROR:
+@@ -245,7 +251,32 @@ static int xc_try_lzma_decode(
+             }
+             xc_dom_printf("%s: LZMA decompression error %s\n",
+                           __FUNCTION__, msg);
+-            break;
++            free(out_buf);
++            goto lzma_cleanup;
++        }
++
++        if ( stream.avail_out == 0 )
++        {
++            /* Protect against output buffer overflow */
++            if ( outsize > INT_MAX / 2 )
++            {
++                xc_dom_printf("LZMA: output buffer overflow\n");
++                free(out_buf);
++                goto lzma_cleanup;
++            }
++
++            tmp_buf = realloc(out_buf, outsize * 2);
++            if ( tmp_buf == NULL )
++            {
++                xc_dom_printf("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;
+         }
+     }
+ 
+@@ -314,18 +345,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 )
+@@ -358,10 +389,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(XC_INVALID_KERNEL, "%s: payload offset overflow",
++                     __FUNCTION__);
++        return -EINVAL;
++    }
++    if ( (payload_offset + payload_length) > dom->kernel_size )
++    {
++        xc_dom_panic(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 )
+@@ -372,7 +423,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 )
+@@ -383,7 +434,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 )
diff --git a/xen.spec b/xen.spec
index c5c1e54..55fc2b9 100644
--- a/xen.spec
+++ b/xen.spec
@@ -6,7 +6,7 @@
 Summary: Xen is a virtual machine monitor
 Name:    xen
 Version: 3.4.3
-Release: 2%{?dist}
+Release: 3%{?dist}
 Group:   Development/Libraries
 License: GPLv2+ and LGPLv2+ and BSD
 URL:     http://xen.org/
@@ -38,6 +38,7 @@ Patch5: xen-net-disable-iptables-on-bridge.patch
 Patch10: xen-no-werror.patch
 
 Patch15: xen-dev-create-cleanup.patch
+Patch29: cve-2011-1583-4.0.patch
 
 Patch100: xen-configure-xend.patch
 
@@ -144,6 +145,7 @@ which manage Xen virtual machines.
 %patch10 -p1
 
 %patch15 -p1
+%patch29 -p1
 
 %patch100 -p1
 
@@ -460,6 +462,11 @@ rm -rf %{buildroot}
 %{_libdir}/*.so
 
 %changelog
+* Sat May 21 2011 Michael Young <m.a.young at durham.ac.uk> - 3.4.3-3
+- 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]
+
 * Sun Jun 20 2010 Michael Young <m.a.young at durham.ac.uk> - 3.4.3-2
 - add patch to remove some old device creation code that doesn't
   work with the latest pvops kernels


More information about the scm-commits mailing list