[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 7/8] xsm: add checks on PCI configuration access
PCI configuration access is allowed to any privileged domain regardless of I/O port access restrictions; add XSM hooks for these accesses. Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> --- xen/arch/x86/traps.c | 26 ++++++++++++++++++++++---- xen/arch/x86/x86_64/mmconfig_64.c | 13 +++++++++++++ xen/include/xsm/xsm.h | 6 ++++++ xen/xsm/dummy.c | 8 ++++++++ xen/xsm/flask/hooks.c | 24 ++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 7f38ddc..2d585c8 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -72,6 +72,7 @@ #include <asm/mc146818rtc.h> #include <asm/hpet.h> #include <public/arch-x86/cpuid.h> +#include <xsm/xsm.h> /* * opt_nmi: one of 'ignore', 'dom0', or 'fatal'. @@ -1680,6 +1681,21 @@ static int admin_io_okay( return ioports_access_permitted(v->domain, port, port + bytes - 1); } +static int pci_cfg_ok(struct domain *d, int write, int size) +{ + uint32_t machine_bdf; + uint16_t start, end; + if (!IS_PRIV(d)) + return 0; + + machine_bdf = (d->arch.pci_cf8 >> 8) & 0xFFFF; + start = d->arch.pci_cf8 & 0xFF; + end = start + size - 1; + if (xsm_pci_config_permission(d, machine_bdf, start, end, write)) + return 0; + return 1; +} + static uint32_t guest_io_read( unsigned int port, unsigned int bytes, struct vcpu *v, struct cpu_user_regs *regs) @@ -1726,12 +1742,13 @@ static uint32_t guest_io_read( size = 4; sub_data = v->domain->arch.pci_cf8; } - else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) ) + else if ( (port & 0xfffc) == 0xcfc ) { size = min(bytes, 4 - (port & 3)); if ( size == 3 ) size = 2; - sub_data = pci_conf_read(v->domain->arch.pci_cf8, port & 3, size); + if ( pci_cfg_ok(v->domain, 0, size) ) + sub_data = pci_conf_read(v->domain->arch.pci_cf8, port & 3, size); } if ( size == 4 ) @@ -1798,12 +1815,13 @@ static void guest_io_write( size = 4; v->domain->arch.pci_cf8 = data; } - else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) ) + else if ( (port & 0xfffc) == 0xcfc ) { size = min(bytes, 4 - (port & 3)); if ( size == 3 ) size = 2; - pci_conf_write(v->domain->arch.pci_cf8, port & 3, size, data); + if ( pci_cfg_ok(v->domain, 1, size) ) + pci_conf_write(v->domain->arch.pci_cf8, port & 3, size, data); } if ( size == 4 ) diff --git a/xen/arch/x86/x86_64/mmconfig_64.c b/xen/arch/x86/x86_64/mmconfig_64.c index 16d432e..f2e7fed 100644 --- a/xen/arch/x86/x86_64/mmconfig_64.c +++ b/xen/arch/x86/x86_64/mmconfig_64.c @@ -14,6 +14,7 @@ #include <xen/xmalloc.h> #include <xen/pci.h> #include <xen/pci_regs.h> +#include <xsm/xsm.h> #include "mmconfig.h" @@ -58,6 +59,7 @@ int pci_mmcfg_read(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 *value) { char __iomem *addr; + uint32_t mbdf; /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) { @@ -65,6 +67,12 @@ err: *value = -1; return -EINVAL; } + mbdf = (seg << 16) | (bus << 8) | devfn; + if (xsm_pci_config_permission(current->domain, mbdf, reg, reg + len - 1, 0)) { + *value = -1; + return -EPERM; + } + addr = pci_dev_base(seg, bus, devfn); if (!addr) goto err; @@ -88,11 +96,16 @@ int pci_mmcfg_write(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 value) { char __iomem *addr; + uint32_t mbdf; /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) return -EINVAL; + mbdf = (seg << 16) | (bus << 8) | devfn; + if (xsm_pci_config_permission(current->domain, mbdf, reg, reg + len - 1, 1)) + return -EPERM; + addr = pci_dev_base(seg, bus, devfn); if (!addr) return -EINVAL; diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 0c7f248..df6cec2 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -113,6 +113,7 @@ struct xsm_operations { int (*schedop_shutdown) (struct domain *d1, struct domain *d2); 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 (*pci_config_permission) (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access); int (*get_device_group) (uint32_t machine_bdf); int (*test_assign_device) (uint32_t machine_bdf); @@ -473,6 +474,11 @@ static inline int xsm_iomem_permission (struct domain *d, uint64_t s, uint64_t e return xsm_call(iomem_permission(d, s, e, allow)); } +static inline int xsm_pci_config_permission (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access) +{ + return xsm_call(pci_config_permission(d, machine_bdf, start, end, access)); +} + static inline int xsm_get_device_group(uint32_t machine_bdf) { return xsm_call(get_device_group(machine_bdf)); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index a4accb8..4bbfbff 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -369,6 +369,13 @@ static int dummy_iomem_permission (struct domain *d, uint64_t s, uint64_t e, uin return 0; } +static int dummy_pci_config_permission (struct domain *d, uint32_t machine_bdf, + uint16_t start, uint16_t end, + uint8_t access) +{ + return 0; +} + #ifdef CONFIG_X86 static int dummy_shadow_control (struct domain *d, uint32_t op) { @@ -631,6 +638,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, irq_permission); set_to_dummy_if_null(ops, iomem_permission); + set_to_dummy_if_null(ops, pci_config_permission); set_to_dummy_if_null(ops, test_assign_device); set_to_dummy_if_null(ops, assign_device); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index efe52bb..0d35767 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -762,6 +762,29 @@ static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end return security_iterate_iomem_sids(start, end, _iomem_has_perm, &data); } +static int flask_pci_config_permission(struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access) +{ + u32 rsid; + int rc = -EPERM; + struct avc_audit_data ad; + struct domain_security_struct *ssec; + u32 perm = RESOURCE__USE; + + rc = security_device_sid(machine_bdf, &rsid); + if ( rc ) + return rc; + + /* Writes to the BARs count as setup */ + if ( access && (end >= 0x10 && start < 0x28) ) + perm = RESOURCE__SETUP; + + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = (unsigned long) machine_bdf; + ssec = d->ssid; + return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); + +} + static int flask_resource_plug_core(void) { struct domain_security_struct *ssec; @@ -1481,6 +1504,7 @@ static struct xsm_operations flask_ops = { .irq_permission = flask_irq_permission, .iomem_permission = flask_iomem_permission, + .pci_config_permission = flask_pci_config_permission, .resource_plug_core = flask_resource_plug_core, .resource_unplug_core = flask_resource_unplug_core, -- 1.7.7.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |