Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:Maintenance:114
xen.openSUSE_Evergreen_11.4
CVE-2013-1919-xsa46.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File CVE-2013-1919-xsa46.patch of Package xen.openSUSE_Evergreen_11.4
x86: fix various issues with handling guest IRQs - properly revoke IRQ access in map_domain_pirq() error path - don't permit replacing an in use IRQ - don't accept inputs in the GSI range for MAP_PIRQ_TYPE_MSI - track IRQ access permission in host IRQ terms, not guest IRQ ones (and with that, also disallow Dom0 access to IRQ0) This is CVE-2013-1919 / XSA-46. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- a/tools/python/xen/xend/server/irqif.py +++ b/tools/python/xen/xend/server/irqif.py @@ -73,6 +73,12 @@ pirq = get_param('irq') + rc = xc.physdev_map_pirq(domid = self.getDomid(), + index = pirq, + pirq = pirq) + if rc < 0: + raise VmError('irq: Failed to map irq %x' % (pirq)) + rc = xc.domain_irq_permission(domid = self.getDomid(), pirq = pirq, allow_access = True) @@ -81,12 +87,6 @@ #todo non-fatal raise VmError( 'irq: Failed to configure irq: %d' % (pirq)) - rc = xc.physdev_map_pirq(domid = self.getDomid(), - index = pirq, - pirq = pirq) - if rc < 0: - raise VmError( - 'irq: Failed to map irq %x' % (pirq)) back = dict([(k, config[k]) for k in self.valid_cfg if k in config]) return (self.allocateDeviceID(), back, {}) --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -1091,7 +1091,7 @@ /* DOM0 is permitted full I/O capabilities. */ rc |= ioports_permit_access(dom0, 0, 0xFFFF); rc |= iomem_permit_access(dom0, 0UL, ~0UL); - rc |= irqs_permit_access(dom0, 0, d->nr_pirqs - 1); + rc |= irqs_permit_access(dom0, 1, nr_irqs_gsi - 1); /* * Modify I/O port access permissions. --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -902,9 +902,13 @@ goto bind_out; ret = -EPERM; - if ( !IS_PRIV(current->domain) && - !irq_access_permitted(current->domain, bind->machine_irq) ) - goto bind_out; + if ( !IS_PRIV(current->domain) ) + { + int irq = domain_pirq_to_irq(d, bind->machine_irq); + + if ( irq <= 0 || !irq_access_permitted(current->domain, irq) ) + goto bind_out; + } ret = -ESRCH; if ( iommu_enabled ) @@ -932,9 +936,13 @@ bind = &(domctl->u.bind_pt_irq); ret = -EPERM; - if ( !IS_PRIV(current->domain) && - !irq_access_permitted(current->domain, bind->machine_irq) ) - goto unbind_out; + if ( !IS_PRIV(current->domain) ) + { + int irq = domain_pirq_to_irq(d, bind->machine_irq); + + if ( irq <= 0 || !irq_access_permitted(current->domain, irq) ) + goto unbind_out; + } if ( iommu_enabled ) { --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -178,6 +178,15 @@ out: spin_unlock_irqrestore(&vector_lock, flags); + if ( irq > 0 && dom0 ) + { + ret = irq_permit_access(dom0, irq); + if ( ret ) + printk(XENLOG_G_ERR + "Could not grant Dom0 access to IRQ%d (error %d)\n", + irq, ret); + } + return irq; } @@ -260,6 +269,17 @@ void destroy_irq(unsigned int irq) { BUG_ON(!MSI_IRQ(irq)); + + if ( dom0 ) + { + int err = irq_deny_access(dom0, irq); + + if ( err ) + printk(XENLOG_G_ERR + "Could not revoke Dom0 access to IRQ%u (error %d)\n", + irq, err); + } + dynamic_irq_cleanup(irq); clear_irq_vector(irq); } @@ -1541,7 +1561,7 @@ if ( !IS_PRIV(current->domain) && !(IS_PRIV_FOR(current->domain, d) && - irq_access_permitted(current->domain, pirq))) + irq_access_permitted(current->domain, irq))) return -EPERM; if ( pirq < 0 || pirq >= d->nr_pirqs || irq < 0 || irq >= nr_irqs ) @@ -1562,11 +1582,12 @@ return 0; } - ret = irq_permit_access(d, pirq); + ret = irq_permit_access(d, irq); if ( ret ) { - dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d\n", - d->domain_id, pirq); + printk(XENLOG_G_ERR + "dom%d: could not permit access to IRQ%d (pirq %d)\n", + d->domain_id, irq, pirq); return ret; } @@ -1588,8 +1609,14 @@ spin_lock_irqsave(&desc->lock, flags); if ( desc->handler != &no_irq_type ) + { + spin_unlock_irqrestore(&desc->lock, flags); dprintk(XENLOG_G_ERR, "dom%d: irq %d in use\n", d->domain_id, irq); + pci_disable_msi(msi_desc); + ret = -EBUSY; + goto done; + } desc->handler = &pci_msi_type; if ( opt_irq_vector_map == OPT_IRQ_VECTOR_MAP_PERDEV && !desc->chip_data->used_vectors ) @@ -1617,6 +1644,10 @@ } done: + if ( ret && irq_deny_access(d, irq) ) + printk(XENLOG_G_ERR + "dom%d: could not revoke access to IRQ%d (pirq %d)\n", + d->domain_id, irq, pirq); return ret; } @@ -1676,10 +1707,11 @@ if (msi_desc) msi_free_irq(msi_desc); - ret = irq_deny_access(d, pirq); + ret = irq_deny_access(d, irq); if ( ret ) - dprintk(XENLOG_G_ERR, "dom%d: could not deny access to irq %d\n", - d->domain_id, pirq); + printk(XENLOG_G_ERR + "dom%d: could not deny access to IRQ%d (pirq %d)\n", + d->domain_id, irq, pirq); if ( desc->handler == &pci_msi_type ) desc->handler = &no_irq_type; --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -82,7 +82,7 @@ if ( irq == -1 ) irq = create_irq(); - if ( irq < 0 || irq >= nr_irqs ) + if ( irq < nr_irqs_gsi || irq >= nr_irqs ) { dprintk(XENLOG_G_ERR, "dom%d: can't create irq for msi!\n", d->domain_id); --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -845,9 +845,9 @@ if ( pirq >= d->nr_pirqs ) ret = -EINVAL; else if ( op->u.irq_permission.allow_access ) - ret = irq_permit_access(d, pirq); + ret = pirq_permit_access(d, pirq); else - ret = irq_deny_access(d, pirq); + ret = pirq_deny_access(d, pirq); rcu_unlock_domain(d); } --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -305,7 +305,7 @@ if ( (pirq < 0) || (pirq >= d->nr_pirqs) ) return -EINVAL; - if ( !irq_access_permitted(d, pirq) ) + if ( !pirq_access_permitted(d, pirq) ) return -EPERM; spin_lock(&d->event_lock); --- a/xen/include/xen/iocap.h +++ b/xen/include/xen/iocap.h @@ -28,4 +28,22 @@ #define irq_access_permitted(d, i) \ rangeset_contains_singleton((d)->irq_caps, i) +#define pirq_permit_access(d, i) ({ \ + struct domain *d__ = (d); \ + int i__ = domain_pirq_to_irq(d__, i); \ + i__ > 0 ? rangeset_add_singleton(d__->irq_caps, i__)\ + : -EINVAL; \ +}) +#define pirq_deny_access(d, i) ({ \ + struct domain *d__ = (d); \ + int i__ = domain_pirq_to_irq(d__, i); \ + i__ > 0 ? rangeset_remove_singleton(d__->irq_caps, i__)\ + : -EINVAL; \ +}) +#define pirq_access_permitted(d, i) ({ \ + struct domain *d__ = (d); \ + rangeset_contains_singleton(d__->irq_caps, \ + domain_pirq_to_irq(d__, i));\ +}) + #endif /* __XEN_IOCAP_H__ */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor