diff -r 49deb113cd40 tools/flask/libflask/flask_op.c --- a/tools/flask/libflask/flask_op.c Fri Nov 13 15:46:58 2009 +0000 +++ b/tools/flask/libflask/flask_op.c Fri Nov 13 13:27:18 2009 -0500 @@ -109,3 +109,236 @@ 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 49deb113cd40 tools/flask/libflask/include/flask.h --- a/tools/flask/libflask/include/flask.h Fri Nov 13 15:46:58 2009 +0000 +++ b/tools/flask/libflask/include/flask.h Fri Nov 13 13:27:18 2009 -0500 @@ -20,5 +20,24 @@ 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 49deb113cd40 tools/flask/policy/policy/flask/access_vectors --- a/tools/flask/policy/policy/flask/access_vectors Fri Nov 13 15:46:58 2009 +0000 +++ b/tools/flask/policy/policy/flask/access_vectors Fri Nov 13 13:27:18 2009 -0500 @@ -163,4 +163,6 @@ setenforce setbool setsecparam + add_ocontext + del_ocontext } diff -r 49deb113cd40 tools/flask/policy/policy/modules/xen/xen.te --- a/tools/flask/policy/policy/modules/xen/xen.te Fri Nov 13 15:46:58 2009 +0000 +++ b/tools/flask/policy/policy/modules/xen/xen.te Fri Nov 13 13:27:18 2009 -0500 @@ -51,7 +51,7 @@ 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 49deb113cd40 xen/include/public/xsm/flask_op.h --- a/xen/include/public/xsm/flask_op.h Fri Nov 13 15:46:58 2009 +0000 +++ b/xen/include/public/xsm/flask_op.h Fri Nov 13 13:27:18 2009 -0500 @@ -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 49deb113cd40 xen/xsm/flask/flask_op.c --- a/xen/xsm/flask/flask_op.c Fri Nov 13 15:46:58 2009 +0000 +++ b/xen/xsm/flask/flask_op.c Fri Nov 13 13:27:18 2009 -0500 @@ -45,7 +45,9 @@ 1UL<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 @@ } 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 49deb113cd40 xen/xsm/flask/include/av_perm_to_string.h --- a/xen/xsm/flask/include/av_perm_to_string.h Fri Nov 13 15:46:58 2009 +0000 +++ b/xen/xsm/flask/include/av_perm_to_string.h Fri Nov 13 13:27:18 2009 -0500 @@ -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 49deb113cd40 xen/xsm/flask/include/av_permissions.h --- a/xen/xsm/flask/include/av_permissions.h Fri Nov 13 15:46:58 2009 +0000 +++ b/xen/xsm/flask/include/av_permissions.h Fri Nov 13 13:27:18 2009 -0500 @@ -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 49deb113cd40 xen/xsm/flask/include/security.h --- a/xen/xsm/flask/include/security.h Fri Nov 13 15:46:58 2009 +0000 +++ b/xen/xsm/flask/include/security.h Fri Nov 13 13:27:18 2009 -0500 @@ -82,4 +82,8 @@ 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 49deb113cd40 xen/xsm/flask/ss/services.c --- a/xen/xsm/flask/ss/services.c Fri Nov 13 15:46:58 2009 +0000 +++ b/xen/xsm/flask/ss/services.c Fri Nov 13 13:27:18 2009 -0500 @@ -1942,3 +1942,277 @@ 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; +}