diff options
author | Jan Beulich <jbeulich@suse.com> | 2013-05-02 16:37:24 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2013-05-02 16:37:24 +0200 |
commit | 4939f9a6dee4280f38730fd3066e5dce353112f6 (patch) | |
tree | f7fc6fa0c8f7b1261706f24a15c6ee9e58534440 /xen/common | |
parent | 918a5f17b447072b40780f4d03a3adc99ff0073b (diff) | |
download | xen-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.c | 12 | ||||
-rw-r--r-- | xen/common/domctl.c | 13 |
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; |