head 1.2; access; symbols pkgsrc-2013Q2:1.1.0.2 pkgsrc-2013Q2-base:1.1; locks; strict; comment @# @; 1.2 date 2013.09.11.18.00.33; author drochner; state dead; branches; next 1.1; commitid 76aqq1Rgu8ITY25x; 1.1 date 2013.05.03.16.48.37; author drochner; state Exp; branches; next ; desc @@ 1.2 log @update to 4.1.6.1 This release fixes the following critical vulnerabilities: CVE-2013-1918 / XSA-45: Several long latency operations are not preemptible CVE-2013-1952 / XSA-49: VT-d interrupt remapping source validation flaw for bridges CVE-2013-2076 / XSA-52: Information leak on XSAVE/XRSTOR capable AMD CPUs CVE-2013-2077 / XSA-53: Hypervisor crash due to missing exception recovery on XRSTOR CVE-2013-2078 / XSA-54: Hypervisor crash due to missing exception recovery on XSETBV CVE-2013-2194, CVE-2013-2195, CVE-2013-2196 / XSA-55: Multiple vulnerabilities in libelf PV kernel handling CVE-2013-2072 / XSA-56: Buffer overflow in xencontrol Python bindings affecting xend CVE-2013-2211 / XSA-57: libxl allows guest write access to sensitive console related xenstore keys CVE-2013-1432 / XSA-58: Page reference counting error due to XSA-45/CVE-2013-1918 fixes XSA-61: libxl partially sets up HVM passthrough even with disabled iommu This release contains many bug fixes and improvements. The highlights are: addressing a regression from the fix for XSA-21 addressing a regression from the fix for XSA-46 bug fixes to low level system state handling, including certain hardware errata workarounds (CVE-2013-1918 and CVE-2013-1952 were patched in pkgsrc before) @ text @$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 @ 1.1 log @update to 4.1.5 This integrates fixes for all vulnerabilities which were patched in pkgsrc before. Among many bug fixes and improvements (around 50 since Xen 4.1.4): * ACPI APEI/ERST finally working on production systems * Bug fixes for other low level system state handling * Support for xz compressed Dom0 and DomU kernels @ text @d1 1 a1 1 $NetBSD$ @