# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1206726610 0
# Node ID 4e2e98c2098eb78faaaca6982370900f11851013
# Parent b5fea3aeb04b14b8ba82d3db18449bd593051113
Clean up handling of IS_PRIV_FOR() and rcu_[un]lock_domain().
In particular this *removes* some IS_PRIV_FOR() checks. *Especially*
in particular, all domctls are executable only by dom0. Several of
them were really unsafe for execution by a stub domain as they can
affect global system resource usage.
This probably breaks stub domains. Where necessary, some of these
reversions can themselves be reverted where they are judged both
necessary and safe.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/hvm/hvm.c | 11 ++-
xen/arch/x86/mm.c | 28 ++++----
xen/common/domain.c | 2
xen/common/domctl.c | 156 +++++++++++++--------------------------------
xen/common/event_channel.c | 49 ++++++++------
xen/common/grant_table.c | 43 ++++++------
xen/common/memory.c | 51 ++++++++------
7 files changed, 153 insertions(+), 187 deletions(-)
diff -r b5fea3aeb04b -r 4e2e98c2098e xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Fri Mar 28 14:12:33 2008 +0000
+++ b/xen/arch/x86/hvm/hvm.c Fri Mar 28 17:50:10 2008 +0000
@@ -2160,12 +2160,15 @@ long do_hvm_op(unsigned long op, XEN_GUE
return -EINVAL;
if ( a.domid == DOMID_SELF )
+ {
d = rcu_lock_current_domain();
- else {
- d = rcu_lock_domain_by_id(a.domid);
- if ( d == NULL )
+ }
+ else
+ {
+ if ( (d = rcu_lock_domain_by_id(a.domid)) == NULL )
return -ESRCH;
- if ( !IS_PRIV_FOR(current->domain, d) ) {
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
rc = -EPERM;
goto param_fail;
}
diff -r b5fea3aeb04b -r 4e2e98c2098e xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Fri Mar 28 14:12:33 2008 +0000
+++ b/xen/arch/x86/mm.c Fri Mar 28 17:50:10 2008 +0000
@@ -2114,14 +2114,14 @@ static int set_foreigndom(domid_t domid)
info->foreign = rcu_lock_domain(dom_xen);
break;
default:
- e = rcu_lock_domain_by_id(domid);
- if ( e == NULL )
+ if ( (e = rcu_lock_domain_by_id(domid)) == NULL )
{
MEM_LOG("Unknown domain '%u'", domid);
okay = 0;
break;
}
- if (!IS_PRIV_FOR(d, e)) {
+ if ( !IS_PRIV_FOR(d, e) )
+ {
MEM_LOG("Cannot set foreign dom");
okay = 0;
rcu_unlock_domain(e);
@@ -3259,12 +3259,15 @@ long arch_memory_op(int op, XEN_GUEST_HA
return -EFAULT;
if ( xatp.domid == DOMID_SELF )
+ {
d = rcu_lock_current_domain();
- else {
- d = rcu_lock_domain_by_id(xatp.domid);
- if ( d == NULL )
+ }
+ else
+ {
+ if ( (d = rcu_lock_domain_by_id(xatp.domid)) == NULL )
return -ESRCH;
- if ( !IS_PRIV_FOR(current->domain, d) ) {
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
rcu_unlock_domain(d);
return -EPERM;
}
@@ -3355,12 +3358,15 @@ long arch_memory_op(int op, XEN_GUEST_HA
return -EINVAL;
if ( fmap.domid == DOMID_SELF )
+ {
d = rcu_lock_current_domain();
- else {
- d = rcu_lock_domain_by_id(fmap.domid);
- if ( d == NULL )
+ }
+ else
+ {
+ if ( (d = rcu_lock_domain_by_id(fmap.domid)) == NULL )
return -ESRCH;
- if ( !IS_PRIV_FOR(current->domain, d) ) {
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
rcu_unlock_domain(d);
return -EPERM;
}
diff -r b5fea3aeb04b -r 4e2e98c2098e xen/common/domain.c
--- a/xen/common/domain.c Fri Mar 28 14:12:33 2008 +0000
+++ b/xen/common/domain.c Fri Mar 28 17:50:10 2008 +0000
@@ -522,7 +522,7 @@ static void complete_domain_destroy(stru
if ( (v = d->vcpu[i]) != NULL )
free_vcpu_struct(v);
- if (d->target)
+ if ( d->target != NULL )
put_domain(d->target);
free_domain(d);
diff -r b5fea3aeb04b -r 4e2e98c2098e xen/common/domctl.c
--- a/xen/common/domctl.c Fri Mar 28 14:12:33 2008 +0000
+++ b/xen/common/domctl.c Fri Mar 28 17:50:10 2008 +0000
@@ -182,6 +182,9 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
struct xen_domctl curop, *op = &curop;
static DEFINE_SPINLOCK(domctl_lock);
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
if ( copy_from_guest(op, u_domctl, 1) )
return -EFAULT;
@@ -203,10 +206,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
ret = -ESRCH;
if ( d == NULL )
break;
-
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto svc_out;
ret = xsm_setvcpucontext(d);
if ( ret )
@@ -259,10 +258,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
ret = -ESRCH;
if ( d != NULL )
{
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto pausedomain_out;
-
ret = xsm_pausedomain(d);
if ( ret )
goto pausedomain_out;
@@ -287,18 +282,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
if ( d == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto unpausedomain_out;
-
ret = xsm_unpausedomain(d);
if ( ret )
- goto unpausedomain_out;
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
domain_unpause_by_systemcontroller(d);
- ret = 0;
-unpausedomain_out:
- rcu_unlock_domain(d);
+ rcu_unlock_domain(d);
+ ret = 0;
}
break;
@@ -310,18 +303,16 @@ unpausedomain_out:
if ( d == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto resumedomain_out;
-
ret = xsm_resumedomain(d);
if ( ret )
- goto resumedomain_out;
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
domain_resume(d);
- ret = 0;
-resumedomain_out:
- rcu_unlock_domain(d);
+ rcu_unlock_domain(d);
+ ret = 0;
}
break;
@@ -331,10 +322,6 @@ resumedomain_out:
domid_t dom;
static domid_t rover = 0;
unsigned int domcr_flags;
-
- ret = -EPERM;
- if ( !IS_PRIV(current->domain) )
- break;
ret = -EINVAL;
if ( supervisor_mode_kernel ||
@@ -401,13 +388,12 @@ resumedomain_out:
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto maxvcpu_out2;
-
ret = xsm_max_vcpus(d);
if ( ret )
- goto maxvcpu_out2;
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
/* Needed, for example, to ensure writable p.t. state is synced. */
domain_pause(d);
@@ -435,7 +421,6 @@ resumedomain_out:
maxvcpu_out:
domain_unpause(d);
- maxvcpu_out2:
rcu_unlock_domain(d);
}
break;
@@ -446,9 +431,7 @@ resumedomain_out:
ret = -ESRCH;
if ( d != NULL )
{
- ret = -EPERM;
- if ( IS_PRIV_FOR(current->domain, d) )
- ret = xsm_destroydomain(d) ? : domain_kill(d);
+ ret = xsm_destroydomain(d) ? : domain_kill(d);
rcu_unlock_domain(d);
}
}
@@ -466,10 +449,6 @@ resumedomain_out:
if ( d == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto vcpuaffinity_out;
-
ret = xsm_vcpuaffinity(op->cmd, d);
if ( ret )
goto vcpuaffinity_out;
@@ -508,10 +487,6 @@ resumedomain_out:
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto scheduler_op_out;
-
ret = xsm_scheduler(d);
if ( ret )
goto scheduler_op_out;
@@ -533,7 +508,7 @@ resumedomain_out:
rcu_read_lock(&domlist_read_lock);
for_each_domain ( d )
- if ( d->domain_id >= dom && IS_PRIV_FOR(current->domain, d))
+ if ( d->domain_id >= dom )
break;
if ( d == NULL )
@@ -567,10 +542,6 @@ resumedomain_out:
ret = -ESRCH;
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
break;
-
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto getvcpucontext_out;
ret = xsm_getvcpucontext(d);
if ( ret )
@@ -632,10 +603,6 @@ resumedomain_out:
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto getvcpuinfo_out;
-
ret = xsm_getvcpuinfo(d);
if ( ret )
goto getvcpuinfo_out;
@@ -675,10 +642,6 @@ resumedomain_out:
if ( d == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto max_mem_out;
-
ret = xsm_setdomainmaxmem(d);
if ( ret )
goto max_mem_out;
@@ -695,8 +658,6 @@ resumedomain_out:
d->max_pages = new_max;
ret = 0;
}
- else
- printk("new max %ld, tot pages %d\n", new_max, d->tot_pages);
spin_unlock(&d->page_alloc_lock);
max_mem_out:
@@ -713,19 +674,17 @@ resumedomain_out:
if ( d == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto setdomainhandle_out;
-
ret = xsm_setdomainhandle(d);
if ( ret )
- goto setdomainhandle_out;
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
memcpy(d->handle, op->u.setdomainhandle.handle,
sizeof(xen_domain_handle_t));
- ret = 0;
-setdomainhandle_out:
- rcu_unlock_domain(d);
+ rcu_unlock_domain(d);
+ ret = 0;
}
break;
@@ -738,20 +697,18 @@ setdomainhandle_out:
if ( d == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto setdebugging_out;
-
ret = xsm_setdebugging(d);
if ( ret )
- goto setdebugging_out;
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
domain_pause(d);
d->debugger_attached = !!op->u.setdebugging.enable;
domain_unpause(d); /* causes guest to latch new status */
- ret = 0;
-setdebugging_out:
- rcu_unlock_domain(d);
+ rcu_unlock_domain(d);
+ ret = 0;
}
break;
@@ -768,10 +725,6 @@ setdebugging_out:
d = rcu_lock_domain_by_id(op->domain);
if ( d == NULL )
break;
-
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto irq_permission_out;
ret = xsm_irq_permission(d, pirq, op->u.irq_permission.allow_access);
if ( ret )
@@ -802,10 +755,6 @@ setdebugging_out:
if ( d == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto iomem_permission_out;
-
ret = xsm_iomem_permission(d, mfn,
op->u.iomem_permission.allow_access);
if ( ret )
goto iomem_permission_out;
@@ -829,19 +778,16 @@ setdebugging_out:
if ( d == NULL )
break;
- ret = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
- goto settimeoffset_out;
-
ret = xsm_domain_settime(d);
if ( ret )
- goto settimeoffset_out;
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
d->time_offset_seconds = op->u.settimeoffset.time_offset_seconds;
-
- ret = 0;
-settimeoffset_out:
- rcu_unlock_domain(d);
+ rcu_unlock_domain(d);
+ ret = 0;
}
break;
@@ -853,33 +799,25 @@ settimeoffset_out:
d = rcu_lock_domain_by_id(op->domain);
if ( d == NULL )
break;
-
- ret = -EPERM;
- if (!IS_PRIV_FOR(current->domain, d))
- goto set_target_out;
ret = -ESRCH;
e = get_domain_by_id(op->u.set_target.target);
if ( e == NULL )
goto set_target_out;
- if ( d == e ) {
- ret = -EINVAL;
+ ret = -EINVAL;
+ if ( (d == e) || (d->target != NULL) )
+ {
put_domain(e);
goto set_target_out;
}
- if (!IS_PRIV_FOR(current->domain, e)) {
- ret = -EPERM;
- put_domain(e);
- goto set_target_out;
- }
-
+ /* Hold reference on @e until we destroy @d. */
d->target = e;
- /* and we keep the reference on e, released when destroying d */
- ret = 0;
-
-set_target_out:
+
+ ret = 0;
+
+ set_target_out:
rcu_unlock_domain(d);
}
break;
diff -r b5fea3aeb04b -r 4e2e98c2098e xen/common/event_channel.c
--- a/xen/common/event_channel.c Fri Mar 28 14:12:33 2008 +0000
+++ b/xen/common/event_channel.c Fri Mar 28 17:50:10 2008 +0000
@@ -130,13 +130,17 @@ static long evtchn_alloc_unbound(evtchn_
long rc;
if ( dom == DOMID_SELF )
- d = current->domain;
- else {
+ {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
return -ESRCH;
- if ( !IS_PRIV_FOR(current->domain, d) ) {
- rc = -EPERM;
- goto out2;
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
+ rcu_unlock_domain(d);
+ return -EPERM;
}
}
@@ -158,8 +162,6 @@ static long evtchn_alloc_unbound(evtchn_
out:
spin_unlock(&d->evtchn_lock);
-
- out2:
rcu_unlock_domain(d);
return rc;
@@ -201,7 +203,7 @@ static long evtchn_bind_interdomain(evtc
ERROR_EXIT_DOM(-EINVAL, rd);
rchn = evtchn_from_port(rd, rport);
if ( (rchn->state != ECS_UNBOUND) ||
- (rchn->u.unbound.remote_domid != ld->domain_id && !IS_PRIV_FOR(ld,
rd)))
+ (rchn->u.unbound.remote_domid != ld->domain_id) )
ERROR_EXIT_DOM(-EINVAL, rd);
rc = xsm_evtchn_interdomain(ld, lchn, rd, rchn);
@@ -631,13 +633,17 @@ static long evtchn_status(evtchn_status_
long rc = 0;
if ( dom == DOMID_SELF )
- d = current->domain;
- else {
+ {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
return -ESRCH;
- if ( !IS_PRIV_FOR(current->domain, d) ) {
- rc = -EPERM;
- goto out2;
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
+ rcu_unlock_domain(d);
+ return -EPERM;
}
}
@@ -690,8 +696,8 @@ static long evtchn_status(evtchn_status_
out:
spin_unlock(&d->evtchn_lock);
- out2:
rcu_unlock_domain(d);
+
return rc;
}
@@ -742,6 +748,7 @@ long evtchn_bind_vcpu(unsigned int port,
out:
spin_unlock(&d->evtchn_lock);
+
return rc;
}
@@ -784,15 +791,18 @@ static long evtchn_reset(evtchn_reset_t
{
domid_t dom = r->dom;
struct domain *d;
- int i;
- int rc;
+ int i, rc;
if ( dom == DOMID_SELF )
- d = current->domain;
- else {
+ {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
return -ESRCH;
- if ( !IS_PRIV_FOR(current->domain, d) ) {
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
rc = -EPERM;
goto out;
}
@@ -806,6 +816,7 @@ static long evtchn_reset(evtchn_reset_t
(void)__evtchn_close(d, i);
rc = 0;
+
out:
rcu_unlock_domain(d);
diff -r b5fea3aeb04b -r 4e2e98c2098e xen/common/grant_table.c
--- a/xen/common/grant_table.c Fri Mar 28 14:12:33 2008 +0000
+++ b/xen/common/grant_table.c Fri Mar 28 17:50:10 2008 +0000
@@ -828,32 +828,34 @@ gnttab_setup_table(
" per domain.\n",
max_nr_grant_frames);
op.status = GNTST_general_error;
- goto out;
+ goto out1;
}
dom = op.dom;
if ( dom == DOMID_SELF )
{
- d = current->domain;
- }
- else {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) )
{
gdprintk(XENLOG_INFO, "Bad domid %d.\n", dom);
op.status = GNTST_bad_domain;
- goto out;
- }
- if ( unlikely(!IS_PRIV_FOR(current->domain, d)) ) {
+ goto out1;
+ }
+
+ if ( unlikely(!IS_PRIV_FOR(current->domain, d)) )
+ {
op.status = GNTST_permission_denied;
- goto setup_unlock_out2;
+ goto out2;
}
}
if ( xsm_grant_setup(current->domain, d) )
{
- rcu_unlock_domain(d);
op.status = GNTST_permission_denied;
- goto out;
+ goto out2;
}
spin_lock(&d->grant_table->lock);
@@ -867,7 +869,7 @@ gnttab_setup_table(
nr_grant_frames(d->grant_table),
max_nr_grant_frames);
op.status = GNTST_general_error;
- goto setup_unlock_out;
+ goto out3;
}
op.status = GNTST_okay;
@@ -877,13 +879,11 @@ gnttab_setup_table(
(void)copy_to_guest_offset(op.frame_list, i, &gmfn, 1);
}
- setup_unlock_out:
+ out3:
spin_unlock(&d->grant_table->lock);
-
- setup_unlock_out2:
+ out2:
rcu_unlock_domain(d);
-
- out:
+ out1:
if ( unlikely(copy_to_guest(uop, &op, 1)) )
return -EFAULT;
@@ -911,16 +911,19 @@ gnttab_query_size(
dom = op.dom;
if ( dom == DOMID_SELF )
{
- d = current->domain;
- }
- else {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) )
{
gdprintk(XENLOG_INFO, "Bad domid %d.\n", dom);
op.status = GNTST_bad_domain;
goto query_out;
}
- if ( unlikely(!IS_PRIV_FOR(current->domain, d)) ) {
+
+ if ( unlikely(!IS_PRIV_FOR(current->domain, d)) )
+ {
op.status = GNTST_permission_denied;
goto query_out_unlock;
}
diff -r b5fea3aeb04b -r 4e2e98c2098e xen/common/memory.c
--- a/xen/common/memory.c Fri Mar 28 14:12:33 2008 +0000
+++ b/xen/common/memory.c Fri Mar 28 17:50:10 2008 +0000
@@ -232,12 +232,15 @@ static long translate_gpfn_list(
return -EFAULT;
if ( op.domid == DOMID_SELF )
- d = current->domain;
- else {
- d = rcu_lock_domain_by_id(op.domid);
- if ( d == NULL )
+ {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
+ if ( (d = rcu_lock_domain_by_id(op.domid)) == NULL )
return -ESRCH;
- if ( !IS_PRIV_FOR(current->domain, d) ) {
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
rcu_unlock_domain(d);
return -EPERM;
}
@@ -539,12 +542,15 @@ long do_memory_op(unsigned long cmd, XEN
}
if ( likely(reservation.domid == DOMID_SELF) )
- d = current->domain;
- else {
- d = rcu_lock_domain_by_id(reservation.domid);
- if ( d == NULL)
+ {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
+ if ( (d = rcu_lock_domain_by_id(reservation.domid)) == NULL )
return start_extent;
- if ( !IS_PRIV_FOR(current->domain, d) ) {
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
rcu_unlock_domain(d);
return start_extent;
}
@@ -554,8 +560,7 @@ long do_memory_op(unsigned long cmd, XEN
rc = xsm_memory_adjust_reservation(current->domain, d);
if ( rc )
{
- if ( reservation.domid != DOMID_SELF )
- rcu_unlock_domain(d);
+ rcu_unlock_domain(d);
return rc;
}
@@ -572,8 +577,7 @@ long do_memory_op(unsigned long cmd, XEN
break;
}
- if ( unlikely(reservation.domid != DOMID_SELF) )
- rcu_unlock_domain(d);
+ rcu_unlock_domain(d);
rc = args.nr_done;
@@ -599,12 +603,15 @@ long do_memory_op(unsigned long cmd, XEN
return -EFAULT;
if ( likely(domid == DOMID_SELF) )
- d = current->domain;
- else {
- d = rcu_lock_domain_by_id(domid);
- if ( d == NULL )
+ {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
+ if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
return -ESRCH;
- if ( !IS_PRIV_FOR(current->domain, d) ) {
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
rcu_unlock_domain(d);
return -EPERM;
}
@@ -613,8 +620,7 @@ long do_memory_op(unsigned long cmd, XEN
rc = xsm_memory_stat_reservation(current->domain, d);
if ( rc )
{
- if ( domid != DOMID_SELF )
- rcu_unlock_domain(d);
+ rcu_unlock_domain(d);
return rc;
}
@@ -632,8 +638,7 @@ long do_memory_op(unsigned long cmd, XEN
break;
}
- if ( unlikely(domid != DOMID_SELF) )
- rcu_unlock_domain(d);
+ rcu_unlock_domain(d);
break;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|