aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-04-08 14:06:37 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-04-08 14:06:37 +0100
commit7e2b6626e8a6692b1024c52a09ad6ff955e16b05 (patch)
tree129559a234294860dbdee5ab0bd11565aaa96d92
parent2a75d8fdffdba432c0b6dddea59a4db85f51a2ce (diff)
downloadxen-7e2b6626e8a6692b1024c52a09ad6ff955e16b05.tar.gz
xen-7e2b6626e8a6692b1024c52a09ad6ff955e16b05.tar.bz2
xen-7e2b6626e8a6692b1024c52a09ad6ff955e16b05.zip
x86 hvm: Fix privilege checking in do_hvm_op() hypercall.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/x86/hvm/hvm.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index bc2046fb78..b8b1579041 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -2377,6 +2377,9 @@ static int hvmop_flush_tlb_all(void)
struct domain *d = current->domain;
struct vcpu *v;
+ if ( !is_hvm_domain(d) )
+ return -EINVAL;
+
/* Avoid deadlock if more than one vcpu tries this at the same time. */
if ( !spin_trylock(&d->hypercall_deadlock_mutex) )
return -EAGAIN;
@@ -2413,6 +2416,7 @@ static int hvmop_flush_tlb_all(void)
long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
{
+ struct domain *curr_d = current->domain;
long rc = 0;
switch ( op )
@@ -2435,6 +2439,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
if ( rc != 0 )
return rc;
+ rc = -EPERM;
+ if ( (curr_d != d) && !IS_PRIV_FOR(curr_d, d) )
+ goto param_fail;
+
rc = -EINVAL;
if ( !is_hvm_domain(d) )
goto param_fail;
@@ -2477,8 +2485,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
rc = -EINVAL;
break;
case HVM_PARAM_IDENT_PT:
+ /* Not reflexive, as we must domain_pause(). */
rc = -EPERM;
- if ( !IS_PRIV(current->domain) )
+ if ( curr_d == d )
break;
rc = -EINVAL;
@@ -2508,13 +2517,13 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
domctl_lock_release();
break;
case HVM_PARAM_DM_DOMAIN:
- /* Privileged domains only, as we must domain_pause(d). */
+ /* Not reflexive, as we must domain_pause(). */
rc = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
+ if ( curr_d == d )
break;
if ( a.value == DOMID_SELF )
- a.value = current->domain->domain_id;
+ a.value = curr_d->domain_id;
rc = 0;
domain_pause(d); /* safe to change per-vcpu xen_port */
@@ -2539,9 +2548,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
domain_unpause(d);
break;
case HVM_PARAM_ACPI_S_STATE:
- /* Privileged domains only, as we must domain_pause(d). */
+ /* Not reflexive, as we must domain_pause(). */
rc = -EPERM;
- if ( !IS_PRIV_FOR(current->domain, d) )
+ if ( curr_d == d )
break;
rc = 0;
@@ -2612,6 +2621,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
if ( rc != 0 )
return rc;
+ rc = -EPERM;
+ if ( !IS_PRIV_FOR(curr_d, d) )
+ goto param_fail2;
+
rc = -EINVAL;
if ( !is_hvm_domain(d) )
goto param_fail2;
@@ -2650,6 +2663,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
if ( rc != 0 )
return rc;
+ rc = -EPERM;
+ if ( !IS_PRIV_FOR(curr_d, d) )
+ goto param_fail3;
+
rc = -EINVAL;
if ( !is_hvm_domain(d) )
goto param_fail3;
@@ -2706,6 +2723,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
if ( rc != 0 )
return rc;
+ rc = -EPERM;
+ if ( !IS_PRIV_FOR(curr_d, d) )
+ goto param_fail4;
+
rc = -EINVAL;
if ( !is_hvm_domain(d) )
goto param_fail4;