aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-05-02 16:37:24 +0200
committerJan Beulich <jbeulich@suse.com>2013-05-02 16:37:24 +0200
commit4939f9a6dee4280f38730fd3066e5dce353112f6 (patch)
treef7fc6fa0c8f7b1261706f24a15c6ee9e58534440 /xen/common
parent918a5f17b447072b40780f4d03a3adc99ff0073b (diff)
downloadxen-4939f9a6dee4280f38730fd3066e5dce353112f6.tar.gz
xen-4939f9a6dee4280f38730fd3066e5dce353112f6.tar.bz2
xen-4939f9a6dee4280f38730fd3066e5dce353112f6.zip
x86: make vcpu_reset() preemptible
... as dropping the old page tables may take significant amounts of time. This is part of CVE-2013-1918 / XSA-45. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Tim Deegan <tim@xen.org>
Diffstat (limited to 'xen/common')
-rw-r--r--xen/common/domain.c12
-rw-r--r--xen/common/domctl.c13
2 files changed, 17 insertions, 8 deletions
diff --git a/xen/common/domain.c b/xen/common/domain.c
index ce45d66b45..7cca65507d 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -868,14 +868,18 @@ void domain_unpause_by_systemcontroller(struct domain *d)
domain_unpause(d);
}
-void vcpu_reset(struct vcpu *v)
+int vcpu_reset(struct vcpu *v)
{
struct domain *d = v->domain;
+ int rc;
vcpu_pause(v);
domain_lock(d);
- arch_vcpu_reset(v);
+ set_bit(_VPF_in_reset, &v->pause_flags);
+ rc = arch_vcpu_reset(v);
+ if ( rc )
+ goto out_unlock;
set_bit(_VPF_down, &v->pause_flags);
@@ -891,9 +895,13 @@ void vcpu_reset(struct vcpu *v)
#endif
cpumask_clear(v->cpu_affinity_tmp);
clear_bit(_VPF_blocked, &v->pause_flags);
+ clear_bit(_VPF_in_reset, &v->pause_flags);
+ out_unlock:
domain_unlock(v->domain);
vcpu_unpause(v);
+
+ return rc;
}
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 73b12c8a4d..1d00cfc95f 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -332,13 +332,15 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
ret = -EINVAL;
if ( (d == current->domain) || /* no domain_pause() */
(vcpu >= d->max_vcpus) || ((v = d->vcpu[vcpu]) == NULL) )
- goto svc_out;
+ break;
if ( guest_handle_is_null(op->u.vcpucontext.ctxt) )
{
- vcpu_reset(v);
- ret = 0;
- goto svc_out;
+ ret = vcpu_reset(v);
+ if ( ret == -EAGAIN )
+ ret = hypercall_create_continuation(
+ __HYPERVISOR_domctl, "h", u_domctl);
+ break;
}
#ifdef CONFIG_COMPAT
@@ -347,7 +349,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
#endif
ret = -ENOMEM;
if ( (c.nat = alloc_vcpu_guest_context()) == NULL )
- goto svc_out;
+ break;
#ifdef CONFIG_COMPAT
if ( !is_pv_32on64_vcpu(v) )
@@ -368,7 +370,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
domain_unpause(d);
}
- svc_out:
free_vcpu_guest_context(c.nat);
}
break;