[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