CVE-2022-49882
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
01/05/2025
Last modified:
02/05/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
KVM: Reject attempts to consume or refresh inactive gfn_to_pfn_cache<br />
<br />
Reject kvm_gpc_check() and kvm_gpc_refresh() if the cache is inactive.<br />
Not checking the active flag during refresh is particularly egregious, as<br />
KVM can end up with a valid, inactive cache, which can lead to a variety<br />
of use-after-free bugs, e.g. consuming a NULL kernel pointer or missing<br />
an mmu_notifier invalidation due to the cache not being on the list of<br />
gfns to invalidate.<br />
<br />
Note, "active" needs to be set if and only if the cache is on the list<br />
of caches, i.e. is reachable via mmu_notifier events. If a relevant<br />
mmu_notifier event occurs while the cache is "active" but not on the<br />
list, KVM will not acquire the cache&#39;s lock and so will not serailize<br />
the mmu_notifier event with active users and/or kvm_gpc_refresh().<br />
<br />
A race between KVM_XEN_ATTR_TYPE_SHARED_INFO and KVM_XEN_HVM_EVTCHN_SEND<br />
can be exploited to trigger the bug.<br />
<br />
1. Deactivate shinfo cache:<br />
<br />
kvm_xen_hvm_set_attr<br />
case KVM_XEN_ATTR_TYPE_SHARED_INFO<br />
kvm_gpc_deactivate<br />
kvm_gpc_unmap<br />
gpc->valid = false<br />
gpc->khva = NULL<br />
gpc->active = false<br />
<br />
Result: active = false, valid = false<br />
<br />
2. Cause cache refresh:<br />
<br />
kvm_arch_vm_ioctl<br />
case KVM_XEN_HVM_EVTCHN_SEND<br />
kvm_xen_hvm_evtchn_send<br />
kvm_xen_set_evtchn<br />
kvm_xen_set_evtchn_fast<br />
kvm_gpc_check<br />
return -EWOULDBLOCK because !gpc->valid<br />
kvm_xen_set_evtchn_fast<br />
return -EWOULDBLOCK<br />
kvm_gpc_refresh<br />
hva_to_pfn_retry<br />
gpc->valid = true<br />
gpc->khva = not NULL<br />
<br />
Result: active = false, valid = true<br />
<br />
3. Race ioctl KVM_XEN_HVM_EVTCHN_SEND against ioctl<br />
KVM_XEN_ATTR_TYPE_SHARED_INFO:<br />
<br />
kvm_arch_vm_ioctl<br />
case KVM_XEN_HVM_EVTCHN_SEND<br />
kvm_xen_hvm_evtchn_send<br />
kvm_xen_set_evtchn<br />
kvm_xen_set_evtchn_fast<br />
read_lock gpc->lock<br />
kvm_xen_hvm_set_attr case<br />
KVM_XEN_ATTR_TYPE_SHARED_INFO<br />
mutex_lock kvm->lock<br />
kvm_xen_shared_info_init<br />
kvm_gpc_activate<br />
gpc->khva = NULL<br />
kvm_gpc_check<br />
[ Check passes because gpc->valid is<br />
still true, even though gpc->khva<br />
is already NULL. ]<br />
shinfo = gpc->khva<br />
pending_bits = shinfo->evtchn_pending<br />
CRASH: test_and_set_bit(..., pending_bits)