summaryrefslogtreecommitdiff
path: root/sysutils/xenkernel41/patches/patch-CVE-2013-1918_11
diff options
context:
space:
mode:
Diffstat (limited to 'sysutils/xenkernel41/patches/patch-CVE-2013-1918_11')
-rw-r--r--sysutils/xenkernel41/patches/patch-CVE-2013-1918_11261
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