[kernel/f15] CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and vcpu->arch.apic inconsistency (rhb

Josh Boyer jwboyer at fedoraproject.org
Fri Mar 30 16:35:30 UTC 2012


commit 77c32d730a254ab9f043ead358f9bab549515c35
Author: Josh Boyer <jwboyer at redhat.com>
Date:   Fri Mar 30 11:08:12 2012 -0400

    CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and
      vcpu->arch.apic inconsistency (rhbz 808207)

 ...all-vcpus-are-consistent-with-in-kernel-i.patch |  106 ++++++++++++++++++++
 kernel.spec                                        |    8 ++
 2 files changed, 114 insertions(+), 0 deletions(-)
---
diff --git a/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch b/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch
new file mode 100644
index 0000000..7e1664f
--- /dev/null
+++ b/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch
@@ -0,0 +1,106 @@
+From 5b40572ed5f0344b9dbee486a17c589ce1abe1a3 Mon Sep 17 00:00:00 2001
+From: Avi Kivity <avi at redhat.com>
+Date: Mon, 5 Mar 2012 14:23:29 +0200
+Subject: [PATCH] KVM: Ensure all vcpus are consistent with in-kernel irqchip
+ settings
+
+If some vcpus are created before KVM_CREATE_IRQCHIP, then
+irqchip_in_kernel() and vcpu->arch.apic will be inconsistent, leading
+to potential NULL pointer dereferences.
+
+Fix by:
+- ensuring that no vcpus are installed when KVM_CREATE_IRQCHIP is called
+- ensuring that a vcpu has an apic if it is installed after KVM_CREATE_IRQCHIP
+
+This is somewhat long winded because vcpu->arch.apic is created without
+kvm->lock held.
+
+Based on earlier patch by Michael Ellerman.
+
+Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
+Signed-off-by: Avi Kivity <avi at redhat.com>
+---
+ arch/ia64/kvm/kvm-ia64.c |    5 +++++
+ arch/x86/kvm/x86.c       |    8 ++++++++
+ include/linux/kvm_host.h |    7 +++++++
+ virt/kvm/kvm_main.c      |    4 ++++
+ 4 files changed, 24 insertions(+), 0 deletions(-)
+
+diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
+index d8ddbba..f5104b7 100644
+--- a/arch/ia64/kvm/kvm-ia64.c
++++ b/arch/ia64/kvm/kvm-ia64.c
+@@ -1172,6 +1172,11 @@ out:
+ 
+ #define PALE_RESET_ENTRY    0x80000000ffffffb0UL
+ 
++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
++{
++	return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL);
++}
++
+ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+ {
+ 	struct kvm_vcpu *v;
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 3ee008f..be9594a 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -3199,6 +3199,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
+ 		r = -EEXIST;
+ 		if (kvm->arch.vpic)
+ 			goto create_irqchip_unlock;
++		r = -EINVAL;
++		if (atomic_read(&kvm->online_vcpus))
++			goto create_irqchip_unlock;
+ 		r = -ENOMEM;
+ 		vpic = kvm_create_pic(kvm);
+ 		if (vpic) {
+@@ -6107,6 +6110,11 @@ void kvm_arch_check_processor_compat(void *rtn)
+ 	kvm_x86_ops->check_processor_compatibility(rtn);
+ }
+ 
++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
++{
++	return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL);
++}
++
+ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+ {
+ 	struct page *page;
+diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
+index 355e445..759fa26 100644
+--- a/include/linux/kvm_host.h
++++ b/include/linux/kvm_host.h
+@@ -805,6 +805,13 @@ static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
+ {
+ 	return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id;
+ }
++
++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu);
++
++#else
++
++static bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; }
++
+ #endif
+ 
+ #ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
+diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
+index e4431ad..94e148e 100644
+--- a/virt/kvm/kvm_main.c
++++ b/virt/kvm/kvm_main.c
+@@ -1651,6 +1651,10 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
+ 		goto vcpu_destroy;
+ 
+ 	mutex_lock(&kvm->lock);
++	if (!kvm_vcpu_compatible(vcpu)) {
++		r = -EINVAL;
++		goto unlock_vcpu_destroy;
++	}
+ 	if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) {
+ 		r = -EINVAL;
+ 		goto unlock_vcpu_destroy;
+-- 
+1.7.7.6
+
diff --git a/kernel.spec b/kernel.spec
index 856b1a6..891b77f 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -733,6 +733,9 @@ Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch
 
 Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch
 
+#rhbz 808207 CVE-2012-1601
+Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch
+
 Patch22000: weird-root-dentry-name-debug.patch
 
 %endif
@@ -1361,6 +1364,9 @@ ApplyPatch SHLIB_BASE-randomization.patch
 
 ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch
 
+#rhbz 808207 CVE-2012-1601
+ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2009,6 +2015,8 @@ fi
 
 %changelog
 * Fri Mar 30 2012 Josh Boyer <jwboyer at redhat.com>
+- CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and
+  vcpu->arch.apic inconsistency (rhbz 808207)
 - Add patch to fix incorrect buffer length in __nfs4_get_acl_uncached
 
 * Thu Mar 29 2012 Josh Boyer <jwboyer at redhat.com>


More information about the scm-commits mailing list