- remove xen.migrate.tools_notify_restore_to_hangup_during_migration_--abort_if_busy.patch It changed migration protocol and upstream wants a different solution - bnc#802221 - fix xenpaging readd xenpaging.qemu.flush-cache.patch - Upstream patches from Jan 26891-x86-S3-Fix-cpu-pool-scheduling-after-suspend-resume.patch 26930-x86-EFI-fix-runtime-call-status-for-compat-mode-Dom0.patch - Additional fix for bnc#816159 CVE-2013-1918-xsa45-followup.patch - bnc#817068 - Xen guest with >1 sr-iov vf won't start xen-managed-pci-device.patch - Update to Xen 4.2.2 c/s 26064 The following recent security patches are included in the tarball CVE-2013-0151-xsa34.patch (bnc#797285) CVE-2012-6075-xsa41.patch (bnc#797523) CVE-2013-1917-xsa44.patch (bnc#813673) CVE-2013-1919-xsa46.patch (bnc#813675) - Upstream patch from Jan 26902-x86-EFI-pass-boot-services-variable-info-to-runtime-code.patch - bnc#816159 - VUL-0: xen: CVE-2013-1918: XSA-45: Several long latency operations are not preemptible CVE-2013-1918-xsa45-1-vcpu-destroy-pagetables-preemptible.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=237
213 lines
6.7 KiB
Diff
213 lines
6.7 KiB
Diff
x86: make arch_set_info_guest() preemptible
|
|
|
|
.. as the root page table validation (and the dropping of an eventual
|
|
old one) can require meaningful 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>
|
|
|
|
Index: xen-4.2.2-testing/xen/arch/x86/domain.c
|
|
===================================================================
|
|
--- xen-4.2.2-testing.orig/xen/arch/x86/domain.c
|
|
+++ xen-4.2.2-testing/xen/arch/x86/domain.c
|
|
@@ -858,6 +858,9 @@ int arch_set_info_guest(
|
|
|
|
if ( !v->is_initialised )
|
|
{
|
|
+ if ( !compat && !(flags & VGCF_in_kernel) && !c.nat->ctrlreg[1] )
|
|
+ return -EINVAL;
|
|
+
|
|
v->arch.pv_vcpu.ldt_base = c(ldt_base);
|
|
v->arch.pv_vcpu.ldt_ents = c(ldt_ents);
|
|
}
|
|
@@ -955,24 +958,44 @@ int arch_set_info_guest(
|
|
if ( rc != 0 )
|
|
return rc;
|
|
|
|
+ set_bit(_VPF_in_reset, &v->pause_flags);
|
|
+
|
|
if ( !compat )
|
|
- {
|
|
cr3_gfn = xen_cr3_to_pfn(c.nat->ctrlreg[3]);
|
|
- cr3_page = get_page_from_gfn(d, cr3_gfn, NULL, P2M_ALLOC);
|
|
-
|
|
- if ( !cr3_page )
|
|
- {
|
|
- destroy_gdt(v);
|
|
- return -EINVAL;
|
|
- }
|
|
- if ( !paging_mode_refcounts(d)
|
|
- && !get_page_type(cr3_page, PGT_base_page_table) )
|
|
- {
|
|
- put_page(cr3_page);
|
|
- destroy_gdt(v);
|
|
- return -EINVAL;
|
|
- }
|
|
+#ifdef CONFIG_COMPAT
|
|
+ else
|
|
+ cr3_gfn = compat_cr3_to_pfn(c.cmp->ctrlreg[3]);
|
|
+#endif
|
|
+ cr3_page = get_page_from_gfn(d, cr3_gfn, NULL, P2M_ALLOC);
|
|
|
|
+ if ( !cr3_page )
|
|
+ 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_page(cr3_page);
|
|
#ifdef __x86_64__
|
|
if ( c.nat->ctrlreg[1] )
|
|
@@ -980,56 +1003,44 @@ int arch_set_info_guest(
|
|
cr3_gfn = xen_cr3_to_pfn(c.nat->ctrlreg[1]);
|
|
cr3_page = get_page_from_gfn(d, cr3_gfn, NULL, P2M_ALLOC);
|
|
|
|
- if ( !cr3_page ||
|
|
- (!paging_mode_refcounts(d)
|
|
- && !get_page_type(cr3_page, PGT_base_page_table)) )
|
|
+ if ( !cr3_page )
|
|
+ rc = -EINVAL;
|
|
+ else if ( !paging_mode_refcounts(d) )
|
|
{
|
|
- if (cr3_page)
|
|
- put_page(cr3_page);
|
|
- cr3_page = pagetable_get_page(v->arch.guest_table);
|
|
- v->arch.guest_table = pagetable_null();
|
|
- if ( paging_mode_refcounts(d) )
|
|
- put_page(cr3_page);
|
|
- else
|
|
- put_page_and_type(cr3_page);
|
|
- destroy_gdt(v);
|
|
- return -EINVAL;
|
|
+ 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_page(cr3_page);
|
|
- }
|
|
- else if ( !(flags & VGCF_in_kernel) )
|
|
- {
|
|
- destroy_gdt(v);
|
|
- return -EINVAL;
|
|
+ if ( !rc )
|
|
+ v->arch.guest_table_user = pagetable_from_page(cr3_page);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
l4_pgentry_t *l4tab;
|
|
|
|
- cr3_gfn = compat_cr3_to_pfn(c.cmp->ctrlreg[3]);
|
|
- cr3_page = get_page_from_gfn(d, cr3_gfn, NULL, P2M_ALLOC);
|
|
-
|
|
- if ( !cr3_page)
|
|
- {
|
|
- destroy_gdt(v);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if (!paging_mode_refcounts(d)
|
|
- && !get_page_type(cr3_page, PGT_l3_page_table) )
|
|
- {
|
|
- put_page(cr3_page);
|
|
- destroy_gdt(v);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
l4tab = __va(pagetable_get_paddr(v->arch.guest_table));
|
|
*l4tab = l4e_from_pfn(page_to_mfn(cr3_page),
|
|
_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);
|
|
Index: xen-4.2.2-testing/xen/common/compat/domain.c
|
|
===================================================================
|
|
--- xen-4.2.2-testing.orig/xen/common/compat/domain.c
|
|
+++ xen-4.2.2-testing/xen/common/compat/domain.c
|
|
@@ -50,6 +50,10 @@ int compat_vcpu_op(int cmd, int vcpuid,
|
|
rc = v->is_initialised ? -EEXIST : arch_set_info_guest(v, cmp_ctxt);
|
|
domain_unlock(d);
|
|
|
|
+ if ( rc == -EAGAIN )
|
|
+ rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih",
|
|
+ cmd, vcpuid, arg);
|
|
+
|
|
xfree(cmp_ctxt);
|
|
break;
|
|
}
|
|
Index: xen-4.2.2-testing/xen/common/domain.c
|
|
===================================================================
|
|
--- xen-4.2.2-testing.orig/xen/common/domain.c
|
|
+++ xen-4.2.2-testing/xen/common/domain.c
|
|
@@ -849,6 +849,11 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
|
|
domain_unlock(d);
|
|
|
|
free_vcpu_guest_context(ctxt);
|
|
+
|
|
+ if ( rc == -EAGAIN )
|
|
+ rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih",
|
|
+ cmd, vcpuid, arg);
|
|
+
|
|
break;
|
|
|
|
case VCPUOP_up: {
|
|
Index: xen-4.2.2-testing/xen/common/domctl.c
|
|
===================================================================
|
|
--- xen-4.2.2-testing.orig/xen/common/domctl.c
|
|
+++ xen-4.2.2-testing/xen/common/domctl.c
|
|
@@ -339,6 +339,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
|
|
domain_pause(d);
|
|
ret = arch_set_info_guest(v, c);
|
|
domain_unpause(d);
|
|
+
|
|
+ if ( ret == -EAGAIN )
|
|
+ ret = hypercall_create_continuation(
|
|
+ __HYPERVISOR_domctl, "h", u_domctl);
|
|
}
|
|
|
|
svc_out:
|