[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen stable-4.3] gnttab: correct locking order reversal



commit 96b59ae2dcaa639a4f58c68f122f8ba8738009dc
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Mon Nov 4 10:13:59 2013 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Mon Nov 4 10:13:59 2013 +0100

    gnttab: correct locking order reversal
    
    Coverity ID 1087189
    
    Correct a lock order reversal between a domains page allocation and grant
    table locks.
    
    This is CVE-2013-4494 / XSA-73.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    
    Consolidate error handling.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Keir Fraser <keir@xxxxxxx>
    Tested-by: Matthew Daley <mattjd@xxxxxxxxx>
    master commit: a321abc6d8122f8cb3928066cc74363c4fdddcfd
    master date: 2013-11-04 10:06:36 +0100
---
 xen/common/grant_table.c |   52 ++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 3f97328..9182a44 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -1518,6 +1518,8 @@ gnttab_transfer(
 
     for ( i = 0; i < count; i++ )
     {
+        bool_t okay;
+
         if (i && hypercall_preempt_check())
             return i;
 
@@ -1626,16 +1628,18 @@ gnttab_transfer(
          * pages when it is dying.
          */
         if ( unlikely(e->is_dying) ||
-             unlikely(e->tot_pages >= e->max_pages) ||
-             unlikely(!gnttab_prepare_for_transfer(e, d, gop.ref)) )
+             unlikely(e->tot_pages >= e->max_pages) )
         {
-            if ( !e->is_dying )
-                gdprintk(XENLOG_INFO, "gnttab_transfer: "
-                        "Transferee has no reservation "
-                        "headroom (%d,%d) or provided a bad grant ref (%08x) "
-                        "or is dying (%d)\n",
-                        e->tot_pages, e->max_pages, gop.ref, e->is_dying);
             spin_unlock(&e->page_alloc_lock);
+
+            if ( e->is_dying )
+                gdprintk(XENLOG_INFO, "gnttab_transfer: "
+                         "Transferee (d%d) is dying\n", e->domain_id);
+            else
+                gdprintk(XENLOG_INFO, "gnttab_transfer: "
+                         "Transferee (d%d) has no headroom (tot %u, max %u)\n",
+                         e->domain_id, e->tot_pages, e->max_pages);
+
             rcu_unlock_domain(e);
             put_gfn(d, gop.mfn);
             page->count_info &= ~(PGC_count_mask|PGC_allocated);
@@ -1647,6 +1651,38 @@ gnttab_transfer(
         /* Okay, add the page to 'e'. */
         if ( unlikely(domain_adjust_tot_pages(e, 1) == 1) )
             get_knownalive_domain(e);
+
+        /*
+         * We must drop the lock to avoid a possible deadlock in
+         * gnttab_prepare_for_transfer.  We have reserved a page in e so can
+         * safely drop the lock and re-aquire it later to add page to the
+         * pagelist.
+         */
+        spin_unlock(&e->page_alloc_lock);
+        okay = gnttab_prepare_for_transfer(e, d, gop.ref);
+        spin_lock(&e->page_alloc_lock);
+
+        if ( unlikely(!okay) || unlikely(e->is_dying) )
+        {
+            bool_t drop_dom_ref = !domain_adjust_tot_pages(e, -1);
+
+            spin_unlock(&e->page_alloc_lock);
+
+            if ( okay /* i.e. e->is_dying due to the surrounding if() */ )
+                gdprintk(XENLOG_INFO, "gnttab_transfer: "
+                         "Transferee (d%d) is now dying\n", e->domain_id);
+
+            if ( drop_dom_ref )
+                put_domain(e);
+            rcu_unlock_domain(e);
+
+            put_gfn(d, gop.mfn);
+            page->count_info &= ~(PGC_count_mask|PGC_allocated);
+            free_domheap_page(page);
+            gop.status = GNTST_general_error;
+            goto copyback;
+        }
+
         page_list_add_tail(page, &e->page_list);
         page_set_owner(page, e);
 
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.3

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.