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

Re: [Xen-devel] [V3 PATCH 7/9] pvh: change xsm_add_to_physmap



On 11/26/2013 09:27 PM, Mukesh Rathor wrote:
In preparation for the next patch, we update xsm_add_to_physmap to
allow for checking of foreign domain. Thus, the current domain must
have the right to update the mappings of target domain with pages from
foreign domain.

Signed-off-by: Mukesh Rathor <mukesh.rathor@xxxxxxxxxx>
CC: dgdegra@xxxxxxxxxxxxx
---
  xen/arch/x86/mm.c       |   16 +++++++++++++---
  xen/include/xsm/dummy.h |   10 ++++++++--
  xen/include/xsm/xsm.h   |    6 +++---
  xen/xsm/flask/hooks.c   |   10 ++++++++--
  4 files changed, 32 insertions(+), 10 deletions(-)

The XSM changes look good; however, the calling code needs a bit of
tweaking.  Currently, if domain 0 is specified as the foreign domain,
the check is skipped, and the check is also run unnecessarily when
foreign_domid is nonzero but the operation is not XENMAPSPACE_gmfn_foreign.
The locking in this version also implies a potential TOCTOU bug, but
which in reality is impossible to trigger due to the existing RCU lock
held on (d).  I would suggest passing the foreign struct domain instead
of the domid, as below.

An unrelated question about XENMAPSPACE_gmfn_foreign that came up while
looking at this: is the domain parameter (d) supposed to be ignored
here, with maps always modifying the current domain? I would have
expected this call to manipulate d's physmap, with the common case being
(d == current->domain).

---

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 797fbc7..9afbcb9 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -4531,23 +4531,17 @@ static int handle_iomem_range(unsigned long s, unsigned 
long e, void *p)
  * Returns: 0 ==> success
  */
 static int xenmem_add_foreign_to_pmap(unsigned long fgfn, unsigned long gpfn,
-                                      domid_t foreign_domid)
+                                      struct domain *fdom)
 {
     p2m_type_t p2mt, p2mt_prev;
     int rc = 0;
     unsigned long prev_mfn, mfn = 0;
-    struct domain *fdom, *currd = current->domain;
+    struct domain *currd = current->domain;
     struct page_info *page = NULL;
- if ( currd->domain_id == foreign_domid || foreign_domid == DOMID_SELF ||
-         !is_pvh_domain(currd) )
+    if ( currd == fdom || !fdom || !is_pvh_domain(currd) )
         return -EINVAL;
- /* Note, access check is done in the caller via xsm_add_to_physmap */
-    if ( !is_control_domain(currd) ||
-         (fdom = get_pg_owner(foreign_domid)) == NULL )
-        return -EPERM;
-
     /* following will take a refcnt on the mfn */
     page = get_page_from_gfn(fdom, fgfn, &p2mt, P2M_ALLOC);
     if ( !page || !p2m_is_valid(p2mt) )
@@ -4579,7 +4573,7 @@ static int xenmem_add_foreign_to_pmap(unsigned long fgfn, 
unsigned long gpfn,
     {
         gdprintk(XENLOG_WARNING, "set_foreign_p2m_entry failed. "
                  "gpfn:%lx mfn:%lx fgfn:%lx fd:%d\n",
-                 gpfn, mfn, fgfn, foreign_domid);
+                 gpfn, mfn, fgfn, fdom->domain_id);
         put_page(page);
         rc = -EINVAL;
     }
@@ -4590,14 +4584,13 @@ static int xenmem_add_foreign_to_pmap(unsigned long 
fgfn, unsigned long gpfn,
      */
     put_gfn(currd, gpfn);
- put_pg_owner(fdom);
     return rc;
 }
static int xenmem_add_to_physmap_once(
     struct domain *d,
     const struct xen_add_to_physmap *xatp,
-    domid_t foreign_domid)
+    struct domain *foreign_dom)
 {
     struct page_info *page = NULL;
     unsigned long gfn = 0; /* gcc ... */
@@ -4660,7 +4653,7 @@ static int xenmem_add_to_physmap_once(
         case XENMAPSPACE_gmfn_foreign:
         {
             rc = xenmem_add_foreign_to_pmap(xatp->idx, xatp->gpfn,
-                                            foreign_domid);
+                                            foreign_dom);
             return rc;
         }
@@ -4729,7 +4722,7 @@ static int xenmem_add_to_physmap(struct domain *d,
         start_xatp = *xatp;
         while ( xatp->size > 0 )
         {
-            rc = xenmem_add_to_physmap_once(d, xatp, DOMID_INVALID);
+            rc = xenmem_add_to_physmap_once(d, xatp, NULL);
             if ( rc < 0 )
                 return rc;
@@ -4755,11 +4748,12 @@ static int xenmem_add_to_physmap(struct domain *d,
         return rc;
     }
- return xenmem_add_to_physmap_once(d, xatp, DOMID_INVALID);
+    return xenmem_add_to_physmap_once(d, xatp, NULL);
 }
static int xenmem_add_to_physmap_range(struct domain *d,
-                                       struct xen_add_to_physmap_range *xatpr)
+                                       struct xen_add_to_physmap_range *xatpr,
+                                       struct domain *foreign_dom)
 {
     int rc;
@@ -4779,7 +4773,7 @@ static int xenmem_add_to_physmap_range(struct domain *d,
         xatp.space = xatpr->space;
         xatp.idx = idx;
         xatp.gpfn = gpfn;
-        rc = xenmem_add_to_physmap_once(d, &xatp, xatpr->foreign_domid);
+        rc = xenmem_add_to_physmap_once(d, &xatp, foreign_dom);
if ( copy_to_guest_offset(xatpr->errs, xatpr->size-1, &rc, 1) )
             return -EFAULT;
@@ -4855,25 +4849,29 @@ long arch_memory_op(int op, 
XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             return -ESRCH;
- if ( xatpr.foreign_domid )
+        if ( xatpr.space == XENMAPSPACE_gmfn_foreign )
         {
-            if ( (fd = rcu_lock_domain_by_any_id(xatpr.foreign_domid)) == NULL 
)
+            fd = get_pg_owner(xatpr.foreign_domid);
+            if ( fd == NULL )
             {
                 rcu_unlock_domain(d);
                 return -ESRCH;
             }
-            rcu_unlock_domain(fd);
         }
if ( (rc = xsm_add_to_physmap(XSM_TARGET, current->domain, d, fd)) )
         {
             rcu_unlock_domain(d);
+            if (fd)
+                put_pg_owner(fd);
             return rc;
         }
- rc = xenmem_add_to_physmap_range(d, &xatpr);
+        rc = xenmem_add_to_physmap_range(d, &xatpr, fd);
rcu_unlock_domain(d);
+        if (fd)
+            put_pg_owner(fd);
if ( rc == -EAGAIN )
             rc = hypercall_create_continuation(

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