In ksm_msr_allowed() we read "count" out of the SRCU read section, this may cause access to corrupted bitmap in ksm_msr_allowed() due to kfree() by kvm_clear_msr_filter() in very small ratio. We can fix this by reading "count" value in the SRCU read section. The big comment block below shows detail of this issue: ===== Details ===== bool kvm_msr_allowed(struct kvm_vcpu *vcpu, u32 index, u32 type) { struct kvm *kvm = vcpu->kvm; struct msr_bitmap_range *ranges = kvm->arch.msr_filter.ranges; u32 count = kvm->arch.msr_filter.count; /* Schedule out happenes at this point, but before the kvm_clear_msr_filter() run "kvm->arch.msr_filter.count = 0;" on another CPU, so we get the "old" count value which should be > 0 if QEMU already set the MSR filter before. */ u32 i; bool r = kvm->arch.msr_filter.default_allow; int idx; /* MSR filtering not set up or x2APIC enabled, allow everything */ if (!count || (index >= 0x800 && index <= 0x8ff)) return true; /* Schedule in at this point later, now it has very small ratio that the kvm_clear_msr_filter() run on another CPU is doing "kfree(ranges[i].bitmap)" due to no exist srcu read sections of kvm->srcu, then the below code will access to a currupted(kfreed) bitmap, we already got count > 0 before. */ /* Prevent collision with set_msr_filter */ idx = srcu_read_lock(&kvm->srcu); for (i = 0; i < count; i++) { u32 start = ranges[i].base; u32 end = start + ranges[i].nmsrs; u32 flags = ranges[i].flags; unsigned long *bitmap = ranges[i].bitmap; if ((index >= start) && (index < end) && (flags & type)) { r = !!test_bit(index - start, bitmap); break; } } srcu_read_unlock(&kvm->srcu, idx); return r; } --- arch/x86/kvm/x86.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 46b0e52671bb..d6bc1b858167 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1528,18 +1528,22 @@ bool kvm_msr_allowed(struct kvm_vcpu *vcpu, u32 index, u32 type) { struct kvm *kvm = vcpu->kvm; struct msr_bitmap_range *ranges = kvm->arch.msr_filter.ranges; - u32 count = kvm->arch.msr_filter.count; + u32 count; u32 i; bool r = kvm->arch.msr_filter.default_allow; int idx; /* MSR filtering not set up or x2APIC enabled, allow everything */ - if (!count || (index >= 0x800 && index <= 0x8ff)) + if (index >= 0x800 && index <= 0x8ff) return true; /* Prevent collision with set_msr_filter */ idx = srcu_read_lock(&kvm->srcu); + count = kvm->arch.msr_filter.count; + if (!count) + r = true; + for (i = 0; i < count; i++) { u32 start = ranges[i].base; u32 end = start + ranges[i].nmsrs; -- 2.30.1