Stefano Stabellini
2009-Oct-21 14:32 UTC
[Xen-devel] [PATCH 1 of 2] xen: fix the security issue with stubdoms and pci passthrough
This patch adds securty checks for pci passthrough related hypercalls to enforce that the current domain owns the resources that it is about to remap. It also adds a call to xc_assign_device to xend and removes the PRIVILEGED_STUBDOMS flags. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- diff -r 3bbe9ab2202b tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Wed Oct 21 09:23:10 2009 +0100 +++ b/tools/python/xen/xend/server/pciif.py Wed Oct 21 14:51:20 2009 +0100 @@ -444,7 +444,15 @@ # For hvm guest, (from c/s 19679 on) assigning device statically and # dynamically both go through reconfigureDevice(), so HERE the # setupOneDevice() is not necessary. - if not self.vm.info.is_hvm(): + if self.vm.info.is_hvm(): + for pci_dev in pci_dev_list: + # Setup IOMMU device assignment + bdf = xc.assign_device(self.getDomid(), pci_dict_to_xc_str(pci_dev)) + pci_str = pci_dict_to_bdf_str(pci_dev) + if bdf > 0: + raise VmError("Failed to assign device to IOMMU (%s)" % pci_str) + log.debug("pci: assign device %s" % pci_str) + else : for d in pci_dev_list: self.setupOneDevice(d) wPath = ''/local/domain/0/backend/pci/%u/0/aerState'' % (self.getDomid()) diff -r 3bbe9ab2202b xen/Rules.mk --- a/xen/Rules.mk Wed Oct 21 09:23:10 2009 +0100 +++ b/xen/Rules.mk Wed Oct 21 14:51:20 2009 +0100 @@ -10,9 +10,6 @@ crash_debug ?= n gdbsx ?= n frame_pointer ?= n - -# Allow some delicate passthrough related hypercalls to be made from a stubdom -privileged_stubdoms ?= y XEN_ROOT=$(BASEDIR)/.. include $(XEN_ROOT)/Config.mk @@ -56,7 +53,6 @@ CFLAGS-$(perfc_arrays) += -DPERF_ARRAYS CFLAGS-$(lock_profile) += -DLOCK_PROFILE CFLAGS-$(frame_pointer) += -fno-omit-frame-pointer -DCONFIG_FRAME_POINTER -CFLAGS-$(privileged_stubdoms) += -DPRIVILEGED_STUBDOMS CFLAGS-$(gdbsx) += -DXEN_GDBSX_CONFIG ifneq ($(max_phys_cpus),) diff -r 3bbe9ab2202b xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Wed Oct 21 09:23:10 2009 +0100 +++ b/xen/arch/x86/domctl.c Wed Oct 21 14:51:20 2009 +0100 @@ -796,6 +796,11 @@ if ( ret ) goto bind_out; + ret = -EPERM; + if ( !IS_PRIV(current->domain) && + !irq_access_permitted(current->domain, bind->machine_irq) ) + goto bind_out; + ret = -ESRCH; if ( iommu_enabled ) { @@ -820,6 +825,12 @@ if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) break; bind = &(domctl->u.bind_pt_irq); + + ret = -EPERM; + if ( !IS_PRIV(current->domain) && + !irq_access_permitted(current->domain, bind->machine_irq) ) + goto bind_out; + if ( iommu_enabled ) { spin_lock(&pcidevs_lock); @@ -846,6 +857,11 @@ ret = -ESRCH; if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) ) + break; + + ret = -EPERM; + if ( !IS_PRIV(current->domain) && + !iomem_access_permitted(current->domain, mfn, mfn + nr_mfns - 1) ) break; ret=0; @@ -894,6 +910,11 @@ fgp, fmp, np); break; } + + ret = -EPERM; + if ( !IS_PRIV(current->domain) && + !ioports_access_permitted(current->domain, fmp, fmp + np - 1) ) + break; ret = -ESRCH; if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) ) diff -r 3bbe9ab2202b xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Wed Oct 21 09:23:10 2009 +0100 +++ b/xen/arch/x86/irq.c Wed Oct 21 14:51:20 2009 +0100 @@ -1340,7 +1340,9 @@ ASSERT(spin_is_locked(&pcidevs_lock)); ASSERT(spin_is_locked(&d->event_lock)); - if ( !STUBDOM_IS_PRIV_FOR(current->domain, d) ) + if ( !IS_PRIV(current->domain) && + !(IS_PRIV_FOR(current->domain, d) && + irq_access_permitted(current->domain, pirq))) return -EPERM; if ( pirq < 0 || pirq >= d->nr_pirqs || irq < 0 || irq >= nr_irqs ) diff -r 3bbe9ab2202b xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Wed Oct 21 09:23:10 2009 +0100 +++ b/xen/arch/x86/physdev.c Wed Oct 21 14:51:20 2009 +0100 @@ -45,7 +45,7 @@ if ( d == NULL ) return -ESRCH; - if ( !STUBDOM_IS_PRIV_FOR(current->domain, d) ) + if ( !IS_PRIV_FOR(current->domain, d) ) { ret = -EPERM; goto free_domain; @@ -169,7 +169,7 @@ return -ESRCH; ret = -EPERM; - if ( !STUBDOM_IS_PRIV_FOR(current->domain, d) ) + if ( !IS_PRIV_FOR(current->domain, d) ) goto free_domain; spin_lock(&pcidevs_lock); diff -r 3bbe9ab2202b xen/common/domctl.c --- a/xen/common/domctl.c Wed Oct 21 09:23:10 2009 +0100 +++ b/xen/common/domctl.c Wed Oct 21 14:51:20 2009 +0100 @@ -231,14 +231,12 @@ case XEN_DOMCTL_ioport_mapping: case XEN_DOMCTL_memory_mapping: case XEN_DOMCTL_bind_pt_irq: - case XEN_DOMCTL_unbind_pt_irq: - case XEN_DOMCTL_assign_device: - case XEN_DOMCTL_deassign_device: { + case XEN_DOMCTL_unbind_pt_irq: { struct domain *d; bool_t is_priv = IS_PRIV(current->domain); if ( !is_priv && ((d = rcu_lock_domain_by_id(op->domain)) != NULL) ) { - is_priv = STUBDOM_IS_PRIV_FOR(current->domain, d); + is_priv = IS_PRIV_FOR(current->domain, d); rcu_unlock_domain(d); } if ( !is_priv ) diff -r 3bbe9ab2202b xen/include/xen/config.h --- a/xen/include/xen/config.h Wed Oct 21 09:23:10 2009 +0100 +++ b/xen/include/xen/config.h Wed Oct 21 14:51:20 2009 +0100 @@ -95,10 +95,4 @@ #define __cpuinitdata #define __cpuinit -#ifdef PRIVILEGED_STUBDOMS -#define STUBDOM_IS_PRIV_FOR(x,y) IS_PRIV_FOR(x,y) -#else -#define STUBDOM_IS_PRIV_FOR(x,y) IS_PRIV(x) -#endif - #endif /* __XEN_CONFIG_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel