oss-sec mailing list archives
Re: CVE-2021-4095: kernel: KVM: NULL pointer dereference in kvm_dirty_ring_get() in virt/kvm/dirty_ring.c
From: butt3rflyh4ck <butterflyhuangxx () gmail com>
Date: Mon, 17 Jan 2022 12:33:54 +0800
The patch for this issue is available upstream now. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=55749769fe608fa3f4a075e42e89d237c8e37637 Regards, butt3rflyh4ck. On Tue, Dec 14, 2021 at 11:26 PM butt3rflyh4ck <butterflyhuangxx () gmail com> wrote:
Hi, there was a null-ptr-deref bug in kvm_dirty_ring_get in virt/kvm/dirty_ring.c and I reproduced it on 5.15.0-rc5+. #Root Cause When dirty ring logging is enabled, any dirty logging without an active vCPU context will cause a kernel oops via a KVM KVM_XEN_HVM_SET_ATTR ioctl. we can call KVM_XEN_HVM_SET_ATTR ioctl and it would invoke kvm_xen_hvm_set_attr(), it would call mark_page_dirty_in_slot(). Call chains is like this: KVM_XEN_HVM_SET_ATTR ioctl --->kvm_xen_hvm_set_attr --->kvm_write_wall_clock --->kvm_write_guest -->__kvm_write_guest_page --->mark_page_dirty_in_slot mark_page_dirty_in_slot(). if kvm->dirty_ring_size is sat. ``` void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot, gfn_t gfn) { if (memslot && kvm_slot_dirty_track_enabled(memslot)) { unsigned long rel_gfn = gfn - memslot->base_gfn; u32 slot = (memslot->as_id << 16) | memslot->id; if (kvm->dirty_ring_size) kvm_dirty_ring_push(kvm_dirty_ring_get(kvm), slot, rel_gfn); else set_bit_le(rel_gfn, memslot->dirty_bitmap); } } ``` mark_page_dirty_in_slot() would call kvm_dirty_ring_push() to push a dirty-page to dirty ring then kvm_dirty_ring_get() would get vcpu->dirty_ring. kvm_dirty_ring_get() ``` struct kvm_dirty_ring *kvm_dirty_ring_get(struct kvm *kvm) { struct kvm_vcpu *vcpu = kvm_get_running_vcpu(); //-------> invoke kvm_get_running_vcpu() to get a vcpu. WARN_ON_ONCE(vcpu->kvm != kvm); [1] return &vcpu->dirty_ring; } ``` If vCPU stat did not work, kvm_get_running_vcpu() would get a NULL vcpu pointer . #Details Analyze and some discussion on this issue. https://lore.kernel.org/kvm/CAFcO6XOmoS7EacN_n6v4Txk7xL7iqRa2gABg3F7E3Naf5uG94g () mail gmail com/ #Fix The patch for this issue, not available upstream now. https://patchwork.kernel.org/project/kvm/patch/20211121125451.9489-12-dwmw2 () infradead org/ #CVE Red Hat has assigned CVE-2021-4095 to this issue. https://access.redhat.com/security/cve/CVE-2021-4095 https://bugzilla.redhat.com/show_bug.cgi?id=2031194 #Cedit Active Defense Lab of Venustech. Regards, butt3rflyh4ck. -- Active Defense Lab of Venustech
-- Active Defense Lab of Venustech
Current thread:
- Re: CVE-2021-4095: kernel: KVM: NULL pointer dereference in kvm_dirty_ring_get() in virt/kvm/dirty_ring.c butt3rflyh4ck (Jan 16)