# 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
|