From: Tamas K Lengyel <tklengyel@sec.in.tum.de>
To: xen-devel@lists.xen.org
Cc: wei.liu2@citrix.com, ian.campbell@citrix.com, tim@xen.org,
stefano.stabellini@citrix.com, dgdegra@tycho.nsa.gov,
Tamas K Lengyel <tklengyel@sec.in.tum.de>
Subject: [PATCH for-4.5 v11 5/9] xen/arm: Allow hypervisor access to mem_access protected pages
Date: Mon, 29 Sep 2014 13:36:45 +0200 [thread overview]
Message-ID: <1411990609-22374-6-git-send-email-tklengyel@sec.in.tum.de> (raw)
In-Reply-To: <1411990609-22374-1-git-send-email-tklengyel@sec.in.tum.de>
The guestcopy helpers use the MMU to verify that the given guest has read/write
access to a given page during hypercalls. As we may have custom mem_access
permissions set on these pages, we do a software-based type checking in case
the MMU based approach failed, but only if access_in_use is set.
These memory accesses are not forwarded to the mem_event listener. Accesses
performed by the hypervisor are currently not part of the mem_access scheme.
This is consistent behaviour with the x86 side as well.
Signed-off-by: Tamas K Lengyel <tklengyel@sec.in.tum.de>
---
xen/arch/arm/guestcopy.c | 120 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 117 insertions(+), 3 deletions(-)
diff --git a/xen/arch/arm/guestcopy.c b/xen/arch/arm/guestcopy.c
index 0173597..b0727b1 100644
--- a/xen/arch/arm/guestcopy.c
+++ b/xen/arch/arm/guestcopy.c
@@ -6,6 +6,111 @@
#include <asm/mm.h>
#include <asm/guest_access.h>
+#include <asm/p2m.h>
+
+/*
+ * If mem_access is in use it might have been the reason why get_page_from_gva
+ * failed to fetch the page, as it uses the MMU for the permission checking.
+ * Only in these cases we do a software-based type check and fetch the page if
+ * we indeed found a conflicting mem_access setting.
+ */
+static int check_type_get_page(vaddr_t gva, unsigned long flag,
+ struct page_info** page)
+{
+ long rc;
+ paddr_t ipa;
+ unsigned long maddr;
+ xenmem_access_t xma;
+ p2m_type_t t;
+
+ rc = gva_to_ipa(gva, &ipa);
+ if ( rc < 0 )
+ return rc;
+
+ /*
+ * We do this first as this is faster in the default case when no
+ * permission is set on the page.
+ */
+ rc = p2m_get_mem_access(current->domain, paddr_to_pfn(ipa), &xma);
+ if ( rc < 0 )
+ return rc;
+
+ /* Let's check if mem_access limited the access. */
+ switch ( xma )
+ {
+ default:
+ case XENMEM_access_rwx:
+ case XENMEM_access_rw:
+ return -EFAULT;
+ case XENMEM_access_n2rwx:
+ case XENMEM_access_n:
+ case XENMEM_access_x:
+ break;
+ case XENMEM_access_wx:
+ case XENMEM_access_w:
+ if ( flag == GV2M_READ )
+ break;
+ else return -EFAULT;
+ case XENMEM_access_rx2rw:
+ case XENMEM_access_rx:
+ case XENMEM_access_r:
+ if ( flag == GV2M_WRITE )
+ break;
+ else return -EFAULT;
+ }
+
+ /*
+ * We had a mem_access permission limiting the access, but the page type
+ * could also be limiting, so we need to check that as well.
+ */
+ maddr = p2m_lookup(current->domain, ipa, &t);
+ if ( maddr == INVALID_PADDR )
+ return -EFAULT;
+
+ /*
+ * All page types are readable so we only have to check the
+ * type if writing.
+ */
+ if ( flag == GV2M_WRITE )
+ {
+ switch ( t )
+ {
+ case p2m_ram_rw:
+ case p2m_iommu_map_rw:
+ case p2m_map_foreign:
+ case p2m_grant_map_rw:
+ case p2m_mmio_direct:
+ /* Base type allows writing, we are good to get the page. */
+ break;
+ default:
+ return -EFAULT;
+ }
+ }
+
+ *page = mfn_to_page(maddr >> PAGE_SHIFT);
+ ASSERT(*page);
+
+ if ( unlikely(!get_page(*page, current->domain)) )
+ {
+ *page = NULL;
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/*
+ * If mem_access is not in use, we have a fault. If mem_access is in use, do the
+ * software-based type checking.
+ */
+static inline
+int check_mem_access(vaddr_t gva, unsigned long flag, struct page_info **page)
+{
+ if( !current->domain->arch.p2m.access_in_use )
+ return -EFAULT;
+
+ return check_type_get_page(gva, flag, page);
+}
static unsigned long raw_copy_to_guest_helper(void *to, const void *from,
unsigned len, int flush_dcache)
@@ -21,7 +126,10 @@ static unsigned long raw_copy_to_guest_helper(void *to, const void *from,
page = get_page_from_gva(current->domain, (vaddr_t) to, GV2M_WRITE);
if ( page == NULL )
- return len;
+ {
+ if ( check_mem_access((vaddr_t) to, GV2M_WRITE, &page) < 0 )
+ return len;
+ }
p = __map_domain_page(page);
p += offset;
@@ -68,7 +176,10 @@ unsigned long raw_clear_guest(void *to, unsigned len)
page = get_page_from_gva(current->domain, (vaddr_t) to, GV2M_WRITE);
if ( page == NULL )
- return len;
+ {
+ if ( check_mem_access((vaddr_t) to, GV2M_WRITE, &page) < 0 )
+ return len;
+ }
p = __map_domain_page(page);
p += offset;
@@ -100,7 +211,10 @@ unsigned long raw_copy_from_guest(void *to, const void __user *from, unsigned le
page = get_page_from_gva(current->domain, (vaddr_t) from, GV2M_READ);
if ( page == NULL )
- return len;
+ {
+ if ( check_mem_access((vaddr_t) from, GV2M_READ, &page) < 0 )
+ return len;
+ }
p = __map_domain_page(page);
p += ((vaddr_t)from & (~PAGE_MASK));
--
2.1.0
next prev parent reply other threads:[~2014-09-29 11:36 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-29 11:36 [PATCH for-4.5 v11 0/9] Mem_event and mem_access for ARM Tamas K Lengyel
2014-09-29 11:36 ` [PATCH for-4.5 v11 1/9] xen/arm: p2m changes for mem_access support Tamas K Lengyel
2014-09-29 12:26 ` Julien Grall
2014-09-29 12:41 ` Tamas K Lengyel
2014-09-29 11:36 ` [PATCH for-4.5 v11 2/9] xen/arm: Implement domain_get_maximum_gpfn Tamas K Lengyel
2014-09-29 11:36 ` [PATCH for-4.5 v11 3/9] xen/arm: Add p2m_set_permission and p2m_shatter_page helpers Tamas K Lengyel
2014-09-29 11:36 ` [PATCH for-4.5 v11 4/9] xen/arm: Data abort exception (R/W) mem_events Tamas K Lengyel
2014-09-29 12:35 ` Julien Grall
2014-09-29 12:47 ` Tamas K Lengyel
2014-09-29 12:52 ` Julien Grall
2014-09-29 12:53 ` Julien Grall
2014-09-29 11:36 ` Tamas K Lengyel [this message]
2014-09-29 14:12 ` [PATCH for-4.5 v11 5/9] xen/arm: Allow hypervisor access to mem_access protected pages Julien Grall
2014-09-29 14:44 ` Tamas K Lengyel
2014-09-29 14:50 ` Julien Grall
2014-09-29 14:57 ` Tamas K Lengyel
2014-09-29 15:07 ` Julien Grall
2014-09-29 11:36 ` [PATCH for-4.5 v11 6/9] xen/arm: Instruction prefetch abort (X) mem_event handling Tamas K Lengyel
2014-09-29 14:13 ` Julien Grall
2014-09-29 11:36 ` [PATCH for-4.5 v11 7/9] xen/arm: Enable the compilation of mem_access and mem_event on ARM Tamas K Lengyel
2014-09-29 11:36 ` [PATCH for-4.5 v11 8/9] tools/libxc: Allocate magic page for mem access " Tamas K Lengyel
2014-09-29 11:36 ` [PATCH for-4.5 v11 9/9] tools/tests: Enable xen-access " Tamas K Lengyel
2014-09-29 14:16 ` Julien Grall
2014-09-29 12:17 ` [PATCH for-4.5 v11 0/9] Mem_event and mem_access for ARM Tamas K Lengyel
2014-09-29 13:37 ` Ian Campbell
2014-09-29 14:21 ` Tamas K Lengyel
2014-09-29 15:07 ` Ian Campbell
2014-09-29 15:17 ` Tamas K Lengyel
2014-09-29 15:21 ` Ian Campbell
2014-09-29 15:29 ` Tamas K Lengyel
2014-09-30 11:02 ` Stefano Stabellini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1411990609-22374-6-git-send-email-tklengyel@sec.in.tum.de \
--to=tklengyel@sec.in.tum.de \
--cc=dgdegra@tycho.nsa.gov \
--cc=ian.campbell@citrix.com \
--cc=stefano.stabellini@citrix.com \
--cc=tim@xen.org \
--cc=wei.liu2@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).