[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [ACM] Support for running unlabeled domains alongside labeled ones
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1186391434 -3600 # Node ID 6384e168f12268ce38ac1e805c8b99790d6a012d # Parent 0120cca784356fce28d69565f054f8f875ada2c8 [ACM] Support for running unlabeled domains alongside labeled ones Add support for running unlabeled domains alongside labeled ones, if the policy contains a VM label with name '__UNLABELED__' and an STE type with the same name. The ezpolicy tool has been modified to automatically suggest a policy under which unlabeled domains can run. The user may delete this, if this is not desired. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx> --- tools/python/xen/util/acmpolicy.py | 32 +++- tools/python/xen/util/security.py | 8 - tools/python/xen/xend/XendDomainInfo.py | 2 tools/python/xen/xend/server/blkif.py | 27 ++- tools/python/xen/xm/main.py | 3 tools/security/xensec_ezpolicy | 7 xen/acm/acm_chinesewall_hooks.c | 199 +++++++++++++++------------- xen/acm/acm_simple_type_enforcement_hooks.c | 2 8 files changed, 165 insertions(+), 115 deletions(-) diff -r 0120cca78435 -r 6384e168f122 tools/python/xen/util/acmpolicy.py --- a/tools/python/xen/util/acmpolicy.py Fri Aug 03 12:23:03 2007 +0100 +++ b/tools/python/xen/util/acmpolicy.py Mon Aug 06 10:10:34 2007 +0100 @@ -46,6 +46,9 @@ ACM_POLICY_UNDEFINED = 15 ACM_SCHEMA_FILE = "/etc/xen/acm-security/policies/security_policy.xsd" + +ACM_LABEL_UNLABELED = "__UNLABELED__" +ACM_LABEL_UNLABELED_DISPLAY = "unlabeled" class ACMPolicy(XSPolicy): """ @@ -925,11 +928,13 @@ class ACMPolicy(XSPolicy): return -xsconstants.XSERR_POLICY_INCONSISTENT, "", "" vms_with_chws = [] - chws_by_vm = {} + chws_by_vm = { ACM_LABEL_UNLABELED : [] } for v in vms: if v.has_key("chws"): vms_with_chws.append(v["name"]) chws_by_vm[v["name"]] = v["chws"] + + if bootstrap in vms_with_chws: vms_with_chws.remove(bootstrap) vms_with_chws.sort() @@ -937,18 +942,25 @@ class ACMPolicy(XSPolicy): else: vms_with_chws.sort() + if ACM_LABEL_UNLABELED in vms_with_chws: + vms_with_chws.remove(ACM_LABEL_UNLABELED) ; # @1 + vms_with_stes = [] - stes_by_vm = {} + stes_by_vm = { ACM_LABEL_UNLABELED : [] } for v in vms: if v.has_key("stes"): vms_with_stes.append(v["name"]) stes_by_vm[v["name"]] = v["stes"] + if bootstrap in vms_with_stes: vms_with_stes.remove(bootstrap) vms_with_stes.sort() vms_with_stes.insert(0, bootstrap) else: vms_with_stes.sort() + + if ACM_LABEL_UNLABELED in vms_with_stes: + vms_with_stes.remove(ACM_LABEL_UNLABELED) ; # @2 resnames = self.policy_get_resourcelabel_names() resnames.sort() @@ -957,6 +969,9 @@ class ACMPolicy(XSPolicy): for r in res: if r.has_key("stes"): stes_by_res[r["name"]] = r["stes"] + + if ACM_LABEL_UNLABELED in resnames: + resnames.remove(ACM_LABEL_UNLABELED) max_chw_ssids = 1 + len(vms_with_chws) max_chw_types = 1 + len(vms_with_chws) @@ -1083,6 +1098,8 @@ class ACMPolicy(XSPolicy): pr_bin += "\x00" # Build chinese wall part + vms_with_chws.insert(0, ACM_LABEL_UNLABELED) + cfses_names = self.policy_get_chwall_cfses_names_sorted() cfses = self.policy_get_chwall_cfses() @@ -1105,9 +1122,7 @@ class ACMPolicy(XSPolicy): chw_running_types_offset, chw_conf_agg_offset) chw_bin_body = "" - # simulate __NULL_LABEL__ - for c in chws: - chw_bin_body += struct.pack("!h",0) + # VMs that are listed and their chinese walls for v in vms_with_chws: for c in chws: @@ -1143,6 +1158,8 @@ class ACMPolicy(XSPolicy): chw_bin += "\x00" # Build STE part + vms_with_stes.insert(0, ACM_LABEL_UNLABELED) # Took out in @2 + steformat="!iiiii" ste_bin = struct.pack(steformat, ACM_STE_VERSION, @@ -1152,10 +1169,7 @@ class ACMPolicy(XSPolicy): struct.calcsize(steformat)) ste_bin_body = "" if stes: - # Simulate __NULL_LABEL__ - for s in stes: - ste_bin_body += struct.pack("!h",0) - # VMs that are listed and their chinese walls + # VMs that are listed and their STE types for v in vms_with_stes: unknown_ste |= (set(stes_by_vm[v]) - set(stes)) for s in stes: diff -r 0120cca78435 -r 6384e168f122 tools/python/xen/util/security.py --- a/tools/python/xen/util/security.py Fri Aug 03 12:23:03 2007 +0100 +++ b/tools/python/xen/util/security.py Mon Aug 06 10:10:34 2007 +0100 @@ -155,7 +155,7 @@ def calc_dom_ssidref_from_info(info): ssidref = label2ssidref(vmlabel, policyname, "dom") return ssidref else: - return 0 + return 0x0 raise VmError("security.calc_dom_ssidref_from_info: info of type '%s'" "not supported." % type(info)) @@ -231,6 +231,10 @@ def ssidref2label(ssidref_var): ssidref = ssidref_var else: err("Instance type of ssidref not supported (must be of type 'str' or 'int')") + + if ssidref == 0: + from xen.util.acmpolicy import ACM_LABEL_UNLABELED + return ACM_LABEL_UNLABELED try: mapfile_lock() @@ -867,7 +871,7 @@ def get_domain_resources(dominfo): resources[typ].append("%s:%s:%s" % (xsconstants.ACM_POLICY_ID, active_policy, - "unlabeled")) + ACM_LABEL_UNLABELED)) return resources diff -r 0120cca78435 -r 6384e168f122 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Aug 03 12:23:03 2007 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Mon Aug 06 10:10:34 2007 +0100 @@ -1463,8 +1463,6 @@ class XendDomainInfo: ssidref = 0 if security.on(): ssidref = security.calc_dom_ssidref_from_info(self.info) - if ssidref == 0: - raise VmError('VM is not properly labeled.') if security.has_authorization(ssidref) == False: raise VmError("VM is not authorized to run.") diff -r 0120cca78435 -r 6384e168f122 tools/python/xen/xend/server/blkif.py --- a/tools/python/xen/xend/server/blkif.py Fri Aug 03 12:23:03 2007 +0100 +++ b/tools/python/xen/xend/server/blkif.py Mon Aug 06 10:10:34 2007 +0100 @@ -73,17 +73,7 @@ class BlkifController(DevController): back['uuid'] = uuid if security.on(): - (label, ssidref, policy) = \ - security.get_res_security_details(uname) - domain_label = self.vm.get_security_label() - if domain_label: - rc = security.res_security_check_xapi(label, ssidref, policy, - domain_label) - if rc == 0: - raise VmError("VM's access to block device '%s' denied." % - uname) - else: - raise VmError("VM must have a security label.") + self.do_access_control(config, uname) devid = blkif.blkdev_name_to_number(dev) if devid is None: @@ -95,6 +85,21 @@ class BlkifController(DevController): return (devid, back, front) + def do_access_control(self, config, uname): + (label, ssidref, policy) = \ + security.get_res_security_details(uname) + domain_label = self.vm.get_security_label() + if domain_label: + rc = security.res_security_check_xapi(label, ssidref, policy, + domain_label) + if rc == 0: + raise VmError("VM's access to block device '%s' denied" % + uname) + else: + from xen.util.acmpolicy import ACM_LABEL_UNLABELED + if label != ACM_LABEL_UNLABELED: + raise VmError("VM must have a security label to access " + "block device '%s'" % uname) def reconfigureDevice(self, _, config): """@see DevController.reconfigureDevice""" diff -r 0120cca78435 -r 6384e168f122 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Fri Aug 03 12:23:03 2007 +0100 +++ b/tools/python/xen/xm/main.py Mon Aug 06 10:10:34 2007 +0100 @@ -51,6 +51,7 @@ from xen.xm import console from xen.xm import console from xen.util.xmlrpcclient import ServerProxy from xen.util.security import ACMError +from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY import XenAPI @@ -947,7 +948,7 @@ def xm_label_list(doms): d = parse_doms_info(dom) if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']: if not d['seclabel']: - d['seclabel'] = 'ERROR' + d['seclabel'] = ACM_LABEL_UNLABELED_DISPLAY elif security.active_policy in ['DEFAULT']: d['seclabel'] = 'DEFAULT' else: diff -r 0120cca78435 -r 6384e168f122 tools/security/xensec_ezpolicy --- a/tools/security/xensec_ezpolicy Fri Aug 03 12:23:03 2007 +0100 +++ b/tools/security/xensec_ezpolicy Mon Aug 06 10:10:34 2007 +0100 @@ -35,6 +35,8 @@ conflict_bmp = None conflict_bmp = None realm_icon = None workload_icon = None + +ACM_LABEL_UNLABELED = '__UNLABELED__' class orgTreeCtrl(wx.TreeCtrl): @@ -870,7 +872,8 @@ class ezFrame(wx.Frame): self.realm_menu.Enable(self.ID_ORGDEL, True) self.realm_menu.Enable(self.ID_ORGEDT, True) self.realm_menu.Enable(self.ID_ORGADD, True) - if len(self.orgs.GetSelections()) > 1: + if len(self.orgs.GetSelections()) > 1 or \ + ACM_LABEL_UNLABELED == self.orgs.GetItemText(item): self.realm_menu.Enable(self.ID_ORGEDT, False) self.realm_menu.Enable(self.ID_ORGADD, False) self.PopupMenu(self.realm_menu) @@ -1622,6 +1625,8 @@ def main(): app = ezApp(0) if len(sys.argv) in [2]: app.Load(sys.argv[1]) + else: + dict2org({'orgs' : [[ACM_LABEL_UNLABELED,[]]], 'cons': []}) app.MainLoop() print "Goodbye" diff -r 0120cca78435 -r 6384e168f122 xen/acm/acm_chinesewall_hooks.c --- a/xen/acm/acm_chinesewall_hooks.c Fri Aug 03 12:23:03 2007 +0100 +++ b/xen/acm/acm_chinesewall_hooks.c Mon Aug 06 10:10:34 2007 +0100 @@ -93,6 +93,7 @@ int acm_init_chwall_policy(void) return ACM_OK; } + static int chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref) { struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid); @@ -104,10 +105,10 @@ static int chwall_init_domain_ssid(void chwall_ssidp->chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); - if ( (chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs) - || (chwall_ssidp->chwall_ssidref == ACM_DEFAULT_LOCAL_SSID) ) - { - printkd("%s: ERROR chwall_ssidref(%x) undefined (>max) or unset (0).\n", + if ( chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs ) + { + printkd("%s: ERROR chwall_ssidref(%x) undefined (>max) or unset " + "(0).\n", __func__, chwall_ssidp->chwall_ssidref); xfree(chwall_ssidp); return ACM_INIT_SSID_ERROR; @@ -117,6 +118,7 @@ static int chwall_init_domain_ssid(void __func__, chwall_ssidp->chwall_ssidref); return ACM_OK; } + static void chwall_free_domain_ssid(void *chwall_ssid) { @@ -205,7 +207,9 @@ chwall_init_state(struct acm_chwall_poli read_lock(&ssid_list_rwlock); - /* go through all domains and adjust policy as if this domain was started now */ + /* go through all domains and adjust policy as if this domain was + * started now + */ for_each_acmssid( rawssid ) { chwall_ssid = @@ -220,8 +224,8 @@ chwall_init_state(struct acm_chwall_poli /* b) check for conflict */ for ( i = 0; i < chwall_buf->chwall_max_types; i++ ) - if (conflict_aggregate_set[i] && - ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i]) + if ( conflict_aggregate_set[i] && + ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i] ) { printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i); @@ -231,37 +235,46 @@ chwall_init_state(struct acm_chwall_poli goto out; } + /* set violation and break out of the loop */ - /* c) adapt conflict aggregate set for this domain (notice conflicts) */ + /* c) adapt conflict aggregate set for this domain + * (notice conflicts) + */ for ( i = 0; i < chwall_buf->chwall_max_conflictsets; i++ ) { int common = 0; /* check if conflict_set_i and ssidref have common types */ for ( j = 0; j < chwall_buf->chwall_max_types; j++ ) - if (conflict_sets[i * chwall_buf->chwall_max_types + j] && - ssidrefs[chwall_ssidref * - chwall_buf->chwall_max_types + j]) + if ( conflict_sets[i * chwall_buf->chwall_max_types + j] && + ssidrefs[chwall_ssidref * + chwall_buf->chwall_max_types + j] ) { common = 1; break; } - if (common == 0) + + if ( common == 0 ) continue; /* try next conflict set */ - /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ + + /* now add types of the conflict set to conflict_aggregate_set + * (except types in chwall_ssidref) + */ for ( j = 0; j < chwall_buf->chwall_max_types; j++ ) - if (conflict_sets[i * chwall_buf->chwall_max_types + j] && - !ssidrefs[chwall_ssidref * - chwall_buf->chwall_max_types + j]) + if ( conflict_sets[i * chwall_buf->chwall_max_types + j] && + !ssidrefs[chwall_ssidref * + chwall_buf->chwall_max_types + j] ) conflict_aggregate_set[j]++; } } out: read_unlock(&ssid_list_rwlock); return violation; - /* returning "violation != 0" means that the currently running set of domains would - * not be possible if the new policy had been enforced before starting them; for chinese - * wall, this means that the new policy includes at least one conflict set of which - * more than one type is currently running */ + /* returning "violation != 0" means that the currently running set of + * domains would not be possible if the new policy had been enforced + * before starting them; for chinese wall, this means that the new + * policy includes at least one conflict set of which more than one + * type is currently running + */ } @@ -348,8 +361,10 @@ static int _chwall_update_policy(u8 *buf memset(conflict_aggregate_set, 0, sizeof(domaintype_t) * chwall_buf->chwall_max_types); - /* 3. now re-calculate the state for the new policy based on running domains; - * this can fail if new policy is conflicting with running domains */ + /* 3. now re-calculate the state for the new policy based on + * running domains; this can fail if new policy is conflicting + * with running domains + */ if ( chwall_init_state(chwall_buf, ssids, conflict_sets, running_types, conflict_aggregate_set, @@ -483,81 +498,27 @@ static int _chwall_pre_domain_create(voi chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); - if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID) - { - printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n", - __func__); - return ACM_ACCESS_DENIED; /* catching and indicating config error */ - } - - if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs) + if ( chwall_ssidref >= chwall_bin_pol.max_ssidrefs ) { printk("%s: ERROR chwall_ssidref > max(%x).\n", __func__, chwall_bin_pol.max_ssidrefs - 1); return ACM_ACCESS_DENIED; } + /* A: chinese wall check for conflicts */ - for (i = 0; i < chwall_bin_pol.max_types; i++) - if (chwall_bin_pol.conflict_aggregate_set[i] && - chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + i]) + for ( i = 0; i < chwall_bin_pol.max_types; i++ ) + if ( chwall_bin_pol.conflict_aggregate_set[i] && + chwall_bin_pol.ssidrefs[chwall_ssidref * + chwall_bin_pol.max_types + i] ) { printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i); return ACM_ACCESS_DENIED; } /* B: chinese wall conflict set adjustment (so that other - * other domains simultaneously created are evaluated against this new set)*/ - for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ ) - { - int common = 0; - /* check if conflict_set_i and ssidref have common types */ - for ( j = 0; j < chwall_bin_pol.max_types; j++ ) - if ( chwall_bin_pol. - conflict_sets[i * chwall_bin_pol.max_types + j] - && chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + j] ) - { - common = 1; - break; - } - if (common == 0) - continue; /* try next conflict set */ - /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ - for ( j = 0; j < chwall_bin_pol.max_types; j++ ) - if ( chwall_bin_pol. - conflict_sets[i * chwall_bin_pol.max_types + j] - && !chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + j]) - chwall_bin_pol.conflict_aggregate_set[j]++; - } - return ACM_ACCESS_PERMITTED; -} - - -static void _chwall_post_domain_create(domid_t domid, ssidref_t ssidref) -{ - int i, j; - ssidref_t chwall_ssidref; - - chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); - /* adjust types ref-count for running domains */ - for ( i = 0; i < chwall_bin_pol.max_types; i++ ) - chwall_bin_pol.running_types[i] += - chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + i]; - if ( domid ) - return; - - /* Xen does not call pre-create hook for DOM0; - * to consider type conflicts of any domain with DOM0, we need - * to adjust the conflict_aggregate for DOM0 here the same way it - * is done for non-DOM0 domains in the pre-hook */ - printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n", - __func__, ssidref, chwall_ssidref); - - /* chinese wall conflict set adjustment (so that other - * other domains simultaneously created are evaluated against this new set)*/ + * other domains simultaneously created are evaluated against + * this new set) + */ for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ ) { int common = 0; @@ -578,6 +539,62 @@ static void _chwall_post_domain_create(d if ( chwall_bin_pol. conflict_sets[i * chwall_bin_pol.max_types + j] && !chwall_bin_pol.ssidrefs[chwall_ssidref * + chwall_bin_pol.max_types + j]) + chwall_bin_pol.conflict_aggregate_set[j]++; + } + return ACM_ACCESS_PERMITTED; +} + + +static void _chwall_post_domain_create(domid_t domid, ssidref_t ssidref) +{ + int i, j; + ssidref_t chwall_ssidref; + + chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); + /* adjust types ref-count for running domains */ + for ( i = 0; i < chwall_bin_pol.max_types; i++ ) + chwall_bin_pol.running_types[i] += + chwall_bin_pol.ssidrefs[chwall_ssidref * + chwall_bin_pol.max_types + i]; + if ( domid ) + return; + + /* Xen does not call pre-create hook for DOM0; + * to consider type conflicts of any domain with DOM0, we need + * to adjust the conflict_aggregate for DOM0 here the same way it + * is done for non-DOM0 domains in the pre-hook */ + printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n", + __func__, ssidref, chwall_ssidref); + + /* chinese wall conflict set adjustment (so that other + * other domains simultaneously created are evaluated against this new set)*/ + for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ ) + { + int common = 0; + /* check if conflict_set_i and ssidref have common types */ + for ( j = 0; j < chwall_bin_pol.max_types; j++ ) + if ( chwall_bin_pol. + conflict_sets[i * chwall_bin_pol.max_types + j] + && chwall_bin_pol.ssidrefs[chwall_ssidref * + chwall_bin_pol.max_types + j] ) + { + common = 1; + break; + } + + if ( common == 0 ) + { + /* try next conflict set */ + continue; + } + + /* now add types of the conflict set to conflict_aggregate_set + (except types in chwall_ssidref) */ + for ( j = 0; j < chwall_bin_pol.max_types; j++ ) + if ( chwall_bin_pol. + conflict_sets[i * chwall_bin_pol.max_types + j] + && !chwall_bin_pol.ssidrefs[chwall_ssidref * chwall_bin_pol.max_types + j] ) chwall_bin_pol.conflict_aggregate_set[j]++; } @@ -638,9 +655,15 @@ static void chwall_domain_destroy(void * common = 1; break; } - if (common == 0) - continue; /* try next conflict set, this one does not include any type of chwall_ssidref */ - /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ + if ( common == 0 ) + { + /* try next conflict set, this one does not include + any type of chwall_ssidref */ + continue; + } + + /* now add types of the conflict set to conflict_aggregate_set + (except types in chwall_ssidref) */ for ( j = 0; j < chwall_bin_pol.max_types; j++ ) if ( chwall_bin_pol. conflict_sets[i * chwall_bin_pol.max_types + j] diff -r 0120cca78435 -r 6384e168f122 xen/acm/acm_simple_type_enforcement_hooks.c --- a/xen/acm/acm_simple_type_enforcement_hooks.c Fri Aug 03 12:23:03 2007 +0100 +++ b/xen/acm/acm_simple_type_enforcement_hooks.c Mon Aug 06 10:10:34 2007 +0100 @@ -408,7 +408,7 @@ _ste_update_policy(u8 *buf, u32 buf_size ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs; ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf; - if ( ste_init_state(NULL) ) + if ( ste_init_state(errors) ) { /* new policy conflicts with sharing of running domains */ printk("%s: New policy conflicts with running domains. " _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |