[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] xsm: Dynamic update to device ocontexts
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1258149619 0 # Node ID b6bbc0c9e6515b60e550e21d22ca88afdeecd00f # Parent e39cec51aebc38fa7c464c867c21c4c3a7ffb1ef xsm: Dynamic update to device ocontexts Added the ability to add and delete ocontexts dynamically on a running system. Two new commands have been added to the xsm hypercall, add and delete ocontext. Twelve new library functions have been implemented that use the hypercall commands to label and unlabel pirqs, PCI devices, I/O ports and memory. The base policy has been updated so dom0 has the ability to use the hypercall commands by default. Items added to the list will not be present next time the system reloads. They will need to be added to the static policy. Signed-off-by : George Coker <gscoker@xxxxxxxxxxxxxx> Signed-off-by : Paul Nuzzi <pjnuzzi@xxxxxxxxxxxxxx> --- tools/flask/libflask/flask_op.c | 233 +++++++++++++++++++++ tools/flask/libflask/include/flask.h | 19 + tools/flask/policy/policy/flask/access_vectors | 2 tools/flask/policy/policy/modules/xen/xen.te | 2 xen/include/public/xsm/flask_op.h | 4 xen/xsm/flask/flask_op.c | 103 +++++++++ xen/xsm/flask/include/av_perm_to_string.h | 2 xen/xsm/flask/include/av_permissions.h | 2 xen/xsm/flask/include/security.h | 4 xen/xsm/flask/ss/services.c | 274 +++++++++++++++++++++++++ 10 files changed, 642 insertions(+), 3 deletions(-) diff -r e39cec51aebc -r b6bbc0c9e651 tools/flask/libflask/flask_op.c --- a/tools/flask/libflask/flask_op.c Fri Nov 13 21:59:20 2009 +0000 +++ b/tools/flask/libflask/flask_op.c Fri Nov 13 22:00:19 2009 +0000 @@ -109,3 +109,236 @@ int flask_setenforce(int xc_handle, int return 0; } + +int flask_add_pirq(int xc_handle, unsigned int pirq, char *scontext) +{ + int err; + flask_op_t op; + char *buf; + char *pirq_s = OCON_PIRQ_STR; + int size = INITCONTEXTLEN + strlen(pirq_s) + (sizeof(unsigned int)) + + (sizeof(char) * 3); + + if ( (buf = (char *) malloc(size)) == NULL ) + return -ENOMEM; + memset(buf, 0, size); + + op.cmd = FLASK_ADD_OCONTEXT; + snprintf(buf, size, "%s %255s %u", pirq_s, scontext, pirq); + op.buf = buf; + op.size = size; + + if ( (err = xc_flask_op(xc_handle, &op)) != 0 ) + { + free(buf); + return err; + } + + free(buf); + return 0; + +} + +int flask_add_ioport(int xc_handle, unsigned long low, unsigned long high, + char *scontext) +{ + int err; + flask_op_t op; + char *buf; + char *ioport = OCON_IOPORT_STR; + int size = INITCONTEXTLEN + strlen(ioport) + + (sizeof(unsigned long) * 2) + (sizeof(char) * 4); + + if ( (buf = (char *) malloc(size)) == NULL ) + return -ENOMEM; + memset(buf, 0, size); + + op.cmd = FLASK_ADD_OCONTEXT; + snprintf(buf, size, "%s %255s %li %li", ioport, scontext, low, high); + op.buf = buf; + op.size = size; + + if ( (err = xc_flask_op(xc_handle, &op)) != 0 ) + { + free(buf); + return err; + } + + free(buf); + return 0; + +} + +int flask_add_iomem(int xc_handle, unsigned long low, unsigned long high, + char *scontext) +{ + int err; + flask_op_t op; + char *buf; + char *iomem = OCON_IOMEM_STR; + int size = INITCONTEXTLEN + strlen(iomem) + + (sizeof(unsigned long) * 2) + (sizeof(char) * 4); + + if ( (buf = (char *) malloc(size)) == NULL ) + return -ENOMEM; + memset(buf, 0, size); + + op.cmd = FLASK_ADD_OCONTEXT; + snprintf(buf, size, "%s %255s %li %li", iomem, scontext, low, high); + op.buf = buf; + op.size = size; + + if ( (err = xc_flask_op(xc_handle, &op)) != 0 ) + { + free(buf); + return err; + } + + free(buf); + return 0; + +} + +int flask_add_device(int xc_handle, unsigned long device, char *scontext) +{ + int err; + flask_op_t op; + char *buf; + char *dev = OCON_DEVICE_STR; + int size = INITCONTEXTLEN + strlen(dev) + (sizeof(unsigned long)) + + (sizeof(char) * 3); + + if ( (buf = (char *) malloc(size)) == NULL ) + return -ENOMEM; + memset(buf, 0, size); + + op.cmd = FLASK_ADD_OCONTEXT; + snprintf(buf, size, "%s %255s %li", dev, scontext, device); + op.buf = buf; + op.size = size; + + if ( (err = xc_flask_op(xc_handle, &op)) != 0 ) + { + free(buf); + return err; + } + + free(buf); + return 0; + +} + +int flask_del_pirq(int xc_handle, unsigned int pirq) +{ + int err; + flask_op_t op; + char *buf; + char *pirq_s = OCON_PIRQ_STR; + int size = strlen(pirq_s) + (sizeof(unsigned int)) + + (sizeof(char) * 2); + + if ( (buf = (char *) malloc(size)) == NULL ) + return -ENOMEM; + memset(buf, 0, size); + + op.cmd = FLASK_DEL_OCONTEXT; + snprintf(buf, size, "%s %u", pirq_s, pirq); + op.buf = buf; + op.size = size; + + if ( (err = xc_flask_op(xc_handle, &op)) != 0 ) + { + free(buf); + return err; + } + + free(buf); + return 0; + +} + +int flask_del_ioport(int xc_handle, unsigned long low, unsigned long high) +{ + int err; + flask_op_t op; + char *buf; + char *ioport = OCON_IOPORT_STR; + int size = strlen(ioport) + (sizeof(unsigned long) * 2) + + (sizeof(char) * 3); + + if ( (buf = (char *) malloc(size)) == NULL ) + return -ENOMEM; + memset(buf, 0, size); + + op.cmd = FLASK_DEL_OCONTEXT; + snprintf(buf, size, "%s %li %li", ioport, low, high); + op.buf = buf; + op.size = size; + + if ( (err = xc_flask_op(xc_handle, &op)) != 0 ) + { + free(buf); + return err; + } + + free(buf); + return 0; + +} + +int flask_del_iomem(int xc_handle, unsigned long low, unsigned long high) +{ + int err; + flask_op_t op; + char *buf; + char *iomem = OCON_IOMEM_STR; + int size = strlen(iomem) + (sizeof(unsigned long) * 2) + + (sizeof(char) * 3); + + if ( (buf = (char *) malloc(size)) == NULL ) + return -ENOMEM; + memset(buf, 0, size); + + op.cmd = FLASK_DEL_OCONTEXT; + snprintf(buf, size, "%s %li %li", iomem, low, high); + op.buf = buf; + op.size = size; + + if ( (err = xc_flask_op(xc_handle, &op)) != 0 ) + { + free(buf); + return err; + } + + free(buf); + return 0; + +} + +int flask_del_device(int xc_handle, unsigned long device) +{ + int err; + flask_op_t op; + char *buf; + char *dev = OCON_DEVICE_STR; + int size = strlen(dev) + (sizeof(unsigned long)) + (sizeof(char) * 2); + + if ( (buf = (char *) malloc(size)) == NULL ) + return -ENOMEM; + memset(buf, 0, size); + + op.cmd = FLASK_DEL_OCONTEXT; + snprintf(buf, size, "%s %li", dev, device); + op.buf = buf; + op.size = size; + + if ( (err = xc_flask_op(xc_handle, &op)) != 0 ) + { + free(buf); + return err; + } + + free(buf); + return 0; + +} diff -r e39cec51aebc -r b6bbc0c9e651 tools/flask/libflask/include/flask.h --- a/tools/flask/libflask/include/flask.h Fri Nov 13 21:59:20 2009 +0000 +++ b/tools/flask/libflask/include/flask.h Fri Nov 13 22:00:19 2009 +0000 @@ -20,5 +20,24 @@ int flask_sid_to_context(int xc_handle, int flask_sid_to_context(int xc_handle, int sid, char *buf, uint32_t size); int flask_getenforce(int xc_handle); int flask_setenforce(int xc_handle, int mode); +int flask_add_pirq(int xc_handle, unsigned int pirq, char *scontext); +int flask_add_ioport(int xc_handle, unsigned long low, unsigned long high, + char *scontext); +int flask_add_iomem(int xc_handle, unsigned long low, unsigned long high, + char *scontext); +int flask_add_device(int xc_handle, unsigned long device, char *scontext); +int flask_del_pirq(int xc_handle, unsigned int pirq); +int flask_del_ioport(int xc_handle, unsigned long low, unsigned long high); +int flask_del_iomem(int xc_handle, unsigned long low, unsigned long high); +int flask_del_device(int xc_handle, unsigned long device); +#define flask_add_single_ioport(x, l, s) flask_add_ioport(x, l, l, s) +#define flask_add_single_iomem(x, l, s) flask_add_iomem(x, l, l, s) +#define flask_del_single_ioport(x, l) flask_del_ioport(x, l, l) +#define flask_del_single_iomem(x, l) flask_del_iomem(x, l, l); +#define OCON_PIRQ_STR "pirq" +#define OCON_IOPORT_STR "ioport" +#define OCON_IOMEM_STR "iomem" +#define OCON_DEVICE_STR "pcidevice" +#define INITCONTEXTLEN 256 #endif /* __FLASK_H__ */ diff -r e39cec51aebc -r b6bbc0c9e651 tools/flask/policy/policy/flask/access_vectors --- a/tools/flask/policy/policy/flask/access_vectors Fri Nov 13 21:59:20 2009 +0000 +++ b/tools/flask/policy/policy/flask/access_vectors Fri Nov 13 22:00:19 2009 +0000 @@ -163,4 +163,6 @@ class security setenforce setbool setsecparam + add_ocontext + del_ocontext } diff -r e39cec51aebc -r b6bbc0c9e651 tools/flask/policy/policy/modules/xen/xen.te --- a/tools/flask/policy/policy/modules/xen/xen.te Fri Nov 13 21:59:20 2009 +0000 +++ b/tools/flask/policy/policy/modules/xen/xen.te Fri Nov 13 22:00:19 2009 +0000 @@ -51,7 +51,7 @@ allow dom0_t xen_t:xen firmware; allow dom0_t security_t:security {compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce setbool -setsecparam}; +setsecparam add_ocontext del_ocontext}; create_channel(dom0_t, dom0_t, evchn0-0_t) allow dom0_t evchn0-0_t:event {send}; diff -r e39cec51aebc -r b6bbc0c9e651 xen/include/public/xsm/flask_op.h --- a/xen/include/public/xsm/flask_op.h Fri Nov 13 21:59:20 2009 +0000 +++ b/xen/include/public/xsm/flask_op.h Fri Nov 13 22:00:19 2009 +0000 @@ -31,8 +31,10 @@ #define FLASK_AVC_HASHSTATS 18 #define FLASK_AVC_CACHESTATS 19 #define FLASK_MEMBER 20 +#define FLASK_ADD_OCONTEXT 21 +#define FLASK_DEL_OCONTEXT 22 -#define FLASK_LAST FLASK_MEMBER +#define FLASK_LAST FLASK_DEL_OCONTEXT typedef struct flask_op { uint32_t cmd; diff -r e39cec51aebc -r b6bbc0c9e651 xen/xsm/flask/flask_op.c --- a/xen/xsm/flask/flask_op.c Fri Nov 13 21:59:20 2009 +0000 +++ b/xen/xsm/flask/flask_op.c Fri Nov 13 22:00:19 2009 +0000 @@ -45,7 +45,9 @@ integer_param("flask_enabled", flask_ena 1UL<<FLASK_COMMITBOOLS | \ 1UL<<FLASK_DISABLE | \ 1UL<<FLASK_SETAVC_THRESHOLD | \ - 1UL<<FLASK_MEMBER \ + 1UL<<FLASK_MEMBER | \ + 1UL<<FLASK_ADD_OCONTEXT | \ + 1UL<<FLASK_DEL_OCONTEXT \ ) #define FLASK_COPY_OUT \ @@ -752,6 +754,93 @@ out: return length; } +static int flask_ocontext_del(char *buf, uint32_t size) +{ + int len = 0; + char *ocontext; + unsigned long low = 0; + unsigned long high = 0; + + len = domain_has_security(current->domain, SECURITY__DEL_OCONTEXT); + if ( len ) + return len; + + if ( (ocontext = xmalloc_bytes(size) ) == NULL ) + return -ENOMEM; + + len = sscanf(buf, "%s %li %li", ocontext, &low, &high); + if ( len < 2 ) + { + len = -EINVAL; + goto out; + } + else if ( len == 2 ) + high = low; + + if ( low > high ) + { + len = -EINVAL; + goto out; + } + + len = security_ocontext_del(ocontext, low, high); + out: + xfree(ocontext); + return len; +} + +static int flask_ocontext_add(char *buf, uint32_t size) +{ + int len = 0; + u32 sid = 0; + unsigned long low = 0; + unsigned long high = 0; + char *scontext; + char *ocontext; + + len = domain_has_security(current->domain, SECURITY__ADD_OCONTEXT); + if ( len ) + return len; + + if ( (scontext = xmalloc_bytes(size) ) == NULL ) + return -ENOMEM; + + if ( (ocontext = xmalloc_bytes(size) ) == NULL ) + { + xfree(scontext); + return -ENOMEM; + } + + memset(scontext, 0, size); + memset(ocontext, 0, size); + + len = sscanf(buf, "%s %s %li %li", ocontext, scontext, &low, &high); + if ( len < 3 ) + { + len = -EINVAL; + goto out; + } + else if ( len == 3 ) + high = low; + + if ( low > high ) + { + len = -EINVAL; + goto out; + } + len = security_context_to_sid(scontext, strlen(scontext)+1, &sid); + if ( len < 0 ) + { + len = -EINVAL; + goto out; + } + len = security_ocontext_add(ocontext, low, high, sid); +out: + xfree(ocontext); + xfree(scontext); + return len; +} + long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op) { flask_op_t curop, *op = &curop; @@ -910,6 +999,18 @@ long do_flask_op(XEN_GUEST_HANDLE(xsm_op } break; + case FLASK_ADD_OCONTEXT: + { + length = flask_ocontext_add(arg, op->size); + break; + } + + case FLASK_DEL_OCONTEXT: + { + length = flask_ocontext_del(arg, op->size); + break; + } + default: length = -ENOSYS; break; diff -r e39cec51aebc -r b6bbc0c9e651 xen/xsm/flask/include/av_perm_to_string.h --- a/xen/xsm/flask/include/av_perm_to_string.h Fri Nov 13 21:59:20 2009 +0000 +++ b/xen/xsm/flask/include/av_perm_to_string.h Fri Nov 13 22:00:19 2009 +0000 @@ -110,3 +110,5 @@ S_(SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce") S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool") S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam") + S_(SECCLASS_SECURITY, SECURITY__ADD_OCONTEXT, "add_ocontext") + S_(SECCLASS_SECURITY, SECURITY__DEL_OCONTEXT, "del_ocontext") diff -r e39cec51aebc -r b6bbc0c9e651 xen/xsm/flask/include/av_permissions.h --- a/xen/xsm/flask/include/av_permissions.h Fri Nov 13 21:59:20 2009 +0000 +++ b/xen/xsm/flask/include/av_permissions.h Fri Nov 13 22:00:19 2009 +0000 @@ -118,4 +118,6 @@ #define SECURITY__SETENFORCE 0x00000080UL #define SECURITY__SETBOOL 0x00000100UL #define SECURITY__SETSECPARAM 0x00000200UL +#define SECURITY__ADD_OCONTEXT 0x00000400UL +#define SECURITY__DEL_OCONTEXT 0x00000800UL diff -r e39cec51aebc -r b6bbc0c9e651 xen/xsm/flask/include/security.h --- a/xen/xsm/flask/include/security.h Fri Nov 13 21:59:20 2009 +0000 +++ b/xen/xsm/flask/include/security.h Fri Nov 13 22:00:19 2009 +0000 @@ -82,4 +82,8 @@ int security_validate_transition(u32 old int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, u16 tclass); +int security_ocontext_add(char *ocontext, unsigned long low, + unsigned long high, u32 sid); + +int security_ocontext_del(char *ocontext, unsigned int low, unsigned int high); #endif /* _FLASK_SECURITY_H_ */ diff -r e39cec51aebc -r b6bbc0c9e651 xen/xsm/flask/ss/services.c --- a/xen/xsm/flask/ss/services.c Fri Nov 13 21:59:20 2009 +0000 +++ b/xen/xsm/flask/ss/services.c Fri Nov 13 22:00:19 2009 +0000 @@ -1942,3 +1942,277 @@ out: xfree(bvalues); return rc; } + +int determine_ocontext( char *ocontext ) +{ + if ( strcmp(ocontext, "pirq") == 0 ) + return OCON_PIRQ; + else if ( strcmp(ocontext, "ioport") == 0 ) + return OCON_IOPORT; + else if ( strcmp(ocontext, "iomem") == 0 ) + return OCON_IOMEM; + else if ( strcmp(ocontext, "pcidevice") == 0 ) + return OCON_DEVICE; + else + return -1; +} + +int security_ocontext_add( char *ocontext, unsigned long low, unsigned long high + ,u32 sid ) +{ + int ret = 0; + int ocon = 0; + struct ocontext *c; + struct ocontext *add; + + if ( (ocon = determine_ocontext(ocontext)) < 0 ) + return -EINVAL; + if ( (add = xmalloc(struct ocontext)) == NULL ) + return -ENOMEM; + memset(add, 0, sizeof(struct ocontext)); + add->sid[0] = sid; + + POLICY_WRLOCK; + switch( ocon ) + { + case OCON_PIRQ: + add->u.pirq = (u16)low; + if ( high != low ) + { + ret = -EINVAL; + break; + } + + c = policydb.ocontexts[OCON_PIRQ]; + while ( c ) + { + if ( c->u.pirq == add->u.pirq ) + { + printk("%s: Duplicate pirq %d\n", __FUNCTION__, add->u.pirq); + ret = -EINVAL; + break; + } + c = c->next; + } + + if ( ret == 0 ) + { + add->next = policydb.ocontexts[OCON_PIRQ]; + policydb.ocontexts[OCON_PIRQ] = add; + } + break; + + case OCON_IOPORT: + add->u.ioport.low_ioport = low; + add->u.ioport.high_ioport = high; + + 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; + } + c = c->next; + } + + if ( ret == 0 ) + { + add->next = policydb.ocontexts[OCON_IOPORT]; + policydb.ocontexts[OCON_IOPORT] = add; + } + break; + + case OCON_IOMEM: + add->u.iomem.low_iomem = low; + add->u.iomem.high_iomem = high; + + 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; + } + c = c->next; + } + + if ( ret == 0 ) + { + add->next = policydb.ocontexts[OCON_IOMEM]; + policydb.ocontexts[OCON_IOMEM] = add; + } + break; + + case OCON_DEVICE: + add->u.device = low; + if ( high != low ) + { + ret = -EINVAL; + break; + } + + c = policydb.ocontexts[OCON_DEVICE]; + while ( c ) + { + if ( c->u.device == add->u.device ) + { + printk("%s: Duplicate PCI Device 0x%x\n", __FUNCTION__, + add->u.device); + ret = -EINVAL; + break; + } + c = c->next; + } + + if ( ret == 0 ) + { + add->next = policydb.ocontexts[OCON_DEVICE]; + policydb.ocontexts[OCON_DEVICE] = add; + } + break; + + default: + ret = -EINVAL; + } + POLICY_WRUNLOCK; + + if ( ret != 0 ) + xfree(add); + return ret; +} + +int security_ocontext_del( char *ocontext, unsigned int low, unsigned int high ) +{ + int ret = 0; + int ocon = 0; + struct ocontext *c, *before_c; + + if ( (ocon = determine_ocontext(ocontext)) < 0 ) + return -EINVAL; + + POLICY_WRLOCK; + switch( ocon ) + { + case OCON_PIRQ: + for ( before_c = NULL, c = policydb.ocontexts[OCON_PIRQ]; + c; before_c = c, c = c->next ) + { + if ( c->u.pirq == low ) + { + if ( before_c == NULL ) + { + policydb.ocontexts[OCON_PIRQ] = c->next; + xfree(c); + goto out; + } + else + { + before_c->next = c->next; + xfree(c); + goto out; + } + } + } + + printk("%s: ocontext not found: pirq %d\n", __FUNCTION__, low); + ret = -EINVAL; + break; + + case OCON_IOPORT: + for ( before_c = NULL, c = policydb.ocontexts[OCON_IOPORT]; + c; before_c = c, c = c->next ) + { + if ( c->u.ioport.low_ioport == low && + c->u.ioport.high_ioport == high ) + { + if ( before_c == NULL ) + { + policydb.ocontexts[OCON_IOPORT] = c->next; + xfree(c); + goto out; + } + else + { + before_c->next = c->next; + xfree(c); + goto out; + } + } + } + + printk("%s: ocontext not found: ioport 0x%x - 0x%x\n", __FUNCTION__, + low, high); + ret = -EINVAL; + break; + + case OCON_IOMEM: + for ( before_c = NULL, c = policydb.ocontexts[OCON_IOMEM]; + c; before_c = c, c = c->next ) + { + if ( c->u.iomem.low_iomem == low && + c->u.iomem.high_iomem == high ) + { + if ( before_c == NULL ) + { + policydb.ocontexts[OCON_IOMEM] = c->next; + xfree(c); + goto out; + } + else + { + before_c->next = c->next; + xfree(c); + goto out; + } + } + } + + printk("%s: ocontext not found: iomem 0x%x - 0x%x\n", __FUNCTION__, + low, high); + ret = -EINVAL; + break; + + case OCON_DEVICE: + for ( before_c = NULL, c = policydb.ocontexts[OCON_DEVICE]; + c; before_c = c, c = c->next ) + { + if ( c->u.device == low ) + { + if ( before_c == NULL ) + { + policydb.ocontexts[OCON_DEVICE] = c->next; + xfree(c); + goto out; + } + else + { + before_c->next = c->next; + xfree(c); + goto out; + } + } + } + + printk("%s: ocontext not found: pcidevice 0x%x\n", __FUNCTION__, low); + ret = -EINVAL; + break; + + default: + ret = -EINVAL; + } + + out: + POLICY_WRUNLOCK; + return ret; +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |