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

[Xen-changelog] [xen staging] page-alloc: detect double free earlier



commit f882fadbeb8bc4d09f6522e0769baff13b89bdb9
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Mon May 13 09:58:57 2019 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Mon May 13 09:58:57 2019 +0200

    page-alloc: detect double free earlier
    
    Right now this goes unnoticed until some subsequent page allocator
    operation stumbles across the thus corrupted list. We can do better:
    Only PGC_state_inuse and PGC_state_offlining pages can legitimately be
    passed to free_heap_pages().
    
    Take the opportunity and also restrict the PGC_broken check to the
    PGC_state_offlining case, as only pages of that type or
    PGC_state_offlined may have this flag set on them. Similarly, since
    PGC_state_offlined is not a valid input state, the setting of "tainted"
    can be restricted to just this case.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/common/page_alloc.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 9c12d71fc1..b71998cfa8 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -1413,13 +1413,22 @@ static void free_heap_pages(
          *     in its pseudophysical address space).
          * In all the above cases there can be no guest mappings of this page.
          */
-        ASSERT(!page_state_is(&pg[i], offlined));
-        pg[i].count_info =
-            ((pg[i].count_info & PGC_broken) |
-             (page_state_is(&pg[i], offlining)
-              ? PGC_state_offlined : PGC_state_free));
-        if ( page_state_is(&pg[i], offlined) )
+        switch ( pg[i].count_info & PGC_state )
+        {
+        case PGC_state_inuse:
+            BUG_ON(pg[i].count_info & PGC_broken);
+            pg[i].count_info = PGC_state_free;
+            break;
+
+        case PGC_state_offlining:
+            pg[i].count_info = (pg[i].count_info & PGC_broken) |
+                               PGC_state_offlined;
             tainted = 1;
+            break;
+
+        default:
+            BUG();
+        }
 
         /* If a page has no owner it will need no safety TLB flush. */
         pg[i].u.free.need_tlbflush = (page_get_owner(&pg[i]) != NULL);
--
generated by git-patchbot for /home/xen/git/xen.git#staging

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
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®.