mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
KVM: x86: Don't leave APF half-enabled on bad APF data GPA
kvm_pv_enable_async_pf() updates vcpu->arch.apf.msr_en_val before
initializing the APF data gfn_to_hva cache. If userspace provides an
invalid GPA, kvm_gfn_to_hva_cache_init() fails, but msr_en_val stays
enabled and leaves APF state half-initialized.
Later APF paths can then try to use the empty cache and trigger
WARN_ON() in kvm_read_guest_offset_cached().
Determine the new APF enabled state from the incoming MSR value, do cache
initialization first on the enable path, and commit msr_en_val only after
successful initialization. Keep the disable path behavior unchanged.
Reported-by: syzbot+bc0e18379a290e5edfe4@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=bc0e18379a290e5edfe4
Fixes: 344d9588a9 ("KVM: Add PV MSR to enable asynchronous page faults delivery.")
Link: https://lore.kernel.org/r/aHfD3MczrDpzDX9O@google.com
Suggested-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Signed-off-by: Ethan Yang <ethan.yang.kernel@gmail.com>
[sean: don't bother with a local "enable" variable]
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Link: https://patch.msgid.link/20260406225359.1245490-2-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
b21525756e
commit
923ca078f0
|
|
@ -1043,11 +1043,16 @@ bool kvm_require_dr(struct kvm_vcpu *vcpu, int dr)
|
|||
}
|
||||
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_require_dr);
|
||||
|
||||
static bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
|
||||
static bool __kvm_pv_async_pf_enabled(u64 data)
|
||||
{
|
||||
u64 mask = KVM_ASYNC_PF_ENABLED | KVM_ASYNC_PF_DELIVERY_AS_INT;
|
||||
|
||||
return (vcpu->arch.apf.msr_en_val & mask) == mask;
|
||||
return (data & mask) == mask;
|
||||
}
|
||||
|
||||
static bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return __kvm_pv_async_pf_enabled(vcpu->arch.apf.msr_en_val);
|
||||
}
|
||||
|
||||
static inline u64 pdptr_rsvd_bits(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -3648,18 +3653,19 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
|
|||
if (!lapic_in_kernel(vcpu))
|
||||
return data ? 1 : 0;
|
||||
|
||||
if (__kvm_pv_async_pf_enabled(data) &&
|
||||
kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
|
||||
sizeof(u64)))
|
||||
return 1;
|
||||
|
||||
vcpu->arch.apf.msr_en_val = data;
|
||||
|
||||
if (!kvm_pv_async_pf_enabled(vcpu)) {
|
||||
if (!__kvm_pv_async_pf_enabled(data)) {
|
||||
kvm_clear_async_pf_completion_queue(vcpu);
|
||||
kvm_async_pf_hash_reset(vcpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
|
||||
sizeof(u64)))
|
||||
return 1;
|
||||
|
||||
vcpu->arch.apf.send_always = (data & KVM_ASYNC_PF_SEND_ALWAYS);
|
||||
vcpu->arch.apf.delivery_as_pf_vmexit = data & KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user