]> xenbits.xensource.com Git - people/sstabellini/xen-unstable.git/.git/commitdiff
xen: xsm: flask: introduce XENMAPSPACE_gmfn_share for memory sharing
authorZhongze Liu <blackskygg@gmail.com>
Wed, 5 Dec 2018 22:15:57 +0000 (14:15 -0800)
committerStefano Stabellini <sstabellini@xilinx.com>
Wed, 18 Dec 2019 19:16:19 +0000 (11:16 -0800)
The existing XENMAPSPACE_gmfn_foreign subop of XENMEM_add_to_physmap forbids
a Dom0 to map memory pages from one DomU to another, which restricts some useful
yet not dangerous use cases -- such as sharing pages among DomU's so that they
can do shm-based communication.

This patch introduces XENMAPSPACE_gmfn_share to address this inconvenience,
which is mostly the same as XENMAPSPACE_gmfn_foreign but has its own xsm check.

Specifically, the patch:

* Introduces a new av permission MMU__SHARE_MEM to denote if two domains can
  share memory by using the new subop;
* Introduces xsm_map_gmfn_share() to check if (current) has proper permission
  over (t) AND MMU__SHARE_MEM is allowed between (d) and (t);
* Modify the default xen.te to allow MMU__SHARE_MEM for normal domains that
  allow grant mapping/event channels.

The new subop is marked unsupported for x86 because calling p2m_add_foregin
on two DomU's is currently not supported on x86.

This is for the proposal "Allow setting up shared memory areas between VMs
from xl config file" (see [1]).

[1] https://lists.xen.org/archives/html/xen-devel/2017-08/msg03242.html

Signed-off-by: Zhongze Liu <blackskygg@gmail.com>
Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
Cc: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Tim Deegan <tim@xen.org>
Cc: xen-devel@lists.xen.org
tools/flask/policy/modules/xen.if
xen/arch/arm/mm.c
xen/include/public/memory.h
xen/include/xsm/dummy.h
xen/include/xsm/xsm.h
xen/xsm/dummy.c
xen/xsm/flask/hooks.c
xen/xsm/flask/policy/access_vectors

index 8eb2293a529d20e13c73617dcd85d3d228b2734e..cd91766d298ff79e3e8c0aaf76ecd198929c30d1 100644 (file)
@@ -128,6 +128,8 @@ define(`domain_comms', `
        domain_event_comms($1, $2)
        allow $1 $2:grant { map_read map_write copy unmap };
        allow $2 $1:grant { map_read map_write copy unmap };
+       allow $1 $2:mmu share_mem;
+       allow $2 $1:mmu share_mem;
 ')
 
 # domain_self_comms(domain)
index 4d6c971f37dcb589ae30f25d98904dc7809e2d4c..bb059b25b223991914a014aab7bd46e15fd3f89f 100644 (file)
@@ -1435,6 +1435,7 @@ int xenmem_add_to_physmap_one(
 
         break;
     case XENMAPSPACE_gmfn_foreign:
+    case XENMAPSPACE_gmfn_share:
     {
         struct domain *od;
         p2m_type_t p2mt;
@@ -1449,7 +1450,11 @@ int xenmem_add_to_physmap_one(
             return -EINVAL;
         }
 
-        rc = xsm_map_gmfn_foreign(XSM_TARGET, d, od);
+        if ( space == XENMAPSPACE_gmfn_foreign )
+            rc = xsm_map_gmfn_foreign(XSM_TARGET, d, od);
+        else
+            rc = xsm_map_gmfn_share(XSM_TARGET, d, od);
+
         if ( rc )
         {
             put_pg_owner(od);
index cfdda6e2a87ed30bed590034d8d717674abfbc79..d7337f2445ef8dba93cc53481034147334181376 100644 (file)
@@ -227,6 +227,14 @@ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
                                       Stage-2 using the Normal Memory
                                       Inner/Outer Write-Back Cacheable
                                       memory attribute. */
+#define XENMAPSPACE_gmfn_share   6 /* GMFN from another dom,
+                                      XENMEM_add_to_physmap_batch (and
+                                      currently ARM) only. Unlike
+                                      XENMAPSPACE_gmfn_foreign, it
+                                      requires current to have mapping
+                                      privileges instead of the
+                                      destination domain. */
+
 /* ` } */
 
 /*
index b8e185e6fa9bdd77e4b05c6688e9ce392c74eaac..620f0be3fa2b67b0b501a21a6acd8411ba58f11c 100644 (file)
@@ -532,6 +532,20 @@ static XSM_INLINE int xsm_map_gmfn_foreign(XSM_DEFAULT_ARG struct domain *d, str
     return xsm_default_action(action, d, t);
 }
 
+/*
+ * Be aware that this is not an exact default equivalence of its flask
+ * variant which also checks if @d and @t "are allowed to share memory
+ * pages", for now, we don't have a proper default equivalence of such a
+ * check.
+ */
+static XSM_INLINE int xsm_map_gmfn_share(XSM_DEFAULT_ARG struct domain *d,
+                                         struct domain *t)
+{
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, current->domain, d) ?:
+           xsm_default_action(action, current->domain, t);
+}
+
 static XSM_INLINE int xsm_hvm_param(XSM_DEFAULT_ARG struct domain *d, unsigned long op)
 {
     XSM_ASSERT_ACTION(XSM_TARGET);
index e22d6160b5fc677c5c48b4d80407566324cb0253..f044e9961bfce132b453d2fa17e5100f68e9081d 100644 (file)
@@ -86,6 +86,7 @@ struct xsm_operations {
     int (*add_to_physmap) (struct domain *d1, struct domain *d2);
     int (*remove_from_physmap) (struct domain *d1, struct domain *d2);
     int (*map_gmfn_foreign) (struct domain *d, struct domain *t);
+    int (*map_gmfn_share) (struct domain *d, struct domain *t);
     int (*claim_pages) (struct domain *d);
 
     int (*console_io) (struct domain *d, int cmd);
@@ -382,6 +383,11 @@ static inline int xsm_map_gmfn_foreign (xsm_default_t def, struct domain *d, str
     return xsm_ops->map_gmfn_foreign(d, t);
 }
 
+static inline int xsm_map_gmfn_share (xsm_default_t def, struct domain *d, struct domain *t)
+{
+    return xsm_ops->map_gmfn_share(d, t);
+}
+
 static inline int xsm_claim_pages(xsm_default_t def, struct domain *d)
 {
     return xsm_ops->claim_pages(d);
index 5705e52791be86e35d723ee46d9ab6bb89a7595c..60b623d551d7949a7ef83d408fe6e5a405f989b5 100644 (file)
@@ -117,6 +117,7 @@ void __init xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, add_to_physmap);
     set_to_dummy_if_null(ops, remove_from_physmap);
     set_to_dummy_if_null(ops, map_gmfn_foreign);
+    set_to_dummy_if_null(ops, map_gmfn_share);
 
     set_to_dummy_if_null(ops, vm_event_control);
 
index cf7f25cda208a42cf26a85c2d75d05b9bfcc50fb..c7b2b719564825eadc7a0922dcf8e612499e3148 100644 (file)
@@ -1187,6 +1187,12 @@ static int flask_map_gmfn_foreign(struct domain *d, struct domain *t)
     return domain_has_perm(d, t, SECCLASS_MMU, MMU__MAP_READ | MMU__MAP_WRITE);
 }
 
+static int flask_map_gmfn_share(struct domain *d, struct domain *t)
+{
+    return current_has_perm(t, SECCLASS_MMU, MMU__MAP_READ | MMU__MAP_WRITE) ?:
+           domain_has_perm(d, t, SECCLASS_MMU, MMU__SHARE_MEM);
+}
+
 static int flask_hvm_param(struct domain *d, unsigned long op)
 {
     u32 perm;
@@ -1841,6 +1847,7 @@ static struct xsm_operations flask_ops = {
     .add_to_physmap = flask_add_to_physmap,
     .remove_from_physmap = flask_remove_from_physmap,
     .map_gmfn_foreign = flask_map_gmfn_foreign,
+    .map_gmfn_share = flask_map_gmfn_share,
 
 #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
     .get_device_group = flask_get_device_group,
index c055c14c26541d70b966c435777a59f3676d922a..61bbb6ff56203693501436216fa9e231b8efd6bf 100644 (file)
@@ -378,6 +378,11 @@ class mmu
 # Allow a privileged domain to install a map of a page it does not own.  Used
 # for stub domain device models with the PV framebuffer.
     target_hack
+# Checked when using XENMEM_add_to_physmap with XENMAPSPACE_gmfn_share
+# to share memory between two domains:
+#  source = domain whose memory is being shared
+#  target = client domain
+    share_mem
 }
 
 # control of the paging_domctl split by subop