[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [ACM] Check a domain's authorization to run.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1185523275 -3600 # Node ID bf512fde6667f213dc5e32239fd567e2b5a6ef37 # Parent 07655ed2fe58ebf883b8a4b5c2dccf15576f4778 [ACM] Check a domain's authorization to run. A domain is only authorized to run if it has a superset of Simple Type Enforcement Types in its VM label compared to that of Domain-0, which itself may not have all STEs available in a policy. This patch adds a check for this into Xend and the necessary code support into Xen. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx> --- tools/python/xen/lowlevel/acm/acm.c | 9 ++-- tools/python/xen/util/security.py | 22 +++++++++- tools/python/xen/xend/XendDomainInfo.py | 10 +++- xen/acm/acm_chinesewall_hooks.c | 1 xen/acm/acm_core.c | 29 ------------- xen/acm/acm_policy.c | 4 + xen/acm/acm_simple_type_enforcement_hooks.c | 38 ++++++++++++++++- xen/include/acm/acm_core.h | 3 - xen/include/acm/acm_hooks.h | 60 +++++++++++++++++++++------- xen/include/public/acm.h | 5 +- 10 files changed, 125 insertions(+), 56 deletions(-) diff -r 07655ed2fe58 -r bf512fde6667 tools/python/xen/lowlevel/acm/acm.c --- a/tools/python/xen/lowlevel/acm/acm.c Thu Jul 26 12:00:32 2007 +0100 +++ b/tools/python/xen/lowlevel/acm/acm.c Fri Jul 27 09:01:15 2007 +0100 @@ -148,9 +148,10 @@ static PyObject *getdecision(PyObject * char *arg1_name, *arg1, *arg2_name, *arg2, *decision = NULL; struct acm_getdecision getdecision; int xc_handle, rc; - - if (!PyArg_ParseTuple(args, "ssss", &arg1_name, - &arg1, &arg2_name, &arg2)) { + uint32_t hooktype; + + if (!PyArg_ParseTuple(args, "ssssi", &arg1_name, + &arg1, &arg2_name, &arg2, &hooktype)) { return NULL; } @@ -163,7 +164,7 @@ static PyObject *getdecision(PyObject * (strcmp(arg2_name, "domid") && strcmp(arg2_name, "ssidref"))) return NULL; - getdecision.hook = ACMHOOK_sharing; + getdecision.hook = hooktype; if (!strcmp(arg1_name, "domid")) { getdecision.get_decision_by1 = ACM_GETBY_domainid; getdecision.id1.domainid = atoi(arg1); diff -r 07655ed2fe58 -r bf512fde6667 tools/python/xen/util/security.py --- a/tools/python/xen/util/security.py Thu Jul 26 12:00:32 2007 +0100 +++ b/tools/python/xen/util/security.py Fri Jul 27 09:01:15 2007 +0100 @@ -61,6 +61,10 @@ empty_line_re = re.compile("^\s*$") empty_line_re = re.compile("^\s*$") binary_name_re = re.compile(".*[chwall|ste|chwall_ste].*\.bin", re.IGNORECASE) policy_name_re = re.compile(".*[chwall|ste|chwall_ste].*", re.IGNORECASE) + +#decision hooks known to the hypervisor +ACMHOOK_sharing = 1 +ACMHOOK_authorization = 2 #other global variables NULL_SSIDREF = 0 @@ -453,7 +457,8 @@ def get_decision(arg1, arg2): err("Invalid id or ssidref type, string or int required") try: - decision = acm.getdecision(arg1[0], arg1[1], arg2[0], arg2[1]) + decision = acm.getdecision(arg1[0], arg1[1], arg2[0], arg2[1], + ACMHOOK_sharing) except: err("Cannot determine decision.") @@ -461,6 +466,21 @@ def get_decision(arg1, arg2): return decision else: err("Cannot determine decision (Invalid parameter).") + + +def has_authorization(ssidref): + """ Check if the domain with the given ssidref has authorization to + run on this system. To have authoriztion dom0's STE types must + be a superset of that of the domain's given through its ssidref. + """ + rc = True + dom0_ssidref = int(acm.getssid(0)['ssidref']) + decision = acm.getdecision('ssidref', str(dom0_ssidref), + 'ssidref', str(ssidref), + ACMHOOK_authorization) + if decision == "DENIED": + rc = False + return rc def hv_chg_policy(bin_pol, del_array, chg_array): diff -r 07655ed2fe58 -r bf512fde6667 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Thu Jul 26 12:00:32 2007 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Jul 27 09:01:15 2007 +0100 @@ -1460,9 +1460,13 @@ class XendDomainInfo: # allocation of 1MB. We free up 2MB here to be on the safe side. balloon.free(2*1024) # 2MB should be plenty - ssidref = security.calc_dom_ssidref_from_info(self.info) - if ssidref == 0 and security.on(): - raise VmError('VM is not properly labeled.') + 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.") try: self.domid = xc.domain_create( diff -r 07655ed2fe58 -r bf512fde6667 xen/acm/acm_chinesewall_hooks.c --- a/xen/acm/acm_chinesewall_hooks.c Thu Jul 26 12:00:32 2007 +0100 +++ b/xen/acm/acm_chinesewall_hooks.c Fri Jul 27 09:01:15 2007 +0100 @@ -685,6 +685,7 @@ struct acm_operations acm_chinesewall_op .fail_grant_setup = NULL, /* generic domain-requested decision hooks */ .sharing = NULL, + .authorization = NULL, .is_default_policy = chwall_is_default_policy, }; diff -r 07655ed2fe58 -r bf512fde6667 xen/acm/acm_core.c --- a/xen/acm/acm_core.c Thu Jul 26 12:00:32 2007 +0100 +++ b/xen/acm/acm_core.c Fri Jul 27 09:01:15 2007 +0100 @@ -314,26 +314,7 @@ acm_init(char *policy_start, return ret; } -int -acm_init_domain_ssid(domid_t id, ssidref_t ssidref) -{ - struct domain *subj = rcu_lock_domain_by_id(id); - int ret; - - if (subj == NULL) - { - printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id); - return ACM_NULL_POINTER_ERROR; - } - - ret = acm_init_domain_ssid_new(subj, ssidref); - - rcu_unlock_domain(subj); - - return ret; -} - -int acm_init_domain_ssid_new(struct domain *subj, ssidref_t ssidref) +int acm_init_domain_ssid(struct domain *subj, ssidref_t ssidref) { struct acm_ssid_domain *ssid; int ret1, ret2; @@ -373,10 +354,6 @@ int acm_init_domain_ssid_new(struct doma acm_free_domain_ssid(ssid); return ACM_INIT_SSID_ERROR; } - - write_lock(&ssid_list_rwlock); - list_add(&ssid->node, &ssid_list); - write_unlock(&ssid_list_rwlock); printkd("%s: assigned domain %x the ssidref=%x.\n", __func__, subj->domain_id, ssid->ssidref); @@ -398,10 +375,6 @@ acm_free_domain_ssid(struct acm_ssid_dom if (acm_secondary_ops->free_domain_ssid != NULL) acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid); ssid->secondary_ssid = NULL; - - write_lock(&ssid_list_rwlock); - list_del(&ssid->node); - write_unlock(&ssid_list_rwlock); xfree(ssid); printkd("%s: Freed individual domain ssid (domain=%02x).\n", diff -r 07655ed2fe58 -r bf512fde6667 xen/acm/acm_policy.c --- a/xen/acm/acm_policy.c Thu Jul 26 12:00:32 2007 +0100 +++ b/xen/acm/acm_policy.c Fri Jul 27 09:01:15 2007 +0100 @@ -438,6 +438,10 @@ acm_get_decision(ssidref_t ssidref1, ssi ret = acm_sharing(ssidref1, ssidref2); break; + case ACMHOOK_authorization: + ret = acm_authorization(ssidref1, ssidref2); + break; + default: /* deny */ break; diff -r 07655ed2fe58 -r bf512fde6667 xen/acm/acm_simple_type_enforcement_hooks.c --- a/xen/acm/acm_simple_type_enforcement_hooks.c Thu Jul 26 12:00:32 2007 +0100 +++ b/xen/acm/acm_simple_type_enforcement_hooks.c Fri Jul 27 09:01:15 2007 +0100 @@ -38,15 +38,16 @@ ssidref_t dom0_ste_ssidref = 0x0001; /* local cache structures for STE policy */ struct ste_binary_policy ste_bin_pol; -static inline int have_common_type (ssidref_t ref1, ssidref_t ref2) { +static inline int have_common_type (ssidref_t ref1, ssidref_t ref2) +{ int i; if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs && ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs ) { for( i = 0; i< ste_bin_pol.max_types; i++ ) - if ( ste_bin_pol.ssidrefs[ref1*ste_bin_pol.max_types + i] && - ste_bin_pol.ssidrefs[ref2*ste_bin_pol.max_types + i]) + if ( ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] && + ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i]) { printkd("%s: common type #%02x.\n", __func__, i); return 1; @@ -54,6 +55,26 @@ static inline int have_common_type (ssid } return 0; } + +static inline int is_superset(ssidref_t ref1, ssidref_t ref2) +{ + int i; + + if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs && + ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs ) + { + for( i = 0; i< ste_bin_pol.max_types; i++ ) + if (!ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] && + ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i]) + { + return 0; + } + } else { + return 0; + } + return 1; +} + /* Helper function: return = (subj and obj share a common type) */ static int share_common_type(struct domain *subj, struct domain *obj) @@ -609,6 +630,7 @@ ste_pre_domain_create(void *subject_ssid { /* check for ssidref in range for policy */ ssidref_t ste_ssidref; + traceprintk("%s.\n", __func__); read_lock(&acm_bin_pol_rwlock); @@ -830,6 +852,15 @@ ste_sharing(ssidref_t ssidref1, ssidref_ GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1), GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2)); return (hct ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED); +} + +static int +ste_authorization(ssidref_t ssidref1, ssidref_t ssidref2) +{ + int iss = is_superset( + GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1), + GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2)); + return (iss ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED); } static int @@ -867,6 +898,7 @@ struct acm_operations acm_simple_type_en .pre_grant_setup = ste_pre_grant_setup, .fail_grant_setup = NULL, .sharing = ste_sharing, + .authorization = ste_authorization, .is_default_policy = ste_is_default_policy, }; diff -r 07655ed2fe58 -r bf512fde6667 xen/include/acm/acm_core.h --- a/xen/include/acm/acm_core.h Thu Jul 26 12:00:32 2007 +0100 +++ b/xen/include/acm/acm_core.h Fri Jul 27 09:01:15 2007 +0100 @@ -153,8 +153,7 @@ static inline int acm_array_append_tuple } /* protos */ -int acm_init_domain_ssid(domid_t id, ssidref_t ssidref); -int acm_init_domain_ssid_new(struct domain *, ssidref_t ssidref); +int acm_init_domain_ssid(struct domain *, ssidref_t ssidref); void acm_free_domain_ssid(struct acm_ssid_domain *ssid); int acm_init_binary_policy(u32 policy_code); int acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size); diff -r 07655ed2fe58 -r bf512fde6667 xen/include/acm/acm_hooks.h --- a/xen/include/acm/acm_hooks.h Thu Jul 26 12:00:32 2007 +0100 +++ b/xen/include/acm/acm_hooks.h Fri Jul 27 09:01:15 2007 +0100 @@ -112,7 +112,10 @@ struct acm_operations { int (*pre_grant_setup) (domid_t id); void (*fail_grant_setup) (domid_t id); /* generic domain-requested decision hooks (can be NULL) */ - int (*sharing) (ssidref_t ssidref1, ssidref_t ssidref2); + int (*sharing) (ssidref_t ssidref1, + ssidref_t ssidref2); + int (*authorization) (ssidref_t ssidref1, + ssidref_t ssidref2); /* determine whether the default policy is installed */ int (*is_default_policy) (void); }; @@ -148,6 +151,8 @@ static inline int acm_is_policy(char *bu { return 0; } static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2) { return 0; } +static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2) +{ return 0; } static inline int acm_domain_create(struct domain *d, ssidref_t ssidref) { return 0; } static inline void acm_domain_destroy(struct domain *d) @@ -157,6 +162,19 @@ static inline void acm_domain_destroy(st #else +static inline void acm_domain_ssid_onto_list(struct acm_ssid_domain *ssid) +{ + write_lock(&ssid_list_rwlock); + list_add(&ssid->node, &ssid_list); + write_unlock(&ssid_list_rwlock); +} + +static inline void acm_domain_ssid_off_list(struct acm_ssid_domain *ssid) +{ + write_lock(&ssid_list_rwlock); + list_del(&ssid->node); + write_unlock(&ssid_list_rwlock); +} static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2) { @@ -241,6 +259,7 @@ static inline void acm_domain_destroy(st if (acm_secondary_ops->domain_destroy != NULL) acm_secondary_ops->domain_destroy(ssid, d); /* free security ssid for the destroyed domain (also if null policy */ + acm_domain_ssid_off_list(ssid); acm_free_domain_ssid((struct acm_ssid_domain *)(ssid)); } } @@ -250,13 +269,16 @@ static inline int acm_domain_create(stru { void *subject_ssid = current->domain->ssid; domid_t domid = d->domain_id; - int rc = 0; + int rc; read_lock(&acm_bin_pol_rwlock); /* To be called when a domain is created; returns '0' if the domain is allowed to be created, != '0' if not. */ + rc = acm_init_domain_ssid(d, ssidref); + if (rc != ACM_OK) + goto error_out; if ((acm_primary_ops->domain_create != NULL) && acm_primary_ops->domain_create(subject_ssid, ssidref, domid)) { @@ -267,18 +289,17 @@ static inline int acm_domain_create(stru /* roll-back primary */ if (acm_primary_ops->domain_destroy != NULL) acm_primary_ops->domain_destroy(d->ssid, d); + rc = ACM_ACCESS_DENIED; + } + + if ( rc == ACM_OK ) + { + acm_domain_ssid_onto_list(d->ssid); + } else { acm_free_domain_ssid(d->ssid); - rc = ACM_ACCESS_DENIED; - } - - if (rc == 0) { - rc = acm_init_domain_ssid_new(d, ssidref); - - if (rc != ACM_OK) { - acm_domain_destroy(d); - } - } - + } + +error_out: read_unlock(&acm_bin_pol_rwlock); return rc; } @@ -291,6 +312,19 @@ static inline int acm_sharing(ssidref_t return ACM_ACCESS_DENIED; else if ((acm_secondary_ops->sharing != NULL) && acm_secondary_ops->sharing(ssidref1, ssidref2)) { + return ACM_ACCESS_DENIED; + } else + return ACM_ACCESS_PERMITTED; +} + + +static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2) +{ + if ((acm_primary_ops->authorization != NULL) && + acm_primary_ops->authorization(ssidref1, ssidref2)) + return ACM_ACCESS_DENIED; + else if ((acm_secondary_ops->authorization != NULL) && + acm_secondary_ops->authorization(ssidref1, ssidref2)) { return ACM_ACCESS_DENIED; } else return ACM_ACCESS_PERMITTED; diff -r 07655ed2fe58 -r bf512fde6667 xen/include/public/acm.h --- a/xen/include/public/acm.h Thu Jul 26 12:00:32 2007 +0100 +++ b/xen/include/public/acm.h Fri Jul 27 09:01:15 2007 +0100 @@ -99,8 +99,9 @@ typedef uint32_t ssidref_t; typedef uint32_t ssidref_t; /* hooks that are known to domains */ -#define ACMHOOK_none 0 -#define ACMHOOK_sharing 1 +#define ACMHOOK_none 0 +#define ACMHOOK_sharing 1 +#define ACMHOOK_authorization 2 /* -------security policy relevant type definitions-------- */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |