mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/xsm: Add helpers to check permission for device tree passthrough
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>
This commit is contained in:
1 parent
25785da906
commit
5fb6f0a4db
7 files changed
+130
-2
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
@@ -482,6 +488,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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
+68
-1
@@ -587,7 +587,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:
|
||||
@@ -1259,6 +1264,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 CONFIG_X86
|
||||
static int flask_do_mca(void)
|
||||
{
|
||||
@@ -1628,6 +1689,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 CONFIG_X86
|
||||
.do_mca = flask_do_mca,
|
||||
.shadow_control = flask_shadow_control,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -425,7 +425,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
|
||||
|
||||