[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] xsm/flask: fix resource list range checks
# HG changeset patch # User Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> # Date 1321968588 0 # Node ID d3859e348951cde6b211c5afb610ac1f12a909ec # Parent 0db9c1fc8213013f48110cb19641a286140c0563 xsm/flask: fix resource list range checks The FLASK security checks for resource ranges were not implemented correctly - only the permissions on the endpoints of a range were checked, instead of all items contained in the range. This would allow certain resources (I/O ports, I/O memory) to be used by domains in contravention to security policy. This also corrects a bug where adding overlapping resource ranges did not trigger an error. Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> Committed-by: Keir Fraser <keir@xxxxxxx> --- diff -r 0db9c1fc8213 -r d3859e348951 xen/xsm/flask/hooks.c --- a/xen/xsm/flask/hooks.c Tue Nov 22 13:29:01 2011 +0000 +++ b/xen/xsm/flask/hooks.c Tue Nov 22 13:29:48 2011 +0000 @@ -664,14 +664,32 @@ return rc; } -static int iomem_has_perm(struct domain *d, unsigned long mfn, uint8_t access) +struct iomem_has_perm_data { + struct domain_security_struct *ssec, *tsec; + u32 perm; +}; + +static int _iomem_has_perm(void *v, u32 sid, unsigned long start, unsigned long end) { - u32 perm; - u32 rsid; + struct iomem_has_perm_data *data = v; + struct avc_audit_data ad; int rc = -EPERM; - struct domain_security_struct *ssec, *tsec; - struct avc_audit_data ad; + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = start; + + rc = avc_has_perm(data->ssec->sid, sid, SECCLASS_RESOURCE, data->perm, &ad); + + if ( rc ) + return rc; + + return avc_has_perm(data->tsec->sid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); +} + +static int iomem_has_perm(struct domain *d, unsigned long start, unsigned long end, uint8_t access) +{ + struct iomem_has_perm_data data; + int rc; rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, resource_to_perm(access)); @@ -679,27 +697,14 @@ return rc; if ( access ) - perm = RESOURCE__ADD_IOMEM; + data.perm = RESOURCE__ADD_IOMEM; else - perm = RESOURCE__REMOVE_IOMEM; + data.perm = RESOURCE__REMOVE_IOMEM; - ssec = current->domain->ssid; - tsec = d->ssid; + data.ssec = current->domain->ssid; + data.tsec = d->ssid; - rc = security_iomem_sid(mfn, &rsid); - if ( rc ) - return rc; - - AVC_AUDIT_DATA_INIT(&ad, DEV); - ad.device = mfn; - - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); - - if ( rc ) - return rc; - - return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, - RESOURCE__USE, &ad); + return security_iterate_iomem_sids(start, end, _iomem_has_perm, &data); } static int flask_perfcontrol(void) @@ -736,14 +741,33 @@ return domain_has_perm(current->domain, d, SECCLASS_SHADOW, perm); } -static int ioport_has_perm(struct domain *d, uint32_t ioport, uint8_t access) +struct ioport_has_perm_data { + struct domain_security_struct *ssec, *tsec; + u32 perm; +}; + +static int _ioport_has_perm(void *v, u32 sid, unsigned long start, unsigned long end) { - u32 perm; - u32 rsid; - int rc = -EPERM; + struct ioport_has_perm_data *data = v; + struct avc_audit_data ad; + int rc; - struct avc_audit_data ad; - struct domain_security_struct *ssec, *tsec; + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = start; + + rc = avc_has_perm(data->ssec->sid, sid, SECCLASS_RESOURCE, data->perm, &ad); + + if ( rc ) + return rc; + + return avc_has_perm(data->tsec->sid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); +} + + +static int ioport_has_perm(struct domain *d, uint32_t start, uint32_t end, uint8_t access) +{ + int rc; + struct ioport_has_perm_data data; rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, resource_to_perm(access)); @@ -752,29 +776,14 @@ return rc; if ( access ) - perm = RESOURCE__ADD_IOPORT; + data.perm = RESOURCE__ADD_IOPORT; else - perm = RESOURCE__REMOVE_IOPORT; + data.perm = RESOURCE__REMOVE_IOPORT; - ssec = current->domain->ssid; - tsec = d->ssid; + data.ssec = current->domain->ssid; + data.tsec = d->ssid; - rc = security_ioport_sid(ioport, &rsid); - if ( rc ) - return rc; - - AVC_AUDIT_DATA_INIT(&ad, DEV); - ad.device = ioport; - - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); - if ( rc ) - return rc; - - if ( access ) - return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, - RESOURCE__USE, &ad); - else - return rc; + return security_iterate_ioport_sids(start, end, _ioport_has_perm, &data); } static int flask_getpageframeinfo(struct page_info *page) @@ -1184,31 +1193,25 @@ if ( strcmp(name, "I/O Memory") == 0 ) { - rc = iomem_has_perm(d, s, access); + rc = iomem_has_perm(d, s, e, access); if ( rc ) return rc; - - if ( s != e ) - rc = iomem_has_perm(d, e, access); } else if ( strcmp(name, "Interrupts") == 0 ) { - rc = irq_has_perm(d, s, access); - if ( rc ) - return rc; - - if ( s != e ) - rc = irq_has_perm(d, e, access); + while (s <= e) { + rc = irq_has_perm(d, s, access); + if ( rc ) + return rc; + s++; + } } #ifdef CONFIG_X86 else if ( strcmp(name, "I/O Ports") == 0 ) { - rc = ioport_has_perm(d, s, access); + rc = ioport_has_perm(d, s, e, access); if ( rc ) return rc; - - if ( s != e ) - rc = ioport_has_perm(d, e, access); } #endif diff -r 0db9c1fc8213 -r d3859e348951 xen/xsm/flask/include/security.h --- a/xen/xsm/flask/include/security.h Tue Nov 22 13:29:01 2011 +0000 +++ b/xen/xsm/flask/include/security.h Tue Nov 22 13:29:48 2011 +0000 @@ -82,6 +82,14 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, u16 tclass); +typedef int (*security_iterate_fn)(void *data, u32 sid, unsigned long start, + unsigned long end); +int security_iterate_iomem_sids(unsigned long start, unsigned long end, + security_iterate_fn fn, void *data); + +int security_iterate_ioport_sids(u32 start, u32 end, + security_iterate_fn fn, void *data); + int security_ocontext_add(char *ocontext, unsigned long low, unsigned long high, u32 sid); diff -r 0db9c1fc8213 -r d3859e348951 xen/xsm/flask/ss/services.c --- a/xen/xsm/flask/ss/services.c Tue Nov 22 13:29:01 2011 +0000 +++ b/xen/xsm/flask/ss/services.c Tue Nov 22 13:29:48 2011 +0000 @@ -1594,6 +1594,53 @@ return rc; } +int security_iterate_iomem_sids(unsigned long start, unsigned long end, + security_iterate_fn fn, void *data) +{ + struct ocontext *c; + int rc = 0; + + POLICY_RDLOCK; + + c = policydb.ocontexts[OCON_IOMEM]; + while (c && c->u.iomem.high_iomem < start) + c = c->next; + + while (c && c->u.iomem.low_iomem <= end) { + if (!c->sid[0]) + { + rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]); + if ( rc ) + goto out; + } + if (start < c->u.iomem.low_iomem) { + /* found a gap */ + rc = fn(data, SECINITSID_IOMEM, start, c->u.iomem.low_iomem - 1); + if (rc) + goto out; + start = c->u.iomem.low_iomem; + } + if (end <= c->u.iomem.high_iomem) { + /* iteration ends in the middle of this range */ + rc = fn(data, c->sid[0], start, end); + goto out; + } + + rc = fn(data, c->sid[0], start, c->u.iomem.high_iomem); + if (rc) + goto out; + start = c->u.iomem.high_iomem + 1; + + c = c->next; + } + + rc = fn(data, SECINITSID_IOMEM, start, end); + +out: + POLICY_RDUNLOCK; + return rc; +} + /** * security_ioport_sid - Obtain the SID for an ioport. * @ioport: ioport @@ -1635,6 +1682,53 @@ return rc; } +int security_iterate_ioport_sids(u32 start, u32 end, + security_iterate_fn fn, void *data) +{ + struct ocontext *c; + int rc = 0; + + POLICY_RDLOCK; + + c = policydb.ocontexts[OCON_IOPORT]; + while (c && c->u.ioport.high_ioport < start) + c = c->next; + + while (c && c->u.ioport.low_ioport <= end) { + if (!c->sid[0]) + { + rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]); + if ( rc ) + goto out; + } + if (start < c->u.ioport.low_ioport) { + /* found a gap */ + rc = fn(data, SECINITSID_IOPORT, start, c->u.ioport.low_ioport - 1); + if (rc) + goto out; + start = c->u.ioport.low_ioport; + } + if (end <= c->u.ioport.high_ioport) { + /* iteration ends in the middle of this range */ + rc = fn(data, c->sid[0], start, end); + goto out; + } + + rc = fn(data, c->sid[0], start, c->u.ioport.high_ioport); + if (rc) + goto out; + start = c->u.ioport.high_ioport + 1; + + c = c->next; + } + + rc = fn(data, SECINITSID_IOPORT, start, end); + +out: + POLICY_RDUNLOCK; + return rc; +} + /** * security_device_sid - Obtain the SID for a PCI device. * @ioport: device @@ -1963,6 +2057,7 @@ int ret = 0; int ocon = 0; struct ocontext *c; + struct ocontext *prev; struct ocontext *add; if ( (ocon = determine_ocontext(ocontext)) < 0 ) @@ -2006,23 +2101,27 @@ add->u.ioport.low_ioport = low; add->u.ioport.high_ioport = high; + prev = NULL; c = policydb.ocontexts[OCON_IOPORT]; - while ( c ) - { - if ( c->u.ioport.low_ioport <= add->u.ioport.high_ioport && - add->u.ioport.low_ioport <= c->u.ioport.high_ioport ) - { - printk("%s: IO Port overlap with entry 0x%x - 0x%x\n", - __FUNCTION__, c->u.ioport.low_ioport, - c->u.ioport.high_ioport); - ret = -EINVAL; - break; - } + + while ( c && c->u.ioport.high_ioport < low ) { + prev = c; c = c->next; } - if ( ret == 0 ) + if (c && c->u.ioport.low_ioport <= high) { + printk("%s: IO Port overlap with entry 0x%x - 0x%x\n", + __FUNCTION__, c->u.ioport.low_ioport, + c->u.ioport.high_ioport); + ret = -EINVAL; + break; + } + + if (prev) { + add->next = prev->next; + prev->next = add; + } else { add->next = policydb.ocontexts[OCON_IOPORT]; policydb.ocontexts[OCON_IOPORT] = add; } @@ -2032,23 +2131,27 @@ add->u.iomem.low_iomem = low; add->u.iomem.high_iomem = high; + prev = NULL; c = policydb.ocontexts[OCON_IOMEM]; - while ( c ) - { - if ( c->u.iomem.low_iomem <= add->u.iomem.high_iomem && - add->u.iomem.low_iomem <= c->u.iomem.high_iomem ) - { - printk("%s: IO Memory overlap with entry 0x%x - 0x%x\n", - __FUNCTION__, c->u.iomem.low_iomem, - c->u.iomem.high_iomem); - ret = -EINVAL; - break; - } + + while ( c && c->u.iomem.high_iomem < low ) { + prev = c; c = c->next; } - if ( ret == 0 ) + if (c && c->u.iomem.low_iomem <= high) { + printk("%s: IO Memory overlap with entry 0x%x - 0x%x\n", + __FUNCTION__, c->u.iomem.low_iomem, + c->u.iomem.high_iomem); + ret = -EINVAL; + break; + } + + if (prev) { + add->next = prev->next; + prev->next = add; + } else { add->next = policydb.ocontexts[OCON_IOMEM]; policydb.ocontexts[OCON_IOMEM] = add; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |