[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