Index: root/xen-unstable.hg/xen/common/domctl.c =================================================================== --- root.orig/xen-unstable.hg/xen/common/domctl.c +++ root/xen-unstable.hg/xen/common/domctl.c @@ -176,7 +176,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc { long ret = 0; struct xen_domctl curop, *op = &curop; - void *ssid = NULL; /* save security ptr between pre and post/fail hooks */ static DEFINE_SPINLOCK(domctl_lock); if ( !IS_PRIV(current->domain) ) @@ -188,13 +187,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc if ( op->interface_version != XEN_DOMCTL_INTERFACE_VERSION ) return -EACCES; - acm_rlock_policy(op->cmd); - - if ( acm_pre_domctl(op, &ssid) ) { - acm_runlock_policy(op->cmd); - return -EPERM; - } - spin_lock(&domctl_lock); switch ( op->cmd ) @@ -304,52 +296,69 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc static domid_t rover = 0; unsigned int domcr_flags; - if ( supervisor_mode_kernel || - (op->u.createdomain.flags & ~XEN_DOMCTL_CDF_hvm_guest) ) { - ret = -EINVAL; + acm_rlock_policy(); + + if ( acm_pre_domctl_createdomain(op) ) { + acm_runlock_policy(); + ret = -EPERM; break; } - dom = op->domain; - if ( (dom > 0) && (dom < DOMID_FIRST_RESERVED) ) - { - ret = -EINVAL; - if ( !is_free_domid(dom) ) + do { + if ( supervisor_mode_kernel || + (op->u.createdomain.flags & ~XEN_DOMCTL_CDF_hvm_guest) ) { + ret = -EINVAL; break; - } - else - { - for ( dom = rover + 1; dom != rover; dom++ ) + } + + dom = op->domain; + if ( (dom > 0) && (dom < DOMID_FIRST_RESERVED) ) + { + ret = -EINVAL; + if ( !is_free_domid(dom) ) + break; + } + else { - if ( dom == DOMID_FIRST_RESERVED ) - dom = 0; - if ( is_free_domid(dom) ) + for ( dom = rover + 1; dom != rover; dom++ ) + { + if ( dom == DOMID_FIRST_RESERVED ) + dom = 0; + if ( is_free_domid(dom) ) + break; + } + + ret = -ENOMEM; + if ( dom == rover ) break; + + rover = dom; } + domcr_flags = 0; + if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_hvm_guest ) + domcr_flags |= DOMCRF_hvm; + ret = -ENOMEM; - if ( dom == rover ) + if ( (d = domain_create(dom, domcr_flags)) == NULL ) break; - rover = dom; - } - - domcr_flags = 0; - if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_hvm_guest ) - domcr_flags |= DOMCRF_hvm; + ret = 0; - ret = -ENOMEM; - if ( (d = domain_create(dom, domcr_flags)) == NULL ) - break; + memcpy(d->handle, op->u.createdomain.handle, + sizeof(xen_domain_handle_t)); - ret = 0; + op->domain = d->domain_id; + if ( copy_to_guest(u_domctl, op, 1) ) + ret = -EFAULT; + } while (0); - memcpy(d->handle, op->u.createdomain.handle, - sizeof(xen_domain_handle_t)); + if ( ret == 0 ) + acm_post_domctl_createdomain(op); + else + acm_fail_domctl_createdomain(op); - op->domain = d->domain_id; - if ( copy_to_guest(u_domctl, op, 1) ) - ret = -EFAULT; + acm_runlock_policy(); } break; @@ -399,6 +408,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc case XEN_DOMCTL_destroydomain: { struct domain *d = rcu_lock_domain_by_id(op->domain); + void *ssid; /* save security ptr between pre and post/fail hooks */ + + if ( acm_pre_domctl_destroydomain(op, &ssid) ) { + ret = -EPERM; + break; + } + ret = -ESRCH; if ( d != NULL ) { @@ -410,6 +426,11 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc } rcu_unlock_domain(d); } + + if ( ret == 0 ) + acm_post_domctl_destroydomain(op, &ssid); + else + acm_fail_domctl_destroydomain(op, &ssid); } break; @@ -722,13 +743,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc spin_unlock(&domctl_lock); - if ( ret == 0 ) - acm_post_domctl(op, &ssid); - else - acm_fail_domctl(op, &ssid); - - acm_runlock_policy(op->cmd); - return ret; } Index: root/xen-unstable.hg/xen/include/acm/acm_hooks.h =================================================================== --- root.orig/xen-unstable.hg/xen/include/acm/acm_hooks.h +++ root/xen-unstable.hg/xen/include/acm/acm_hooks.h @@ -132,11 +132,20 @@ extern struct acm_operations *acm_second #ifndef ACM_SECURITY -static inline int acm_pre_domctl(struct xen_domctl *op, void **ssid) +static inline int acm_pre_domctl_createdomain(struct xen_domctl *op) { return 0; } -static inline void acm_post_domctl(struct xen_domctl *op, void *ssid) +static inline void acm_post_domctl_createdomain(struct xen_domctl *op) { return; } -static inline void acm_fail_domctl(struct xen_domctl *op, void *ssid) +static inline void acm_fail_domctl_createdomain(struct xen_domctl *op) +{ return; } +static inline int acm_pre_domctl_destroydomain(struct xen_domctl *op, + void **ssid) +{ return 0; } +static inline void acm_post_domctl_destroydomain(struct xen_domctl *op, + void *ssid) +{ return; } +static inline void acm_fail_domctl_destroydomain(struct xen_domctl *op, + void *ssid) { return; } static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2) { return 0; } @@ -154,9 +163,9 @@ static inline void acm_post_domain0_crea { return; } static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2) { return 0; } -static inline void acm_rlock_policy(int cmd) +static inline void acm_rlock_policy(void) { return; } -static inline void acm_runlock_policy(int cmd) +static inline void acm_runlock_policy(void) { return; } #else @@ -232,86 +241,77 @@ static inline int acm_pre_eventchannel_i return ACM_ACCESS_PERMITTED; } -static inline int acm_pre_domctl(struct xen_domctl *op, void **ssid) + +static inline int acm_pre_domctl_createdomain(struct xen_domctl *op) { - int ret = -EACCES; - struct domain *d; + return acm_pre_domain_create(current->domain->ssid, + op->u.createdomain.ssidref); +} - switch(op->cmd) { - case XEN_DOMCTL_createdomain: - ret = acm_pre_domain_create( - current->domain->ssid, op->u.createdomain.ssidref); - break; - case XEN_DOMCTL_destroydomain: - if (*ssid != NULL) { - printkd("%s: Warning. Overlapping destruction.\n", - __func__); - return -EACCES; - } - d = rcu_lock_domain_by_id(op->domain); - if (d != NULL) { - *ssid = d->ssid; /* save for post destroy when d is gone */ - if (*ssid == NULL) { - printk("%s: Warning. Destroying domain without ssid pointer.\n", - __func__); - rcu_unlock_domain(d); - return -EACCES; - } - d->ssid = NULL; /* make sure it's not used any more */ - /* no policy-specific hook */ +static inline int acm_pre_domctl_destroydomain(struct xen_domctl *op, + void **ssid) +{ + int ret = -EACCES; + struct domain *d = rcu_lock_domain_by_id(op->domain); + if (d != NULL) { + *ssid = d->ssid; /* save for post destroy when d is gone */ + if (*ssid == NULL) { + printk("%s: Warning. Destroying domain without ssid pointer.\n", + __func__); rcu_unlock_domain(d); - ret = 0; + return -EACCES; } - break; - default: - ret = 0; /* ok */ + d->ssid = NULL; /* make sure it's not used any more */ + /* no policy-specific hook */ + rcu_unlock_domain(d); + ret = 0; + } else { + *ssid = NULL; } return ret; } -static inline void acm_post_domctl(struct xen_domctl *op, void **ssid) +static inline void acm_post_domctl_createdomain(struct xen_domctl *op) { - switch(op->cmd) { - case XEN_DOMCTL_createdomain: - /* initialialize shared sHype security labels for new domain */ - acm_init_domain_ssid( - op->domain, op->u.createdomain.ssidref); - acm_post_domain_create( - op->domain, op->u.createdomain.ssidref); - break; - case XEN_DOMCTL_destroydomain: - if (*ssid == NULL) { - printkd("%s: ERROR. SSID unset.\n", - __func__); - break; - } - acm_post_domain_destroy(*ssid, op->domain); - /* free security ssid for the destroyed domain (also if null policy */ - acm_free_domain_ssid((struct acm_ssid_domain *)(*ssid)); - *ssid = NULL; - break; + acm_init_domain_ssid(op->domain, op->u.createdomain.ssidref); + acm_post_domain_create(op->domain, op->u.createdomain.ssidref); +} + + +static inline void acm_post_domctl_destroydomain(struct xen_domctl *op, + void **ssid) +{ + if (*ssid == NULL) { + printkd("%s: ERROR. SSID unset.\n", + __func__); + return; } + acm_post_domain_destroy(*ssid, op->domain); + /* free security ssid for the destroyed domain (also if null policy */ + acm_free_domain_ssid((struct acm_ssid_domain *)(*ssid)); + *ssid = NULL; } -static inline void acm_fail_domctl(struct xen_domctl *op, void **ssid) + +static inline void acm_fail_domctl_createdomain(struct xen_domctl *op) { - switch(op->cmd) { - case XEN_DOMCTL_createdomain: - acm_fail_domain_create( + acm_fail_domain_create( current->domain->ssid, op->u.createdomain.ssidref); - break; - case XEN_DOMCTL_destroydomain: - /* we don't handle domain destroy failure but at least free the ssid */ - if (*ssid == NULL) { - printkd("%s: ERROR. SSID unset.\n", - __func__); - break; - } - acm_free_domain_ssid((struct acm_ssid_domain *)(*ssid)); - *ssid = NULL; +} + +static inline void acm_fail_domctl_destroydomain(struct xen_domctl *op, + void **ssid) +{ + if (*ssid == NULL) { + printkd("%s: ERROR. SSID unset.\n", + __func__); + return; } + acm_free_domain_ssid((struct acm_ssid_domain *)(*ssid)); + *ssid = NULL; } + static inline int acm_pre_grant_map_ref(domid_t id) { if ( (acm_primary_ops->pre_grant_map_ref != NULL) && @@ -375,18 +375,14 @@ static inline int acm_sharing(ssidref_t return ACM_ACCESS_PERMITTED; } -static inline void acm_rlock_policy(int cmd) +static inline void acm_rlock_policy(void) { - if (cmd == XEN_DOMCTL_createdomain) { - read_lock(&acm_bin_pol_rwlock); - } + read_lock(&acm_bin_pol_rwlock); } -static inline void acm_runlock_policy(int cmd) +static inline void acm_runlock_policy(void) { - if (cmd == XEN_DOMCTL_createdomain) { - read_unlock(&acm_bin_pol_rwlock); - } + read_unlock(&acm_bin_pol_rwlock); } extern int acm_init(char *policy_start, unsigned long policy_len);