]> git.pld-linux.org Git - packages/xen.git/commitdiff
security fixes
authorJacek Konieczny <j.konieczny@eggsoft.pl>
Wed, 18 Jun 2014 08:23:42 +0000 (10:23 +0200)
committerJacek Konieczny <j.konieczny@eggsoft.pl>
Wed, 18 Jun 2014 08:23:42 +0000 (10:23 +0200)
- XSA-92 – CVE-2014-3124
- XSA-96 – CVE-2014-3967, CVE-2014-3968
- XSA-99 – none (yet) assigned

xen.spec
xsa92.patch [new file with mode: 0644]
xsa96.patch [new file with mode: 0644]
xsa99.patch [new file with mode: 0644]

index 9f8155b88471ec1da8a37110ec546428acbf1c8b..2ffa5edef351b686fbe6715a8e58b54468855afc 100644 (file)
--- a/xen.spec
+++ b/xen.spec
@@ -111,6 +111,10 @@ Patch14:   %{name}-no_fetcher.patch
 Patch15:       odd-glib2-fix.patch
 Patch16:       CVE-2014-2599.patch
 Patch17:       %{name}-pvh_fixes.patch
+Patch18:       http://xenbits.xen.org/xsa/xsa92.patch
+Patch19:       http://xenbits.xen.org/xsa/xsa96.patch
+# based on: http://xenbits.xen.org/xsa/xsa99.patch
+Patch20:       xsa99.patch
 URL:           http://www.xen.org/products/xenhyp.html
 %if %{with qemu_traditional}
 %{?with_opengl:BuildRequires:  OpenGL-devel}
@@ -417,6 +421,9 @@ Nadzorca Xen w postaci, która może być uruchomiona wprost z firmware
 %patch15 -p1
 %patch16 -p1
 %patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
 
 # stubdom sources
 ln -s %{SOURCE10} %{SOURCE11} %{SOURCE12} %{SOURCE13} %{SOURCE14} stubdom
diff --git a/xsa92.patch b/xsa92.patch
new file mode 100644 (file)
index 0000000..60ef934
--- /dev/null
@@ -0,0 +1,36 @@
+x86/HVM: restrict HVMOP_set_mem_type
+
+Permitting arbitrary type changes here has the potential of creating
+present P2M (and hence EPT/NPT/IOMMU) entries pointing to an invalid
+MFN (INVALID_MFN truncated to the respective hardware structure field's
+width). This would become a problem the latest when something real sat
+at the end of the physical address space; I'm suspecting though that
+other things might break with such bogus entries.
+
+Along with that drop a bogus (and otherwise becoming stale) log
+message.
+
+Afaict the similar operation in p2m_set_mem_access() is safe.
+
+This is XSA-92.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Tim Deegan <tim@xen.org>
+
+--- a/xen/arch/x86/hvm/hvm.c
++++ b/xen/arch/x86/hvm/hvm.c
+@@ -4541,12 +4541,10 @@ long do_hvm_op(unsigned long op, XEN_GUE
+                 rc = -EINVAL;
+                 goto param_fail4;
+             } 
+-            if ( p2m_is_grant(t) )
++            if ( !p2m_is_ram(t) &&
++                 (!p2m_is_hole(t) || a.hvmmem_type != HVMMEM_mmio_dm) )
+             {
+                 put_gfn(d, pfn);
+-                gdprintk(XENLOG_WARNING,
+-                         "type for pfn %#lx changed to grant while "
+-                         "we were working?\n", pfn);
+                 goto param_fail4;
+             }
+             else
diff --git a/xsa96.patch b/xsa96.patch
new file mode 100644 (file)
index 0000000..ef6443f
--- /dev/null
@@ -0,0 +1,38 @@
+x86/HVM: eliminate vulnerabilities from hvm_inject_msi()
+
+- pirq_info() returns NULL for a non-allocated pIRQ, and hence we
+  mustn't unconditionally de-reference it, and we need to invoke it
+  another time after having called map_domain_emuirq_pirq()
+- don't use printk(), namely without XENLOG_GUEST, for error reporting
+
+This is XSA-96.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+
+--- a/xen/arch/x86/hvm/irq.c
++++ b/xen/arch/x86/hvm/irq.c
+@@ -289,20 +289,18 @@ void hvm_inject_msi(struct domain *d, ui
+             struct pirq *info = pirq_info(d, pirq);
+             /* if it is the first time, allocate the pirq */
+-            if (info->arch.hvm.emuirq == IRQ_UNBOUND)
++            if ( !info || info->arch.hvm.emuirq == IRQ_UNBOUND )
+             {
+                 spin_lock(&d->event_lock);
+                 map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
+                 spin_unlock(&d->event_lock);
++                info = pirq_info(d, pirq);
++                if ( !info )
++                    return;
+             } else if (info->arch.hvm.emuirq != IRQ_MSI_EMU)
+-            {
+-                printk("%s: pirq %d does not correspond to an emulated MSI\n", __func__, pirq);
+                 return;
+-            }
+             send_guest_pirq(d, info);
+             return;
+-        } else {
+-            printk("%s: error getting pirq from MSI: pirq = %d\n", __func__, pirq);
+         }
+     }
diff --git a/xsa99.patch b/xsa99.patch
new file mode 100644 (file)
index 0000000..14e58f4
--- /dev/null
@@ -0,0 +1,257 @@
+diff -durN -x '*~' -x '*.orig' -x '*.rej' xen-4.4.0.orig/tools/libxc/xc_mem_access.c xen-4.4.0/tools/libxc/xc_mem_access.c
+--- xen-4.4.0.orig/tools/libxc/xc_mem_access.c 2014-03-10 11:43:57.000000000 +0100
++++ xen-4.4.0/tools/libxc/xc_mem_access.c      2014-06-18 10:19:54.000000000 +0200
+@@ -24,19 +24,9 @@
+ #include "xc_private.h"
+-int xc_mem_access_enable(xc_interface *xch, domid_t domain_id,
+-                         uint32_t *port)
++void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port)
+ {
+-    if ( !port )
+-    {
+-        errno = EINVAL;
+-        return -1;
+-    }
+-
+-    return xc_mem_event_control(xch, domain_id,
+-                                XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE,
+-                                XEN_DOMCTL_MEM_EVENT_OP_ACCESS,
+-                                port);
++    return xc_mem_event_enable(xch, domain_id, HVM_PARAM_ACCESS_RING_PFN, port);
+ }
+ int xc_mem_access_disable(xc_interface *xch, domid_t domain_id)
+diff -durN -x '*~' -x '*.orig' -x '*.rej' xen-4.4.0.orig/tools/libxc/xc_mem_event.c xen-4.4.0/tools/libxc/xc_mem_event.c
+--- xen-4.4.0.orig/tools/libxc/xc_mem_event.c  2014-03-10 11:43:57.000000000 +0100
++++ xen-4.4.0/tools/libxc/xc_mem_event.c       2014-06-18 10:19:54.000000000 +0200
+@@ -56,3 +56,118 @@
+     return do_memory_op(xch, mode, &meo, sizeof(meo));
+ }
++void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
++                          uint32_t *port)
++{
++    void *ring_page = NULL;
++    unsigned long ring_pfn, mmap_pfn;
++    unsigned int op, mode;
++    int rc1, rc2, saved_errno;
++
++    if ( !port )
++    {
++        errno = EINVAL;
++        return NULL;
++    }
++
++    /* Pause the domain for ring page setup */
++    rc1 = xc_domain_pause(xch, domain_id);
++    if ( rc1 != 0 )
++    {
++        PERROR("Unable to pause domain\n");
++        return NULL;
++    }
++
++    /* Get the pfn of the ring page */
++    rc1 = xc_get_hvm_param(xch, domain_id, param, &ring_pfn);
++    if ( rc1 != 0 )
++    {
++        PERROR("Failed to get pfn of ring page\n");
++        goto out;
++    }
++
++    mmap_pfn = ring_pfn;
++    ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
++                                     &mmap_pfn, 1);
++    if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
++    {
++        /* Map failed, populate ring page */
++        rc1 = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0,
++                                              &ring_pfn);
++        if ( rc1 != 0 )
++        {
++            PERROR("Failed to populate ring pfn\n");
++            goto out;
++        }
++
++        mmap_pfn = ring_pfn;
++        ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
++                                         &mmap_pfn, 1);
++        if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
++        {
++            PERROR("Could not map the ring page\n");
++            goto out;
++        }
++    }
++
++    switch ( param )
++    {
++    case HVM_PARAM_PAGING_RING_PFN:
++        op = XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE;
++        mode = XEN_DOMCTL_MEM_EVENT_OP_PAGING;
++        break;
++
++    case HVM_PARAM_ACCESS_RING_PFN:
++        op = XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE;
++        mode = XEN_DOMCTL_MEM_EVENT_OP_ACCESS;
++        break;
++
++    case HVM_PARAM_SHARING_RING_PFN:
++        op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_ENABLE;
++        mode = XEN_DOMCTL_MEM_EVENT_OP_SHARING;
++        break;
++
++    /*
++     * This is for the outside chance that the HVM_PARAM is valid but is invalid
++     * as far as mem_event goes.
++     */
++    default:
++        errno = EINVAL;
++        rc1 = -1;
++        goto out;
++    }
++
++    rc1 = xc_mem_event_control(xch, domain_id, op, mode, port);
++    if ( rc1 != 0 )
++    {
++        PERROR("Failed to enable mem_event\n");
++        goto out;
++    }
++
++    /* Remove the ring_pfn from the guest's physmap */
++    rc1 = xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0, &ring_pfn);
++    if ( rc1 != 0 )
++        PERROR("Failed to remove ring page from guest physmap");
++
++ out:
++    saved_errno = errno;
++
++    rc2 = xc_domain_unpause(xch, domain_id);
++    if ( rc1 != 0 || rc2 != 0 )
++    {
++        if ( rc2 != 0 )
++        {
++            if ( rc1 == 0 )
++                saved_errno = errno;
++            PERROR("Unable to unpause domain");
++        }
++
++        if ( ring_page )
++            munmap(ring_page, XC_PAGE_SIZE);
++        ring_page = NULL;
++
++        errno = saved_errno;
++    }
++
++    return ring_page;
++}
+diff -durN -x '*~' -x '*.orig' -x '*.rej' xen-4.4.0.orig/tools/libxc/xenctrl.h xen-4.4.0/tools/libxc/xenctrl.h
+--- xen-4.4.0.orig/tools/libxc/xenctrl.h       2014-03-10 11:43:57.000000000 +0100
++++ xen-4.4.0/tools/libxc/xenctrl.h    2014-06-18 10:19:54.000000000 +0200
+@@ -2040,6 +2040,12 @@
+ int xc_mem_event_memop(xc_interface *xch, domid_t domain_id, 
+                         unsigned int op, unsigned int mode,
+                         uint64_t gfn, void *buffer);
++/*
++ * Enables mem_event and returns the mapped ring page indicated by param.
++ * param can be HVM_PARAM_PAGING/ACCESS/SHARING_RING_PFN
++ */
++void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
++                          uint32_t *port);
+ /** 
+  * Mem paging operations.
+@@ -2060,7 +2066,13 @@
+  * Access tracking operations.
+  * Supported only on Intel EPT 64 bit processors.
+  */
+-int xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port);
++
++/*
++ * Enables mem_access and returns the mapped ring page.
++ * Will return NULL on error.
++ * Caller has to unmap this page when done.
++ */
++void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port);
+ int xc_mem_access_disable(xc_interface *xch, domid_t domain_id);
+ int xc_mem_access_resume(xc_interface *xch, domid_t domain_id,
+                          unsigned long gfn);
+diff -durN -x '*~' -x '*.orig' -x '*.rej' xen-4.4.0.orig/tools/tests/xen-access/xen-access.c xen-4.4.0/tools/tests/xen-access/xen-access.c
+--- xen-4.4.0.orig/tools/tests/xen-access/xen-access.c 2014-03-10 11:43:57.000000000 +0100
++++ xen-4.4.0/tools/tests/xen-access/xen-access.c      2014-06-18 10:20:55.000000000 +0200
+@@ -231,7 +231,6 @@
+     xenaccess_t *xenaccess = 0;
+     xc_interface *xch;
+     int rc;
+-    unsigned long ring_pfn, mmap_pfn;
+     xch = xc_interface_open(NULL, NULL, 0);
+     if ( !xch )
+@@ -253,40 +252,12 @@
+     /* Initialise lock */
+     mem_event_ring_lock_init(&xenaccess->mem_event);
+-    /* Map the ring page */
+-    xc_get_hvm_param(xch, xenaccess->mem_event.domain_id, 
+-                        HVM_PARAM_ACCESS_RING_PFN, &ring_pfn);
+-    mmap_pfn = ring_pfn;
+-    xenaccess->mem_event.ring_page = 
+-        xc_map_foreign_batch(xch, xenaccess->mem_event.domain_id, 
+-                                PROT_READ | PROT_WRITE, &mmap_pfn, 1);
+-    if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+-    {
+-        /* Map failed, populate ring page */
+-        rc = xc_domain_populate_physmap_exact(xenaccess->xc_handle, 
+-                                              xenaccess->mem_event.domain_id,
+-                                              1, 0, 0, &ring_pfn);
+-        if ( rc != 0 )
+-        {
+-            PERROR("Failed to populate ring gfn\n");
+-            goto err;
+-        }
+-
+-        mmap_pfn = ring_pfn;
+-        xenaccess->mem_event.ring_page = 
+-            xc_map_foreign_batch(xch, xenaccess->mem_event.domain_id, 
+-                                    PROT_READ | PROT_WRITE, &mmap_pfn, 1);
+-        if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+-        {
+-            PERROR("Could not map the ring page\n");
+-            goto err;
+-        }
+-    }
+-
+-    /* Initialise Xen */
+-    rc = xc_mem_access_enable(xenaccess->xc_handle, xenaccess->mem_event.domain_id,
+-                             &xenaccess->mem_event.evtchn_port);
+-    if ( rc != 0 )
++    /* Enable mem_access */
++    xenaccess->mem_event.ring_page =
++            xc_mem_access_enable(xenaccess->xc_handle,
++                                 xenaccess->mem_event.domain_id,
++                                 &xenaccess->mem_event.evtchn_port);
++    if ( xenaccess->mem_event.ring_page == NULL )
+     {
+         switch ( errno ) {
+             case EBUSY:
+@@ -296,7 +267,7 @@
+                 ERROR("EPT not supported for this guest");
+                 break;
+             default:
+-                perror("Error initialising shared page");
++                perror("Error enabling mem_access");
+                 break;
+         }
+         goto err;
+@@ -330,11 +301,6 @@
+                    (mem_event_sring_t *)xenaccess->mem_event.ring_page,
+                    PAGE_SIZE);
+-    /* Now that the ring is set, remove it from the guest's physmap */
+-    if ( xc_domain_decrease_reservation_exact(xch, 
+-                    xenaccess->mem_event.domain_id, 1, 0, &ring_pfn) )
+-        PERROR("Failed to remove ring from guest physmap");
+-
+     /* Get platform info */
+     xenaccess->platform_info = malloc(sizeof(xc_platform_info_t));
+     if ( xenaccess->platform_info == NULL )
This page took 0.254653 seconds and 4 git commands to generate.