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

[Xen-devel] [PATCH RFC 2/4] xen: grant_table: implement grant_table_soft_reset()



When soft reset is being performed we need to replace all actively
granted pages with empty pages to prevent possible future memory
corruption as the newly started kernel won't be aware of these
granted pages.

We make the tot_pages < max_pages assumption here: previously granted pages
need to belong to someone and we don't want to implement possible DoS by
reassigning them to the grantee/anonymous domain/xen/.. (the malicious guest
will be able to consume all host's memory).

Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx>
---
 xen/common/grant_table.c      | 62 +++++++++++++++++++++++++++++++++++++++++++
 xen/include/xen/grant_table.h |  6 +++++
 2 files changed, 68 insertions(+)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index dfb45f8..815d5f3 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -3120,6 +3120,68 @@ gnttab_release_mappings(
     }
 }
 
+int grant_table_soft_reset(struct domain *d)
+{
+    struct grant_table *gt = d->grant_table;
+    struct active_grant_entry *act;
+    grant_ref_t ref;
+    unsigned long mfn_new;
+    struct page_info *page, *new_page;
+    int ret = 0;
+
+    spin_lock(&gt->lock);
+
+    for ( ref = 0; ref != nr_grant_entries(gt); ref++ )
+    {
+        act = &active_entry(gt, ref);
+        if ( !act->pin )
+            continue;
+
+        page = mfn_to_page(act->frame);
+        if ( !page || !get_page(page, d) )
+        {
+            printk(XENLOG_G_ERR "Dom%d's grant frame %lx (gfn %lx) is invalid",
+                   d->domain_id, act->gfn, act->frame);
+            ret = -EINVAL;
+            break;
+        }
+
+        /*
+         * Here we assume the domain has tot_pages < max_pages. Previously
+         * granted page will still belong to us until it is unmapped from
+         * grantee.
+         */
+        new_page = alloc_domheap_page(d, 0);
+        if ( !new_page )
+        {
+            printk(XENLOG_G_ERR "Failed to alloc a page to replace"
+                   " Dom%d's grant frame %lx\n", d->domain_id, act->frame);
+            ret = -ENOMEM;
+            put_page(page);
+            break;
+        }
+        mfn_new = page_to_mfn(new_page);
+        guest_remove_page(d, act->gfn);
+
+        if ( guest_physmap_add_page(d, act->gfn, mfn_new, 0) )
+        {
+            printk(XENLOG_G_ERR "Failed to replace Dom%d's grant frame %lx"
+                   " with new MFN %lx\n", d->domain_id, act->frame, mfn_new);
+            ret = -EFAULT;
+        }
+
+        gnttab_flush_tlb(d);
+
+        put_page(new_page);
+        put_page(page);
+
+        if (ret)
+            break;
+    }
+
+    spin_unlock(&gt->lock);
+    return ret;
+}
 
 void
 grant_table_destroy(
diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
index 32f5786..3f58c54 100644
--- a/xen/include/xen/grant_table.h
+++ b/xen/include/xen/grant_table.h
@@ -95,6 +95,12 @@ int grant_table_create(
 void grant_table_destroy(
     struct domain *d);
 
+/*
+ * Replace all granted pages with empty pages for a domain to prevent possible
+ * future memory corruption in case of soft reset.
+ */
+int grant_table_soft_reset(struct domain *d);
+
 /* Domain death release of granted mappings of other domains' memory. */
 void
 gnttab_release_mappings(
-- 
1.9.3


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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