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

[Xen-changelog] [xen stable-4.5] gnttab: fix pin count / page reference race



commit 08aa260dd172de625ecc2b64b78b1aa68de1f472
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Oct 24 16:53:36 2017 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Oct 24 16:53:36 2017 +0200

    gnttab: fix pin count / page reference race
    
    Dropping page references before decrementing pin counts is a bad idea
    if assumptions are being made that a non-zero pin count implies a valid
    page. Fix the order of operations in gnttab_copy_release_buf(), but at
    the same time also remove the assertion that was found to trigger:
    map_grant_ref() also has the potential of causing a race here, and
    changing the order of operations there would likely be quite a bit more
    involved.
    
    This is CVE-2017-15597 / XSA-236.
    
    Reported-by: Pawel Wieczorkiewicz <wipawel@xxxxxxxxx>
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    master commit: e008f7619dcd6d549727c9635b3f9f3c7ee483ed
    master date: 2017-10-24 16:01:33 +0200
---
 xen/common/grant_table.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index fe91538..ef697b8 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -2086,7 +2086,23 @@ __acquire_grant_for_copy(
     {
         ASSERT(mfn_valid(act->frame));
         *page = mfn_to_page(act->frame);
-        (void)page_get_owner_and_reference(*page);
+        td = page_get_owner_and_reference(*page);
+        /*
+         * act->pin being non-zero should guarantee the page to have a
+         * non-zero refcount and hence a valid owner (matching the one on
+         * record), with one exception: If the owning domain is dying we
+         * had better not make implications from pin count (map_grant_ref()
+         * updates pin counts before obtaining page references, for
+         * example).
+         */
+        if ( td != rd || rd->is_dying )
+        {
+            if ( td )
+                put_page(*page);
+            *page = NULL;
+            rc = GNTST_bad_domain;
+            goto unlock_out_clear;
+        }
     }
 
     act->pin += readonly ? GNTPIN_hstr_inc : GNTPIN_hstw_inc;
@@ -2223,14 +2239,14 @@ __gnttab_copy(
 
     put_page_type(d_pg);
  error_out:
-    if ( d_pg )
-        put_page(d_pg);
-    if ( s_pg )
-        put_page(s_pg);
     if ( have_s_grant )
         __release_grant_for_copy(sd, op->source.u.ref, 1);
     if ( have_d_grant )
         __release_grant_for_copy(dd, op->dest.u.ref, 0);
+    if ( d_pg )
+        put_page(d_pg);
+    if ( s_pg )
+        put_page(s_pg);
     if ( sd )
         rcu_unlock_domain(sd);
     if ( dd )
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.5

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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