diff options
Diffstat (limited to 'sysutils/xenkernel41/patches/patch-CVE-2013-1918_11')
-rw-r--r-- | sysutils/xenkernel41/patches/patch-CVE-2013-1918_11 | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/sysutils/xenkernel41/patches/patch-CVE-2013-1918_11 b/sysutils/xenkernel41/patches/patch-CVE-2013-1918_11 new file mode 100644 index 00000000000..2613b5873e5 --- /dev/null +++ b/sysutils/xenkernel41/patches/patch-CVE-2013-1918_11 @@ -0,0 +1,261 @@ +$NetBSD: patch-CVE-2013-1918_11,v 1.1 2013/05/03 16:48:37 drochner Exp $ + +--- xen/arch/x86/domain.c.orig 2013-05-03 13:27:23.000000000 +0000 ++++ xen/arch/x86/domain.c +@@ -70,8 +70,6 @@ void (*dead_idle) (void) __read_mostly = + 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 continue_idle_domain(struct vcpu *v) + { + reset_stack_and_jump(idle_loop); +@@ -678,6 +676,7 @@ int arch_set_info_guest( + { + struct domain *d = v->domain; + unsigned long cr3_pfn = INVALID_MFN; ++ struct page_info *cr3_page; + unsigned long flags, cr4; + int i, rc = 0, compat; + +@@ -817,72 +816,103 @@ int arch_set_info_guest( + if ( rc != 0 ) + return rc; + ++ set_bit(_VPF_in_reset, &v->pause_flags); ++ + if ( !compat ) +- { + cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c.nat->ctrlreg[3])); ++#ifdef __x86_64__ ++ else ++ cr3_pfn = gmfn_to_mfn(d, compat_cr3_to_pfn(c.cmp->ctrlreg[3])); ++#endif ++ cr3_page = mfn_to_page(cr3_pfn); + +- if ( !mfn_valid(cr3_pfn) || +- (paging_mode_refcounts(d) +- ? !get_page(mfn_to_page(cr3_pfn), d) +- : !get_page_and_type(mfn_to_page(cr3_pfn), d, +- PGT_base_page_table)) ) +- { +- destroy_gdt(v); +- return -EINVAL; +- } ++ if ( !mfn_valid(cr3_pfn) || !get_page(cr3_page, d) ) ++ { ++ cr3_page = NULL; ++ rc = -EINVAL; ++ } ++ else if ( paging_mode_refcounts(d) ) ++ /* nothing */; ++ else if ( cr3_page == v->arch.old_guest_table ) ++ { ++ v->arch.old_guest_table = NULL; ++ put_page(cr3_page); ++ } ++ else ++ { ++ /* ++ * Since v->arch.guest_table{,_user} are both NULL, this effectively ++ * is just a call to put_old_guest_table(). ++ */ ++ if ( !compat ) ++ rc = vcpu_destroy_pagetables(v); ++ if ( !rc ) ++ rc = get_page_type_preemptible(cr3_page, ++ !compat ? PGT_root_page_table ++ : PGT_l3_page_table); ++ if ( rc == -EINTR ) ++ rc = -EAGAIN; ++ } + ++ if ( rc ) ++ /* handled below */; ++ else if ( !compat ) ++ { + v->arch.guest_table = pagetable_from_pfn(cr3_pfn); + + #ifdef __x86_64__ + if ( c.nat->ctrlreg[1] ) + { + cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c.nat->ctrlreg[1])); ++ cr3_page = mfn_to_page(cr3_pfn); + +- if ( !mfn_valid(cr3_pfn) || +- (paging_mode_refcounts(d) +- ? !get_page(mfn_to_page(cr3_pfn), d) +- : !get_page_and_type(mfn_to_page(cr3_pfn), d, +- PGT_base_page_table)) ) ++ if ( !mfn_valid(cr3_pfn) || !get_page(cr3_page, d) ) + { +- cr3_pfn = pagetable_get_pfn(v->arch.guest_table); +- v->arch.guest_table = pagetable_null(); +- if ( paging_mode_refcounts(d) ) +- put_page(mfn_to_page(cr3_pfn)); +- else +- put_page_and_type(mfn_to_page(cr3_pfn)); +- destroy_gdt(v); +- return -EINVAL; ++ cr3_page = NULL; ++ rc = -EINVAL; ++ } ++ else if ( !paging_mode_refcounts(d) ) ++ { ++ rc = get_page_type_preemptible(cr3_page, PGT_root_page_table); ++ switch ( rc ) ++ { ++ case -EINTR: ++ rc = -EAGAIN; ++ case -EAGAIN: ++ v->arch.old_guest_table = ++ pagetable_get_page(v->arch.guest_table); ++ v->arch.guest_table = pagetable_null(); ++ break; ++ } + } + +- v->arch.guest_table_user = pagetable_from_pfn(cr3_pfn); ++ if ( !rc ) ++ v->arch.guest_table_user = pagetable_from_pfn(cr3_pfn); + } + else if ( !(flags & VGCF_in_kernel) ) + { +- destroy_gdt(v); +- return -EINVAL; ++ cr3_page = NULL; ++ rc = -EINVAL; + } + } + else + { + l4_pgentry_t *l4tab; + +- cr3_pfn = gmfn_to_mfn(d, compat_cr3_to_pfn(c.cmp->ctrlreg[3])); +- +- if ( !mfn_valid(cr3_pfn) || +- (paging_mode_refcounts(d) +- ? !get_page(mfn_to_page(cr3_pfn), d) +- : !get_page_and_type(mfn_to_page(cr3_pfn), d, +- PGT_l3_page_table)) ) +- { +- destroy_gdt(v); +- return -EINVAL; +- } +- + l4tab = __va(pagetable_get_paddr(v->arch.guest_table)); + *l4tab = l4e_from_pfn( + cr3_pfn, _PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED); + #endif + } ++ if ( rc ) ++ { ++ if ( cr3_page ) ++ put_page(cr3_page); ++ destroy_gdt(v); ++ return rc; ++ } ++ ++ clear_bit(_VPF_in_reset, &v->pause_flags); + + if ( v->vcpu_id == 0 ) + update_domain_wallclock_time(d); +@@ -904,17 +934,16 @@ int arch_set_info_guest( + #undef c + } + +-void arch_vcpu_reset(struct vcpu *v) ++int arch_vcpu_reset(struct vcpu *v) + { + if ( !is_hvm_vcpu(v) ) + { + destroy_gdt(v); +- vcpu_destroy_pagetables(v); +- } +- else +- { +- vcpu_end_shutdown_deferral(v); ++ return vcpu_destroy_pagetables(v); + } ++ ++ vcpu_end_shutdown_deferral(v); ++ return 0; + } + + /* +@@ -1917,63 +1946,6 @@ static int relinquish_memory( + return ret; + } + +-static void vcpu_destroy_pagetables(struct vcpu *v) +-{ +- struct domain *d = v->domain; +- unsigned long pfn; +- +-#ifdef __x86_64__ +- if ( is_pv_32on64_vcpu(v) ) +- { +- pfn = l4e_get_pfn(*(l4_pgentry_t *) +- __va(pagetable_get_paddr(v->arch.guest_table))); +- +- 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( +- (l4_pgentry_t *)__va(pagetable_get_paddr(v->arch.guest_table)), +- l4e_empty()); +- +- v->arch.cr3 = 0; +- return; +- } +-#endif +- +- pfn = pagetable_get_pfn(v->arch.guest_table); +- 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(); +- } +- +-#ifdef __x86_64__ +- /* 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(); +- } +-#endif +- +- v->arch.cr3 = 0; +-} +- + int domain_relinquish_resources(struct domain *d) + { + int ret; +@@ -1992,7 +1964,9 @@ int domain_relinquish_resources(struct d + for_each_vcpu ( d, v ) + { + /* Drop the in-use references to page-table bases. */ +- vcpu_destroy_pagetables(v); ++ ret = vcpu_destroy_pagetables(v); ++ if ( ret ) ++ return ret; + + /* + * Relinquish GDT mappings. No need for explicit unmapping of the |