[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] This patch
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 7ba4019f7b2d1db8a5e060b699541dc4b7ccfb8f # Parent 897adc98fec23d36fd9644a32e608af9ffbbaba5 This patch * adapts the Xen access control module to recent changes in the "unbound event channel" interface and its usage * adds checks that became necessary because of domain structures "hanging around" in the domain list after domain destruction This patch is tested on today's xen-unstable with Null, CHWALL, STE, CHWALL_STE policies. Signed-off by: Reiner Sailer <sailer@xxxxxxxxxx> diff -r 897adc98fec2 -r 7ba4019f7b2d xen/acm/acm_simple_type_enforcement_hooks.c --- a/xen/acm/acm_simple_type_enforcement_hooks.c Thu Oct 27 16:20:33 2005 +++ b/xen/acm/acm_simple_type_enforcement_hooks.c Thu Oct 27 16:24:06 2005 @@ -392,8 +392,11 @@ int i; printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom); + + if (dom->ssid == NULL) + return 0; ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - (struct acm_ssid_domain *)(dom)->ssid); + (struct acm_ssid_domain *)(dom->ssid)); for(i=0; i< ACM_TE_CACHE_SIZE; i++) { if ((ste_ssid->ste_cache[i].valid == VALID) && @@ -412,6 +415,8 @@ struct ste_ssid *ste_ssid; int i; printkd("caching from doms: %x --> %x.\n", subj->domain_id, obj->domain_id); + if (subj->ssid == NULL) + return; ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, (struct acm_ssid_domain *)(subj)->ssid); for(i=0; i< ACM_TE_CACHE_SIZE; i++) @@ -431,26 +436,34 @@ struct ste_ssid *ste_ssid; int i; struct domain **pd; + struct acm_ssid_domain *ssid; printkd("deleting cache for dom %x.\n", id); - read_lock(&domlist_lock); /* look through caches of all domains */ pd = &domain_list; for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { - ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - (struct acm_ssid_domain *)(*pd)->ssid); + ssid = (struct acm_ssid_domain *)((*pd)->ssid); + + if (ssid == NULL) + continue; /* hanging domain structure, no ssid any more ... */ + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssid); + if (!ste_ssid) { + printk("%s: deleting ID from cache ERROR (no ste_ssid)!\n", + __func__); + goto out; + } for (i=0; i<ACM_TE_CACHE_SIZE; i++) if ((ste_ssid->ste_cache[i].valid == VALID) && - (ste_ssid->ste_cache[i].id = id)) + (ste_ssid->ste_cache[i].id == id)) ste_ssid->ste_cache[i].valid = FREE; } + out: read_unlock(&domlist_lock); } /*************************** * Authorization functions **************************/ - static int ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref) { @@ -484,19 +497,29 @@ /* -------- EVENTCHANNEL OPERATIONS -----------*/ static int -ste_pre_eventchannel_unbound(domid_t id) { +ste_pre_eventchannel_unbound(domid_t id1, domid_t id2) { struct domain *subj, *obj; int ret; - traceprintk("%s: dom%x-->dom%x.\n", - __func__, current->domain->domain_id, id); - - if (check_cache(current->domain, id)) { + traceprintk("%s: dom%x-->dom%x.\n", __func__, + (id1 == DOMID_SELF) ? current->domain->domain_id : id1, + (id2 == DOMID_SELF) ? current->domain->domain_id : id2); + + if (id1 == DOMID_SELF) id1 = current->domain->domain_id; + if (id2 == DOMID_SELF) id2 = current->domain->domain_id; + + subj = find_domain_by_id(id1); + obj = find_domain_by_id(id2); + if ((subj == NULL) || (obj == NULL)) { + ret = ACM_ACCESS_DENIED; + goto out; + } + /* cache check late */ + if (check_cache(subj, obj->domain_id)) { atomic_inc(&ste_bin_pol.ec_cachehit_count); - return ACM_ACCESS_PERMITTED; + ret = ACM_ACCESS_PERMITTED; + goto out; } atomic_inc(&ste_bin_pol.ec_eval_count); - subj = current->domain; - obj = find_domain_by_id(id); if (share_common_type(subj, obj)) { cache_result(subj, obj); @@ -505,38 +528,43 @@ atomic_inc(&ste_bin_pol.ec_denied_count); ret = ACM_ACCESS_DENIED; } + out: if (obj != NULL) put_domain(obj); + if (subj != NULL) + put_domain(subj); return ret; } static int -ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2) -{ - struct domain *subj, *obj; +ste_pre_eventchannel_interdomain(domid_t id) +{ + struct domain *subj=NULL, *obj=NULL; int ret; + traceprintk("%s: dom%x-->dom%x.\n", __func__, - (id1 == DOMID_SELF) ? current->domain->domain_id : id1, - (id2 == DOMID_SELF) ? current->domain->domain_id : id2); + current->domain->domain_id, + (id == DOMID_SELF) ? current->domain->domain_id : id); /* following is a bit longer but ensures that we * "put" only domains that we where "find"-ing */ - if (id1 == DOMID_SELF) id1 = current->domain->domain_id; - if (id2 == DOMID_SELF) id2 = current->domain->domain_id; - - subj = find_domain_by_id(id1); - obj = find_domain_by_id(id2); - if ((subj == NULL) || (obj == NULL)) { + if (id == DOMID_SELF) id = current->domain->domain_id; + + subj = current->domain; + obj = find_domain_by_id(id); + if (obj == NULL) { ret = ACM_ACCESS_DENIED; goto out; } + /* cache check late, but evtchn is not on performance critical path */ if (check_cache(subj, obj->domain_id)) { atomic_inc(&ste_bin_pol.ec_cachehit_count); ret = ACM_ACCESS_PERMITTED; goto out; } + atomic_inc(&ste_bin_pol.ec_eval_count); if (share_common_type(subj, obj)) { @@ -549,8 +577,6 @@ out: if (obj != NULL) put_domain(obj); - if (subj != NULL) - put_domain(subj); return ret; } diff -r 897adc98fec2 -r 7ba4019f7b2d xen/common/acm_ops.c --- a/xen/common/acm_ops.c Thu Oct 27 16:20:33 2005 +++ b/xen/common/acm_ops.c Thu Oct 27 16:24:06 2005 @@ -133,7 +133,10 @@ struct domain *subj = find_domain_by_id(op->u.getssid.id.domainid); if (!subj) return -ESRCH; /* domain not found */ - + if (subj->ssid == NULL) { + put_domain(subj); + return -ESRCH; + } ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; put_domain(subj); } else @@ -167,6 +170,10 @@ ret = -ESRCH; /* domain not found */ goto out; } + if (subj->ssid == NULL) { + put_domain(subj); + ret = -ESRCH; + } ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; put_domain(subj); } else { @@ -181,6 +188,10 @@ if (!subj) { ret = -ESRCH; /* domain not found */ goto out; + } + if (subj->ssid == NULL) { + put_domain(subj); + return -ESRCH; } ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; put_domain(subj); diff -r 897adc98fec2 -r 7ba4019f7b2d xen/include/acm/acm_hooks.h --- a/xen/include/acm/acm_hooks.h Thu Oct 27 16:20:33 2005 +++ b/xen/include/acm/acm_hooks.h Thu Oct 27 16:24:06 2005 @@ -100,10 +100,10 @@ void (*fail_domain_create) (void *subject_ssid, ssidref_t ssidref); void (*post_domain_destroy) (void *object_ssid, domid_t id); /* event channel control hooks (can be NULL) */ - int (*pre_eventchannel_unbound) (domid_t id); - void (*fail_eventchannel_unbound) (domid_t id); - int (*pre_eventchannel_interdomain) (domid_t id1, domid_t id2); - int (*fail_eventchannel_interdomain) (domid_t id1, domid_t id2); + int (*pre_eventchannel_unbound) (domid_t id1, domid_t id2); + void (*fail_eventchannel_unbound) (domid_t id1, domid_t id2); + int (*pre_eventchannel_interdomain) (domid_t id); + void (*fail_eventchannel_interdomain) (domid_t id); /* grant table control hooks (can be NULL) */ int (*pre_grant_map_ref) (domid_t id); void (*fail_grant_map_ref) (domid_t id); @@ -193,31 +193,31 @@ return; } -static inline int acm_pre_eventchannel_unbound(domid_t id) +static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2) { if ((acm_primary_ops->pre_eventchannel_unbound != NULL) && - acm_primary_ops->pre_eventchannel_unbound(id)) + acm_primary_ops->pre_eventchannel_unbound(id1, id2)) return ACM_ACCESS_DENIED; else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) && - acm_secondary_ops->pre_eventchannel_unbound(id)) { + acm_secondary_ops->pre_eventchannel_unbound(id1, id2)) { /* roll-back primary */ if (acm_primary_ops->fail_eventchannel_unbound != NULL) - acm_primary_ops->fail_eventchannel_unbound(id); + acm_primary_ops->fail_eventchannel_unbound(id1, id2); return ACM_ACCESS_DENIED; } else return ACM_ACCESS_PERMITTED; } -static inline int acm_pre_eventchannel_interdomain(domid_t id1, domid_t id2) +static inline int acm_pre_eventchannel_interdomain(domid_t id) { if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) && - acm_primary_ops->pre_eventchannel_interdomain(id1, id2)) + acm_primary_ops->pre_eventchannel_interdomain(id)) return ACM_ACCESS_DENIED; else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) && - acm_secondary_ops->pre_eventchannel_interdomain(id1, id2)) { + acm_secondary_ops->pre_eventchannel_interdomain(id)) { /* roll-back primary */ if (acm_primary_ops->fail_eventchannel_interdomain != NULL) - acm_primary_ops->fail_eventchannel_interdomain(id1, id2); + acm_primary_ops->fail_eventchannel_interdomain(id); return ACM_ACCESS_DENIED; } else return ACM_ACCESS_PERMITTED; @@ -234,10 +234,22 @@ current->domain->ssid, op->u.createdomain.ssidref); break; case DOM0_DESTROYDOMAIN: + if (*ssid != NULL) { + printkd("%s: Warning. Overlapping destruction.\n", + __func__); + return -EACCES; + } d = find_domain_by_id(op->u.destroydomain.domain); if (d != NULL) { *ssid = d->ssid; /* save for post destroy when d is gone */ - /* no policy-specific hook */ + if (*ssid == NULL) { + printk("%s: Warning. Destroying domain without ssid pointer.\n", + __func__); + put_domain(d); + return -EACCES; + } + d->ssid = NULL; /* make sure it's not used any more */ + /* no policy-specific hook */ put_domain(d); ret = 0; } @@ -248,7 +260,7 @@ return ret; } -static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid) +static inline void acm_post_dom0_op(dom0_op_t *op, void **ssid) { switch(op->cmd) { case DOM0_CREATEDOMAIN: @@ -261,7 +273,8 @@ case DOM0_DESTROYDOMAIN: acm_post_domain_destroy(ssid, op->u.destroydomain.domain); /* free security ssid for the destroyed domain (also if null policy */ - acm_free_domain_ssid((struct acm_ssid_domain *)ssid); + acm_free_domain_ssid((struct acm_ssid_domain *)(*ssid)); + *ssid = NULL; break; } } @@ -282,12 +295,13 @@ switch(op->cmd) { case EVTCHNOP_alloc_unbound: - ret = acm_pre_eventchannel_unbound(op->u.alloc_unbound.dom); + ret = acm_pre_eventchannel_unbound( + op->u.alloc_unbound.dom, + op->u.alloc_unbound.remote_dom); break; case EVTCHNOP_bind_interdomain: ret = acm_pre_eventchannel_interdomain( - current->domain->domain_id, - op->u.bind_interdomain.remote_dom); + op->u.bind_interdomain.remote_dom); break; default: ret = 0; /* ok */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |