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

[Xen-changelog] [xen stable-4.2] x86: make MMUEXT_NEW_USER_BASEPTR preemptible



commit f1d1abcc1f5b8c541dd8ef2d970907b2b3515465
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Thu May 2 17:15:51 2013 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu May 2 17:15:51 2013 +0200

    x86: make MMUEXT_NEW_USER_BASEPTR preemptible
    
    ... as it may take significant amounts of time.
    
    This is part of CVE-2013-1918 / XSA-45.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Acked-by: Tim Deegan <tim@xxxxxxx>
    master commit: 918a5f17b447072b40780f4d03a3adc99ff0073b
    master date: 2013-05-02 16:36:44 +0200
---
 xen/arch/x86/mm.c |   39 +++++++++++++++++++++++++++++++++------
 1 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index d455d13..c120288 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -3296,29 +3296,56 @@ long do_mmuext_op(
                 break;
             }
 
+            old_mfn = pagetable_get_pfn(curr->arch.guest_table_user);
+            /*
+             * This is particularly important when getting restarted after the
+             * previous attempt got preempted in the put-old-MFN phase.
+             */
+            if ( old_mfn == op.arg1.mfn )
+                break;
+
             if ( op.arg1.mfn != 0 )
             {
                 if ( paging_mode_refcounts(d) )
                     okay = get_page_from_pagenr(op.arg1.mfn, d);
                 else
-                    okay = !get_page_and_type_from_pagenr(
-                        op.arg1.mfn, PGT_root_page_table, d, 0, 0);
+                {
+                    rc = get_page_and_type_from_pagenr(
+                        op.arg1.mfn, PGT_root_page_table, d, 0, 1);
+                    okay = !rc;
+                }
                 if ( unlikely(!okay) )
                 {
-                    MEM_LOG("Error while installing new mfn %lx", op.arg1.mfn);
+                    if ( rc == -EINTR )
+                        rc = -EAGAIN;
+                    else if ( rc != -EAGAIN )
+                        MEM_LOG("Error while installing new mfn %lx",
+                                op.arg1.mfn);
                     break;
                 }
             }
 
-            old_mfn = pagetable_get_pfn(curr->arch.guest_table_user);
             curr->arch.guest_table_user = pagetable_from_pfn(op.arg1.mfn);
 
             if ( old_mfn != 0 )
             {
+                struct page_info *page = mfn_to_page(old_mfn);
+
                 if ( paging_mode_refcounts(d) )
-                    put_page(mfn_to_page(old_mfn));
+                    put_page(page);
                 else
-                    put_page_and_type(mfn_to_page(old_mfn));
+                    switch ( rc = put_page_and_type_preemptible(page, 1) )
+                    {
+                    case -EINTR:
+                        rc = -EAGAIN;
+                    case -EAGAIN:
+                        curr->arch.old_guest_table = page;
+                        okay = 0;
+                        break;
+                    default:
+                        BUG_ON(rc);
+                        break;
+                    }
             }
 
             break;
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.2

_______________________________________________
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®.