diff mbox

[Xen-devel,v5,p2,11/19] xen/xsm: Add helpers to check permission for device tree passthrough

Message ID 1428592185-18581-12-git-send-email-julien.grall@citrix.com
State New
Headers show

Commit Message

Julien Grall April 9, 2015, 3:09 p.m. UTC
From: Julien Grall <julien.grall@linaro.org>

This is a follow-up of commit 525ee49 "xsm: add device tree labeling
support" which add support for device tree labelling in flask.

Those helpers will be use latter when non-pci passthrough (i.e device
tree) will be added.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

---
    Changes in v5:
        - Add Ian and Daniel's ack

    Changes in v4:
        - Patch added
---
 xen/include/xsm/dummy.h             | 23 +++++++++++++
 xen/include/xsm/xsm.h               | 27 +++++++++++++++
 xen/xsm/dummy.c                     |  6 ++++
 xen/xsm/flask/avc.c                 |  3 ++
 xen/xsm/flask/hooks.c               | 69 ++++++++++++++++++++++++++++++++++++-
 xen/xsm/flask/include/avc.h         |  2 ++
 xen/xsm/flask/policy/access_vectors |  2 +-
 7 files changed, 130 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index c36e05f..05641f9 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -350,6 +350,29 @@  static XSM_INLINE int xsm_deassign_device(XSM_DEFAULT_ARG struct domain *d, uint
 
 #endif /* HAS_PASSTHROUGH && HAS_PCI */
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+static XSM_INLINE int xsm_test_assign_dtdevice(XSM_DEFAULT_ARG const char *dtpath)
+{
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, NULL);
+}
+
+static XSM_INLINE int xsm_assign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
+                                          const char *dtpath)
+{
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
+}
+
+static XSM_INLINE int xsm_deassign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
+                                            const char *dtpath)
+{
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
+}
+
+#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
+
 static XSM_INLINE int xsm_resource_plug_core(XSM_DEFAULT_VOID)
 {
     XSM_ASSERT_ACTION(XSM_HOOK);
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index b7446be..c830b47 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -121,6 +121,12 @@  struct xsm_operations {
     int (*deassign_device) (struct domain *d, uint32_t machine_bdf);
 #endif
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+    int (*test_assign_dtdevice) (const char *dtpath);
+    int (*assign_dtdevice) (struct domain *d, const char *dtpath);
+    int (*deassign_dtdevice) (struct domain *d, const char *dtpath);
+#endif
+
     int (*resource_plug_core) (void);
     int (*resource_unplug_core) (void);
     int (*resource_plug_pci) (uint32_t machine_bdf);
@@ -473,6 +479,27 @@  static inline int xsm_deassign_device(xsm_default_t def, struct domain *d, uint3
 }
 #endif /* HAS_PASSTHROUGH && HAS_PCI) */
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+static inline int xsm_assign_dtdevice(xsm_default_t def, struct domain *d,
+                                      const char *dtpath)
+{
+    return xsm_ops->assign_dtdevice(d, dtpath);
+}
+
+static inline int xsm_test_assign_dtdevice(xsm_default_t def,
+                                           const char *dtpath)
+{
+    return xsm_ops->test_assign_dtdevice(dtpath);
+}
+
+static inline int xsm_deassign_dtdevice(xsm_default_t def, struct domain *d,
+                                        const char *dtpath)
+{
+    return xsm_ops->deassign_dtdevice(d, dtpath);
+}
+
+#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
+
 static inline int xsm_resource_plug_pci (xsm_default_t def, uint32_t machine_bdf)
 {
     return xsm_ops->resource_plug_pci(machine_bdf);
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index a3b8aab..ef856dc 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -96,6 +96,12 @@  void xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, deassign_device);
 #endif
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+    set_to_dummy_if_null(ops, test_assign_dtdevice);
+    set_to_dummy_if_null(ops, assign_dtdevice);
+    set_to_dummy_if_null(ops, deassign_dtdevice);
+#endif
+
     set_to_dummy_if_null(ops, resource_plug_core);
     set_to_dummy_if_null(ops, resource_unplug_core);
     set_to_dummy_if_null(ops, resource_plug_pci);
diff --git a/xen/xsm/flask/avc.c b/xen/xsm/flask/avc.c
index b1a4f8a..31bc702 100644
--- a/xen/xsm/flask/avc.c
+++ b/xen/xsm/flask/avc.c
@@ -600,6 +600,9 @@  void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
     case AVC_AUDIT_DATA_MEMORY:
         avc_printk(&buf, "pte=%#lx mfn=%#lx ", a->memory.pte, a->memory.mfn);
         break;
+    case AVC_AUDIT_DATA_DTDEV:
+        avc_printk(&buf, "dtdevice=%s ", a->dtdev);
+        break;
     }
 
     avc_dump_query(&buf, ssid, tsid, tclass);
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 688ba2a..074eb81 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -589,7 +589,12 @@  static int flask_domctl(struct domain *d, int cmd)
     case XEN_DOMCTL_shadow_op:
     case XEN_DOMCTL_ioport_permission:
     case XEN_DOMCTL_ioport_mapping:
-    /* These have individual XSM hooks (drivers/passthrough/iommu.c) */
+#endif
+#ifdef HAS_PASSTHROUGH
+    /*
+     * These have individual XSM hooks
+     * (drivers/passthrough/{pci,device_tree.c)
+     */
     case XEN_DOMCTL_get_device_group:
     case XEN_DOMCTL_test_assign_device:
     case XEN_DOMCTL_assign_device:
@@ -1231,6 +1236,62 @@  static int flask_deassign_device(struct domain *d, uint32_t machine_bdf)
 }
 #endif /* HAS_PASSTHROUGH && HAS_PCI */
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+static int flask_test_assign_dtdevice(const char *dtpath)
+{
+    u32 rsid;
+    int rc = -EPERM;
+
+    rc = security_devicetree_sid(dtpath, &rsid);
+    if ( rc )
+        return rc;
+
+    return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE,
+                                NULL);
+}
+
+static int flask_assign_dtdevice(struct domain *d, const char *dtpath)
+{
+    u32 dsid, rsid;
+    int rc = -EPERM;
+    struct avc_audit_data ad;
+
+    rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
+    if ( rc )
+        return rc;
+
+    rc = security_devicetree_sid(dtpath, &rsid);
+    if ( rc )
+        return rc;
+
+    AVC_AUDIT_DATA_INIT(&ad, DTDEV);
+    ad.dtdev = dtpath;
+    rc = avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, &ad);
+    if ( rc )
+        return rc;
+
+    dsid = domain_sid(d);
+    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+}
+
+static int flask_deassign_dtdevice(struct domain *d, const char *dtpath)
+{
+    u32 rsid;
+    int rc = -EPERM;
+
+    rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
+    if ( rc )
+        return rc;
+
+    rc = security_devicetree_sid(dtpath, &rsid);
+    if ( rc )
+        return rc;
+
+    return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE,
+                                NULL);
+}
+#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
+
 #ifdef HAS_MEM_ACCESS
 static int flask_vm_event_control(struct domain *d, int mode, int op)
 {
@@ -1598,6 +1659,12 @@  static struct xsm_operations flask_ops = {
     .deassign_device = flask_deassign_device,
 #endif
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+    .test_assign_dtdevice = flask_test_assign_dtdevice,
+    .assign_dtdevice = flask_assign_dtdevice,
+    .deassign_dtdevice = flask_deassign_dtdevice,
+#endif
+
 #ifdef HAS_MEM_ACCESS
     .vm_event_control = flask_vm_event_control,
     .vm_event_op = flask_vm_event_op,
diff --git a/xen/xsm/flask/include/avc.h b/xen/xsm/flask/include/avc.h
index c7a99fc..4283562 100644
--- a/xen/xsm/flask/include/avc.h
+++ b/xen/xsm/flask/include/avc.h
@@ -39,6 +39,7 @@  struct avc_audit_data {
 #define AVC_AUDIT_DATA_IRQ   2
 #define AVC_AUDIT_DATA_RANGE 3
 #define AVC_AUDIT_DATA_MEMORY 4
+#define AVC_AUDIT_DATA_DTDEV 5
     struct domain *sdom;
     struct domain *tdom;
     union {
@@ -52,6 +53,7 @@  struct avc_audit_data {
             unsigned long pte;
             unsigned long mfn;
         } memory;
+        const char *dtdev;
     };
 };
 
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index 128250e..5a760c5 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -416,7 +416,7 @@  class resource
     remove_iomem
 # XEN_DOMCTL_get_device_group, XEN_DOMCTL_test_assign_device:
 #  source = domain making the hypercall
-#  target = PCI device being queried
+#  target = device being queried
     stat_device
 # XEN_DOMCTL_assign_device
     add_device