diff options
-rw-r--r-- | xen/arch/x86/irq.c | 13 | ||||
-rw-r--r-- | xen/arch/x86/physdev.c | 18 | ||||
-rw-r--r-- | xen/include/xsm/dummy.h | 16 | ||||
-rw-r--r-- | xen/include/xsm/xsm.h | 24 | ||||
-rw-r--r-- | xen/xsm/dummy.c | 2 | ||||
-rw-r--r-- | xen/xsm/flask/hooks.c | 37 | ||||
-rw-r--r-- | xen/xsm/flask/policy/access_vectors | 5 |
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 |