diff options
author | Jan Beulich <jbeulich@suse.com> | 2013-05-02 16:34:21 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2013-05-02 16:34:21 +0200 |
commit | 6cdc9be2a5f2a87b4504404fbf648d16d9503c19 (patch) | |
tree | 57244e0df782cc38467cf1045314806967c72ba9 /xen/arch/x86/domain.c | |
parent | 9626d1c1fafe2da5af6e59478c9e9db6d03144df (diff) | |
download | xen-6cdc9be2a5f2a87b4504404fbf648d16d9503c19.tar.gz xen-6cdc9be2a5f2a87b4504404fbf648d16d9503c19.tar.bz2 xen-6cdc9be2a5f2a87b4504404fbf648d16d9503c19.zip |
x86: make vcpu_destroy_pagetables() preemptible
... as it may take significant amounts of time.
The function, being moved to mm.c as the better home for it anyway, and
to avoid having to make a new helper function there non-static, is
given a "preemptible" parameter temporarily (until, in a subsequent
patch, its other caller is also being made capable of dealing with
preemption).
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/arch/x86/domain.c')
-rw-r--r-- | xen/arch/x86/domain.c | 60 |
1 files changed, 4 insertions, 56 deletions
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 3e09f58279..bc1a31f7e6 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -71,8 +71,6 @@ void (*dead_idle) (void) __read_mostly = default_dead_idle; static void paravirt_ctxt_switch_from(struct vcpu *v); static void paravirt_ctxt_switch_to(struct vcpu *v); -static void vcpu_destroy_pagetables(struct vcpu *v); - static void default_idle(void) { local_irq_disable(); @@ -946,7 +944,7 @@ void arch_vcpu_reset(struct vcpu *v) if ( !is_hvm_vcpu(v) ) { destroy_gdt(v); - vcpu_destroy_pagetables(v); + vcpu_destroy_pagetables(v, 0); } else { @@ -1944,58 +1942,6 @@ static int relinquish_memory( return ret; } -static void vcpu_destroy_pagetables(struct vcpu *v) -{ - struct domain *d = v->domain; - unsigned long pfn = pagetable_get_pfn(v->arch.guest_table); - - if ( is_pv_32on64_vcpu(v) ) - { - l4_pgentry_t *l4tab = map_domain_page(pfn); - - pfn = l4e_get_pfn(*l4tab); - - if ( pfn != 0 ) - { - if ( paging_mode_refcounts(d) ) - put_page(mfn_to_page(pfn)); - else - put_page_and_type(mfn_to_page(pfn)); - } - - l4e_write(l4tab, l4e_empty()); - unmap_domain_page(l4tab); - - v->arch.cr3 = 0; - return; - } - - if ( pfn != 0 ) - { - if ( paging_mode_refcounts(d) ) - put_page(mfn_to_page(pfn)); - else - put_page_and_type(mfn_to_page(pfn)); - v->arch.guest_table = pagetable_null(); - } - - /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */ - pfn = pagetable_get_pfn(v->arch.guest_table_user); - if ( pfn != 0 ) - { - if ( !is_pv_32bit_vcpu(v) ) - { - if ( paging_mode_refcounts(d) ) - put_page(mfn_to_page(pfn)); - else - put_page_and_type(mfn_to_page(pfn)); - } - v->arch.guest_table_user = pagetable_null(); - } - - v->arch.cr3 = 0; -} - int domain_relinquish_resources(struct domain *d) { int ret; @@ -2014,7 +1960,9 @@ int domain_relinquish_resources(struct domain *d) /* Drop the in-use references to page-table bases. */ for_each_vcpu ( d, v ) { - vcpu_destroy_pagetables(v); + ret = vcpu_destroy_pagetables(v, 1); + if ( ret ) + return ret; unmap_vcpu_info(v); } |