|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |