[Pkg-xen-changes] r896 - in branches/squeeze-security/xen/debian: . patches
Bastian Blank
waldi at alioth.debian.org
Thu Jun 9 18:35:07 UTC 2011
Author: waldi
Date: Thu Jun 9 18:35:07 2011
New Revision: 896
Log:
* debian/changelog: Prepare to release (4.0.1-4).
* debian/patches/series: Update.
* debian/patches/upstream-21485:b85a9e58ec3a-CVE-2011-1898,
debian/patches/upstream-21482:c2adc059e931-CVE-2011-1583:
New security patches.
Added:
branches/squeeze-security/xen/debian/patches/upstream-21482:c2adc059e931-CVE-2011-1583
branches/squeeze-security/xen/debian/patches/upstream-21485:b85a9e58ec3a-CVE-2011-1898
Modified:
branches/squeeze-security/xen/debian/changelog
branches/squeeze-security/xen/debian/patches/series
Modified: branches/squeeze-security/xen/debian/changelog
==============================================================================
--- branches/squeeze-security/xen/debian/changelog Sat Apr 30 13:39:55 2011 (r895)
+++ branches/squeeze-security/xen/debian/changelog Thu Jun 9 18:35:07 2011 (r896)
@@ -1,3 +1,12 @@
+xen (4.0.1-4) stable-security; urgency=low
+
+ * Fix overflows and missing error checks in PV kernel loader.
+ CVE-2011-1583
+ * Protect against malicious MSIs from untrusted devices.
+ CVE-2011-1898
+
+ -- Bastian Blank <waldi at debian.org> Thu, 09 Jun 2011 20:33:46 +0200
+
xen (4.0.1-3) stable-security; urgency=low
* Fix check for existance of user-mode page tables.
Modified: branches/squeeze-security/xen/debian/patches/series
==============================================================================
--- branches/squeeze-security/xen/debian/patches/series Sat Apr 30 13:39:55 2011 (r895)
+++ branches/squeeze-security/xen/debian/patches/series Thu Jun 9 18:35:07 2011 (r896)
@@ -69,3 +69,5 @@
upstream-21409:a45388506790
upstream-21413:b05fa0652463
upstream-21461:ee088a0b5cb8-CVE-2011-1166
+upstream-21482:c2adc059e931-CVE-2011-1583
+upstream-21485:b85a9e58ec3a-CVE-2011-1898
Added: branches/squeeze-security/xen/debian/patches/upstream-21482:c2adc059e931-CVE-2011-1583
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/squeeze-security/xen/debian/patches/upstream-21482:c2adc059e931-CVE-2011-1583 Thu Jun 9 18:35:07 2011 (r896)
@@ -0,0 +1,235 @@
+# HG changeset patch
+# User Ian Jackson <ian.jackson at eu.citrix.com>
+# Date 1304949977 -3600
+# Node ID c2adc059e9311cc88778fd6020818344902ecdc6
+# Parent e91977e7ab3ab097a49c6a4780b330a4f48dac81
+libxc: [CVE-2011-1583] pv kernel image validation
+
+The functions which interpret the kernel image supplied for a
+paravirtualised guest, and decompress it into memory when booting the
+domain, are incautious. Specifically:
+
+ (i) Integer overflow in the decompression loop memory allocator might
+ result in overrunning the buffer used for the decompressed image;
+ (ii) Integer overflows and lack of checking of certain length fields
+ can result in the loader reading its own address space beyond the
+ size of the supplied kernel image file.
+ (iii) Lack of error checking in the decompression loop can lead to an
+ infinite loop.
+
+This patch fixes these problems.
+
+CVE-2011-1583.
+
+Signed-off-by: Ian Campbell <Ian.Campbell at eu.citrix.com>
+Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
+Committed-by: Ian Jackson <ian.jackson at eu.citrix.com>
+
+diff -r e91977e7ab3a -r c2adc059e931 tools/libxc/xc_dom_bzimageloader.c
+--- a/tools/libxc/xc_dom_bzimageloader.c Mon May 09 12:20:24 2011 +0100
++++ b/tools/libxc/xc_dom_bzimageloader.c Mon May 09 15:06:17 2011 +0100
+@@ -68,8 +68,29 @@
+ 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 @@
+ 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 @@
+ 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 @@
+ }
+ 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 @@
+
+ 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 @@
+ 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 @@
+ 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 @@
+ 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 )
Added: branches/squeeze-security/xen/debian/patches/upstream-21485:b85a9e58ec3a-CVE-2011-1898
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/squeeze-security/xen/debian/patches/upstream-21485:b85a9e58ec3a-CVE-2011-1898 Thu Jun 9 18:35:07 2011 (r896)
@@ -0,0 +1,121 @@
+# HG changeset patch
+# User Keir Fraser <keir at xen.org>
+# Date 1305220065 -3600
+# Node ID b85a9e58ec3aa46be0e4148737fefdddd59fdddf
+# Parent f47c6786ea6d8f14ce0a6770e9be51ca2b9d6888
+x86, vtd: [CVE-2011-1898] Protect against malicious MSIs from untrusted devices.
+
+In the absence of VT-d interrupt remapping support, a device can send
+arbitrary APIC messages to host CPUs. One class of attack that results
+is to confuse the hypervisor by delivering asynchronous interrupts to
+vectors that are expected to handle only synchronous
+traps/exceptions.
+
+We block this class of attack by:
+(1) setting APIC.TPR=0x10, to block all interrupts below vector
+0x20. This blocks delivery to all architectural exception vectors.
+(2) checking APIC.ISR[vec] for vectors 0x80 (fast syscall) and 0x82
+(hypercall). In these cases we BUG if we detect we are handling a
+hardware interrupt -- turning a potentially more severe infiltration
+into a straightforward system crash (i.e, DoS).
+
+Thanks to Invisible Things Lab <http://www.invisiblethingslab.com>
+for discovery and detailed investigation of this attack.
+
+Signed-off-by: Keir Fraser <keir at xen.org>
+xen-unstable changeset: 23337:cc91832a02c7
+xen-unstable date: Thu May 12 16:39:31 2011 +0100
+
+diff -r f47c6786ea6d -r b85a9e58ec3a xen/arch/x86/apic.c
+--- a/xen/arch/x86/apic.c Thu May 12 09:23:21 2011 +0100
++++ b/xen/arch/x86/apic.c Thu May 12 18:07:45 2011 +0100
+@@ -572,12 +572,9 @@
+ init_apic_ldr();
+
+ /*
+- * Set Task Priority to 'accept all'. We never change this
+- * later on.
++ * Set Task Priority to reject any interrupts below FIRST_DYNAMIC_VECTOR.
+ */
+- value = apic_read(APIC_TASKPRI);
+- value &= ~APIC_TPRI_MASK;
+- apic_write_around(APIC_TASKPRI, value);
++ apic_write_around(APIC_TASKPRI, (FIRST_DYNAMIC_VECTOR & 0xF0) - 0x10);
+
+ /*
+ * After a crash, we no longer service the interrupts and a pending
+@@ -1498,3 +1495,9 @@
+
+ return 0;
+ }
++
++void check_for_unexpected_msi(unsigned int vector)
++{
++ unsigned long v = apic_read(APIC_ISR + ((vector & ~0x1f) >> 1));
++ BUG_ON(v & (1 << (vector & 0x1f)));
++}
+diff -r f47c6786ea6d -r b85a9e58ec3a xen/arch/x86/x86_64/compat/entry.S
+--- a/xen/arch/x86/x86_64/compat/entry.S Thu May 12 09:23:21 2011 +0100
++++ b/xen/arch/x86/x86_64/compat/entry.S Thu May 12 18:07:45 2011 +0100
+@@ -27,6 +27,15 @@
+ pushq $0
+ movl $TRAP_syscall,4(%rsp)
+ SAVE_ALL
++
++ cmpb $0,untrusted_msi(%rip)
++ je 1f
++ movl $0x82,%edi
++ call check_for_unexpected_msi
++ RESTORE_ALL
++ SAVE_ALL
++1:
++
+ GET_CURRENT(%rbx)
+
+ cmpl $NR_hypercalls,%eax
+diff -r f47c6786ea6d -r b85a9e58ec3a xen/arch/x86/x86_64/entry.S
+--- a/xen/arch/x86/x86_64/entry.S Thu May 12 09:23:21 2011 +0100
++++ b/xen/arch/x86/x86_64/entry.S Thu May 12 18:07:45 2011 +0100
+@@ -310,6 +310,14 @@
+ pushq $0
+ SAVE_ALL
+
++ cmpb $0,untrusted_msi(%rip)
++ je 1f
++ movl $0x80,%edi
++ call check_for_unexpected_msi
++ RESTORE_ALL
++ SAVE_ALL
++1:
++
+ GET_CURRENT(%rbx)
+
+ /* Check that the callback is non-null. */
+diff -r f47c6786ea6d -r b85a9e58ec3a xen/drivers/passthrough/vtd/iommu.c
+--- a/xen/drivers/passthrough/vtd/iommu.c Thu May 12 09:23:21 2011 +0100
++++ b/xen/drivers/passthrough/vtd/iommu.c Thu May 12 18:07:45 2011 +0100
+@@ -42,6 +42,9 @@
+ #define nr_ioapics iosapic_get_nr_iosapics()
+ #endif
+
++/* Possible unfiltered LAPIC/MSI messages from untrusted sources? */
++bool_t __read_mostly untrusted_msi;
++
+ int nr_iommus;
+ static bool_t rwbf_quirk;
+
+@@ -1566,6 +1569,14 @@
+ if (!pdev)
+ return -ENODEV;
+
++ /*
++ * Devices assigned to untrusted domains (here assumed to be any domU)
++ * can attempt to send arbitrary LAPIC/MSI messages. We are unprotected
++ * by the root complex unless interrupt remapping is enabled.
++ */
++ if ( (target != dom0) && !iommu_intremap )
++ untrusted_msi = 1;
++
+ ret = domain_context_unmap(source, bus, devfn);
+ if ( ret )
+ return ret;
More information about the Pkg-xen-changes
mailing list