[Pkg-xen-changes] [xen] 45/48: x86/HVM: confine internally handled MMIO to solitary regions

Ian James Campbell ijc at moszumanska.debian.org
Tue Dec 9 12:49:28 UTC 2014


This is an automated email from the git hooks/post-receive script.

ijc pushed a commit to branch feature/patch-names
in repository xen.

commit 85ddc29d40daafab754b72af43ca3d7a47643284
Author: Jan Beulich <jbeulich at suse.com>
Date:   Thu Nov 27 14:11:57 2014 +0100

    x86/HVM: confine internally handled MMIO to solitary regions
    
    While it is generally wrong to cross region boundaries when dealing
    with MMIO accesses of repeated string instructions (currently only
    MOVS) as that would do things a guest doesn't expect (leaving aside
    that none of these regions would normally be accessed with repeated
    string instructions in the first place), this is even more of a problem
    for all virtual MSI-X page accesses (both msixtbl_{read,write}() can be
    made dereference NULL "entry" pointers this way) as well as undersized
    (1- or 2-byte) LAPIC writes (causing vlapic_read_aligned() to access
    space beyond the one memory page set up for holding LAPIC register
    values).
    
    Since those functions validly assume to be called only with addresses
    their respective checking functions indicated to be okay, it is generic
    code that needs to be fixed to clip the repetition count.
    
    To be on the safe side (and consistent), also do the same for buffered
    I/O intercepts, even if their only client (stdvga) doesn't put the
    hypervisor at risk (i.e. "only" guest misbehavior would result).
    
    This is CVE-2014-8867 / XSA-112.
    
    Signed-off-by: Jan Beulich <jbeulich at suse.com>
    Reviewed-by: Tim Deegan <tim at xen.org>
    master commit: c5397354b998d030b021810b8202de93b9526818
    master date: 2014-11-27 14:01:40 +0100
    
    (cherry picked from commit a39f202031d7f1d8d9e14b8c3d7d11c812db253e)
    
    Patch-Name: xsa112.diff
---
 xen/arch/x86/hvm/intercept.c | 22 +++++++++++++++++++++-
 xen/arch/x86/hvm/vmsi.c      |  4 ++++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c
index 7cc13b5..52ffee3 100644
--- a/xen/arch/x86/hvm/intercept.c
+++ b/xen/arch/x86/hvm/intercept.c
@@ -169,11 +169,24 @@ int hvm_mmio_intercept(ioreq_t *p)
     int i;
 
     for ( i = 0; i < HVM_MMIO_HANDLER_NR; i++ )
-        if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) )
+    {
+        hvm_mmio_check_t check_handler =
+            hvm_mmio_handlers[i]->check_handler;
+
+        if ( check_handler(v, p->addr) )
+        {
+            if ( unlikely(p->count > 1) &&
+                 !check_handler(v, unlikely(p->df)
+                                   ? p->addr - (p->count - 1L) * p->size
+                                   : p->addr + (p->count - 1L) * p->size) )
+                p->count = 1;
+
             return hvm_mmio_access(
                 v, p,
                 hvm_mmio_handlers[i]->read_handler,
                 hvm_mmio_handlers[i]->write_handler);
+        }
+    }
 
     return X86EMUL_UNHANDLEABLE;
 }
@@ -330,6 +343,13 @@ int hvm_io_intercept(ioreq_t *p, int type)
             if ( type == HVM_PORTIO )
                 return process_portio_intercept(
                     handler->hdl_list[i].action.portio, p);
+
+            if ( unlikely(p->count > 1) &&
+                 (unlikely(p->df)
+                  ? p->addr - (p->count - 1L) * p->size < addr
+                  : p->addr + p->count * 1L * p->size - 1 >= addr + size) )
+                p->count = 1;
+
             return handler->hdl_list[i].action.mmio(p);
         }
     }
diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
index 10e5f34..dc3e4d7 100644
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -235,6 +235,8 @@ static int msixtbl_read(
     rcu_read_lock(&msixtbl_rcu_lock);
 
     entry = msixtbl_find_entry(v, address);
+    if ( !entry )
+        goto out;
     offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
 
     if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET )
@@ -277,6 +279,8 @@ static int msixtbl_write(struct vcpu *v, unsigned long address,
     rcu_read_lock(&msixtbl_rcu_lock);
 
     entry = msixtbl_find_entry(v, address);
+    if ( !entry )
+        goto out;
     nr_entry = (address - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
 
     offset = address & (PCI_MSIX_ENTRY_SIZE - 1);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-xen/xen.git



More information about the Pkg-xen-changes mailing list