|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] mem_access: Add helper API to setup ring and enable mem_access
commit 6ae2df93c277b4093b3e54c9606387d1ba6d10fe
Author: Aravindh Puthiyaparambil <aravindp@xxxxxxxxx>
AuthorDate: Tue May 20 16:35:44 2014 -0700
Commit: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
CommitDate: Mon Jun 23 11:31:52 2014 +0100
mem_access: Add helper API to setup ring and enable mem_access
tools/libxc: Add helper function to setup ring for mem events
This patch adds a helper function that maps the ring, enables mem_event
and removes the ring from the guest physmap while the domain is paused.
This can be used by all mem_events but is only enabled for mem_access at
the moment.
tests/xen-access: Use helper API to setup ring and enable mem_access
Prior to this patch, xen-access was setting up the ring page in a way
that would give a malicous guest a window to write in to the shared ring
page. This patch fixes this by using the helper API that does it safely
on behalf of xen-access.
This is XSA-99.
Signed-off-by: Aravindh Puthiyaparambil <aravindp@xxxxxxxxx>
Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
tools/libxc/xc_mem_access.c | 14 +----
tools/libxc/xc_mem_event.c | 115 +++++++++++++++++++++++++++++++++++
tools/libxc/xenctrl.h | 14 ++++-
tools/tests/xen-access/xen-access.c | 48 ++------------
4 files changed, 137 insertions(+), 54 deletions(-)
diff --git a/tools/libxc/xc_mem_access.c b/tools/libxc/xc_mem_access.c
index f436e69..461f0e9 100644
--- a/tools/libxc/xc_mem_access.c
+++ b/tools/libxc/xc_mem_access.c
@@ -24,19 +24,9 @@
#include "xc_private.h"
#include <xen/memory.h>
-int xc_mem_access_enable(xc_interface *xch, domid_t domain_id,
- uint32_t *port)
+void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t
*port)
{
- if ( !port )
- {
- errno = EINVAL;
- return -1;
- }
-
- return xc_mem_event_control(xch, domain_id,
- XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE,
- XEN_DOMCTL_MEM_EVENT_OP_ACCESS,
- port);
+ return xc_mem_event_enable(xch, domain_id, HVM_PARAM_ACCESS_RING_PFN,
port);
}
int xc_mem_access_disable(xc_interface *xch, domid_t domain_id)
diff --git a/tools/libxc/xc_mem_event.c b/tools/libxc/xc_mem_event.c
index d43a0af..be7c63d 100644
--- a/tools/libxc/xc_mem_event.c
+++ b/tools/libxc/xc_mem_event.c
@@ -56,3 +56,118 @@ int xc_mem_event_memop(xc_interface *xch, domid_t domain_id,
return do_memory_op(xch, mode, &meo, sizeof(meo));
}
+void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
+ uint32_t *port)
+{
+ void *ring_page = NULL;
+ unsigned long ring_pfn, mmap_pfn;
+ unsigned int op, mode;
+ int rc1, rc2, saved_errno;
+
+ if ( !port )
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* Pause the domain for ring page setup */
+ rc1 = xc_domain_pause(xch, domain_id);
+ if ( rc1 != 0 )
+ {
+ PERROR("Unable to pause domain\n");
+ return NULL;
+ }
+
+ /* Get the pfn of the ring page */
+ rc1 = xc_get_hvm_param(xch, domain_id, param, &ring_pfn);
+ if ( rc1 != 0 )
+ {
+ PERROR("Failed to get pfn of ring page\n");
+ goto out;
+ }
+
+ mmap_pfn = ring_pfn;
+ ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
+ &mmap_pfn, 1);
+ if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+ {
+ /* Map failed, populate ring page */
+ rc1 = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0,
+ &ring_pfn);
+ if ( rc1 != 0 )
+ {
+ PERROR("Failed to populate ring pfn\n");
+ goto out;
+ }
+
+ mmap_pfn = ring_pfn;
+ ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ |
PROT_WRITE,
+ &mmap_pfn, 1);
+ if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+ {
+ PERROR("Could not map the ring page\n");
+ goto out;
+ }
+ }
+
+ switch ( param )
+ {
+ case HVM_PARAM_PAGING_RING_PFN:
+ op = XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE;
+ mode = XEN_DOMCTL_MEM_EVENT_OP_PAGING;
+ break;
+
+ case HVM_PARAM_ACCESS_RING_PFN:
+ op = XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE;
+ mode = XEN_DOMCTL_MEM_EVENT_OP_ACCESS;
+ break;
+
+ case HVM_PARAM_SHARING_RING_PFN:
+ op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_ENABLE;
+ mode = XEN_DOMCTL_MEM_EVENT_OP_SHARING;
+ break;
+
+ /*
+ * This is for the outside chance that the HVM_PARAM is valid but is
invalid
+ * as far as mem_event goes.
+ */
+ default:
+ errno = EINVAL;
+ rc1 = -1;
+ goto out;
+ }
+
+ rc1 = xc_mem_event_control(xch, domain_id, op, mode, port);
+ if ( rc1 != 0 )
+ {
+ PERROR("Failed to enable mem_event\n");
+ goto out;
+ }
+
+ /* Remove the ring_pfn from the guest's physmap */
+ rc1 = xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0,
&ring_pfn);
+ if ( rc1 != 0 )
+ PERROR("Failed to remove ring page from guest physmap");
+
+ out:
+ saved_errno = errno;
+
+ rc2 = xc_domain_unpause(xch, domain_id);
+ if ( rc1 != 0 || rc2 != 0 )
+ {
+ if ( rc2 != 0 )
+ {
+ if ( rc1 == 0 )
+ saved_errno = errno;
+ PERROR("Unable to unpause domain");
+ }
+
+ if ( ring_page )
+ munmap(ring_page, XC_PAGE_SIZE);
+ ring_page = NULL;
+
+ errno = saved_errno;
+ }
+
+ return ring_page;
+}
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index b55d857..af6f249 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -2190,6 +2190,12 @@ int xc_mem_event_control(xc_interface *xch, domid_t
domain_id, unsigned int op,
int xc_mem_event_memop(xc_interface *xch, domid_t domain_id,
unsigned int op, unsigned int mode,
uint64_t gfn, void *buffer);
+/*
+ * Enables mem_event and returns the mapped ring page indicated by param.
+ * param can be HVM_PARAM_PAGING/ACCESS/SHARING_RING_PFN
+ */
+void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
+ uint32_t *port);
/**
* Mem paging operations.
@@ -2210,7 +2216,13 @@ int xc_mem_paging_load(xc_interface *xch, domid_t
domain_id,
* Access tracking operations.
* Supported only on Intel EPT 64 bit processors.
*/
-int xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port);
+
+/*
+ * Enables mem_access and returns the mapped ring page.
+ * Will return NULL on error.
+ * Caller has to unmap this page when done.
+ */
+void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t
*port);
int xc_mem_access_disable(xc_interface *xch, domid_t domain_id);
int xc_mem_access_resume(xc_interface *xch, domid_t domain_id);
diff --git a/tools/tests/xen-access/xen-access.c
b/tools/tests/xen-access/xen-access.c
index 0a84bd5..572ab63 100644
--- a/tools/tests/xen-access/xen-access.c
+++ b/tools/tests/xen-access/xen-access.c
@@ -223,7 +223,6 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t
domain_id)
xenaccess_t *xenaccess = 0;
xc_interface *xch;
int rc;
- unsigned long ring_pfn, mmap_pfn;
xch = xc_interface_open(NULL, NULL, 0);
if ( !xch )
@@ -245,40 +244,12 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t
domain_id)
/* Initialise lock */
mem_event_ring_lock_init(&xenaccess->mem_event);
- /* Map the ring page */
- xc_get_hvm_param(xch, xenaccess->mem_event.domain_id,
- HVM_PARAM_ACCESS_RING_PFN, &ring_pfn);
- mmap_pfn = ring_pfn;
- xenaccess->mem_event.ring_page =
- xc_map_foreign_batch(xch, xenaccess->mem_event.domain_id,
- PROT_READ | PROT_WRITE, &mmap_pfn, 1);
- if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
- {
- /* Map failed, populate ring page */
- rc = xc_domain_populate_physmap_exact(xenaccess->xc_handle,
- xenaccess->mem_event.domain_id,
- 1, 0, 0, &ring_pfn);
- if ( rc != 0 )
- {
- PERROR("Failed to populate ring gfn\n");
- goto err;
- }
-
- mmap_pfn = ring_pfn;
- xenaccess->mem_event.ring_page =
- xc_map_foreign_batch(xch, xenaccess->mem_event.domain_id,
- PROT_READ | PROT_WRITE, &mmap_pfn, 1);
- if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
- {
- PERROR("Could not map the ring page\n");
- goto err;
- }
- }
-
- /* Initialise Xen */
- rc = xc_mem_access_enable(xenaccess->xc_handle,
xenaccess->mem_event.domain_id,
- &xenaccess->mem_event.evtchn_port);
- if ( rc != 0 )
+ /* Enable mem_access */
+ xenaccess->mem_event.ring_page =
+ xc_mem_access_enable(xenaccess->xc_handle,
+ xenaccess->mem_event.domain_id,
+ &xenaccess->mem_event.evtchn_port);
+ if ( xenaccess->mem_event.ring_page == NULL )
{
switch ( errno ) {
case EBUSY:
@@ -288,7 +259,7 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t
domain_id)
ERROR("EPT not supported for this guest");
break;
default:
- perror("Error initialising shared page");
+ perror("Error enabling mem_access");
break;
}
goto err;
@@ -322,11 +293,6 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t
domain_id)
(mem_event_sring_t *)xenaccess->mem_event.ring_page,
XC_PAGE_SIZE);
- /* Now that the ring is set, remove it from the guest's physmap */
- if ( xc_domain_decrease_reservation_exact(xch,
- xenaccess->mem_event.domain_id, 1, 0, &ring_pfn) )
- PERROR("Failed to remove ring from guest physmap");
-
/* Get domaininfo */
xenaccess->domain_info = malloc(sizeof(xc_domaininfo_t));
if ( xenaccess->domain_info == NULL )
--
generated by git-patchbot for /home/xen/git/xen.git#master
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |