aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/irq.c13
-rw-r--r--xen/arch/x86/physdev.c18
-rw-r--r--xen/include/xsm/dummy.h16
-rw-r--r--xen/include/xsm/xsm.h24
-rw-r--r--xen/xsm/dummy.c2
-rw-r--r--xen/xsm/flask/hooks.c37
-rw-r--r--xen/xsm/flask/policy/access_vectors5
7 files changed, 77 insertions, 38 deletions
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 095c17dbac..068c5a0228 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1874,7 +1874,7 @@ int map_domain_pirq(
return 0;
}
- ret = xsm_map_domain_pirq(XSM_HOOK, d, irq, data);
+ ret = xsm_map_domain_irq(XSM_HOOK, d, irq, data);
if ( ret )
{
dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d mapping to pirq %d\n",
@@ -1978,14 +1978,19 @@ int unmap_domain_pirq(struct domain *d, int pirq)
goto done;
}
+ desc = irq_to_desc(irq);
+ msi_desc = desc->msi_desc;
+
+ ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq, msi_desc);
+ if ( ret )
+ goto done;
+
forced_unbind = pirq_guest_force_unbind(d, info);
if ( forced_unbind )
dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n",
d->domain_id, pirq);
- desc = irq_to_desc(irq);
-
- if ( (msi_desc = desc->msi_desc) != NULL )
+ if ( msi_desc != NULL )
pci_disable_msi(msi_desc);
spin_lock_irqsave(&desc->lock, flags);
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index b45e18ac51..d9ed5dfd0c 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -105,7 +105,11 @@ int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p,
return physdev_hvm_map_pirq(d, type, index, pirq_p);
}
- ret = rcu_lock_target_domain_by_id(domid, &d);
+ d = rcu_lock_domain_by_any_id(domid);
+ if ( d == NULL )
+ return -ESRCH;
+
+ ret = xsm_map_domain_pirq(XSM_TARGET, d);
if ( ret )
return ret;
@@ -218,9 +222,13 @@ int physdev_unmap_pirq(domid_t domid, int pirq)
struct domain *d;
int ret;
- ret = rcu_lock_target_domain_by_id(domid, &d);
+ d = rcu_lock_domain_by_any_id(domid);
+ if ( d == NULL )
+ return -ESRCH;
+
+ ret = xsm_unmap_domain_pirq(XSM_TARGET, d);
if ( ret )
- return ret;
+ goto free_domain;
if ( is_hvm_domain(d) )
{
@@ -232,10 +240,6 @@ int physdev_unmap_pirq(domid_t domid, int pirq)
goto free_domain;
}
- ret = xsm_unmap_domain_pirq(XSM_TARGET, d, domain_pirq_to_irq(d, pirq));
- if ( ret )
- goto free_domain;
-
spin_lock(&pcidevs_lock);
spin_lock(&d->event_lock);
ret = unmap_domain_pirq(d, pirq);
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index 870bd675c4..19bbe19415 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -405,18 +405,30 @@ static XSM_INLINE char *xsm_show_irq_sid(int irq)
return NULL;
}
-static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d, int irq, void *data)
+static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
+{
+ XSM_ASSERT_ACTION(XSM_TARGET);
+ return xsm_default_action(action, current->domain, d);
+}
+
+static XSM_INLINE int xsm_map_domain_irq(XSM_DEFAULT_ARG struct domain *d, int irq, void *data)
{
XSM_ASSERT_ACTION(XSM_HOOK);
return xsm_default_action(action, current->domain, d);
}
-static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d, int irq)
+static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
XSM_ASSERT_ACTION(XSM_TARGET);
return xsm_default_action(action, current->domain, d);
}
+static XSM_INLINE int xsm_unmap_domain_irq(XSM_DEFAULT_ARG struct domain *d, int irq, void *data)
+{
+ XSM_ASSERT_ACTION(XSM_HOOK);
+ return xsm_default_action(action, current->domain, d);
+}
+
static XSM_INLINE int xsm_irq_permission(XSM_DEFAULT_ARG struct domain *d, int pirq, uint8_t allow)
{
XSM_ASSERT_ACTION(XSM_HOOK);
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 50483440c3..2399da0a6d 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -101,8 +101,10 @@ struct xsm_operations {
int (*schedop_shutdown) (struct domain *d1, struct domain *d2);
char *(*show_irq_sid) (int irq);
- int (*map_domain_pirq) (struct domain *d, int irq, void *data);
- int (*unmap_domain_pirq) (struct domain *d, int irq);
+ int (*map_domain_pirq) (struct domain *d);
+ int (*map_domain_irq) (struct domain *d, int irq, void *data);
+ int (*unmap_domain_pirq) (struct domain *d);
+ int (*unmap_domain_irq) (struct domain *d, int irq, void *data);
int (*irq_permission) (struct domain *d, int pirq, uint8_t allow);
int (*iomem_permission) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow);
int (*iomem_mapping) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow);
@@ -370,14 +372,24 @@ static inline char *xsm_show_irq_sid (int irq)
return xsm_ops->show_irq_sid(irq);
}
-static inline int xsm_map_domain_pirq (xsm_default_t def, struct domain *d, int irq, void *data)
+static inline int xsm_map_domain_pirq (xsm_default_t def, struct domain *d)
{
- return xsm_ops->map_domain_pirq(d, irq, data);
+ return xsm_ops->map_domain_pirq(d);
}
-static inline int xsm_unmap_domain_pirq (xsm_default_t def, struct domain *d, int irq)
+static inline int xsm_map_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
{
- return xsm_ops->unmap_domain_pirq(d, irq);
+ return xsm_ops->map_domain_irq(d, irq, data);
+}
+
+static inline int xsm_unmap_domain_pirq (xsm_default_t def, struct domain *d)
+{
+ return xsm_ops->unmap_domain_pirq(d);
+}
+
+static inline int xsm_unmap_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
+{
+ return xsm_ops->unmap_domain_irq(d, irq, data);
}
static inline int xsm_irq_permission (xsm_default_t def, struct domain *d, int pirq, uint8_t allow)
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index 5031e163a9..dcd3e31526 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -76,7 +76,9 @@ void xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, show_irq_sid);
set_to_dummy_if_null(ops, map_domain_pirq);
+ set_to_dummy_if_null(ops, map_domain_irq);
set_to_dummy_if_null(ops, unmap_domain_pirq);
+ set_to_dummy_if_null(ops, unmap_domain_irq);
set_to_dummy_if_null(ops, irq_permission);
set_to_dummy_if_null(ops, iomem_permission);
set_to_dummy_if_null(ops, iomem_mapping);
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 2a13549045..58695884ae 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -818,18 +818,18 @@ static char *flask_show_irq_sid (int irq)
return ctx;
}
-static int flask_map_domain_pirq (struct domain *d, int irq, void *data)
+static int flask_map_domain_pirq (struct domain *d)
+{
+ return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
+}
+
+static int flask_map_domain_irq (struct domain *d, int irq, void *data)
{
u32 sid, dsid;
int rc = -EPERM;
struct msi_info *msi = data;
struct avc_audit_data ad;
- rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
-
- if ( rc )
- return rc;
-
if ( irq >= nr_static_irqs && msi ) {
u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
AVC_AUDIT_DATA_INIT(&ad, DEV);
@@ -851,22 +851,25 @@ static int flask_map_domain_pirq (struct domain *d, int irq, void *data)
return rc;
}
-static int flask_unmap_domain_pirq (struct domain *d, int irq)
+static int flask_unmap_domain_pirq (struct domain *d)
+{
+ return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
+}
+
+static int flask_unmap_domain_irq (struct domain *d, int irq, void *data)
{
u32 sid;
int rc = -EPERM;
+ struct msi_info *msi = data;
struct avc_audit_data ad;
- rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
- if ( rc )
- return rc;
-
- if ( irq < nr_static_irqs ) {
- rc = get_irq_sid(irq, &sid, &ad);
+ if ( irq >= nr_static_irqs && msi ) {
+ u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
+ AVC_AUDIT_DATA_INIT(&ad, DEV);
+ ad.device = machine_bdf;
+ rc = security_device_sid(machine_bdf, &sid);
} else {
- /* It is currently not possible to check the specific MSI IRQ being
- * removed, since we do not have the msi_info like map_domain_pirq */
- return 0;
+ rc = get_irq_sid(irq, &sid, &ad);
}
if ( rc )
return rc;
@@ -1481,7 +1484,9 @@ static struct xsm_operations flask_ops = {
.show_irq_sid = flask_show_irq_sid,
.map_domain_pirq = flask_map_domain_pirq,
+ .map_domain_irq = flask_map_domain_irq,
.unmap_domain_pirq = flask_unmap_domain_pirq,
+ .unmap_domain_irq = flask_unmap_domain_irq,
.irq_permission = flask_irq_permission,
.iomem_permission = flask_iomem_permission,
.iomem_mapping = flask_iomem_mapping,
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index 2fdaede5e8..36cbacfa13 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -368,12 +368,11 @@ class resource
# target = resource's security label
# also checked when using some core Xen devices (target xen_t)
use
-# PHYSDEVOP_map_pirq and ioapic writes for dom0
+# PHYSDEVOP_map_pirq and ioapic writes for dom0, when acting on real IRQs
# For GSI interrupts, the IRQ's label is indexed by the IRQ number
# For MSI interrupts, the label of the PCI device is used
add_irq
-# PHYSDEVOP_unmap_pirq:
-# This is currently only checked for GSI interrupts
+# PHYSDEVOP_unmap_pirq (same as map, and only for real IRQs)
remove_irq
# XEN_DOMCTL_ioport_permission, XEN_DOMCTL_ioport_mapping
add_ioport