From: Sean Christopherson <seanjc@google.com>
To: xuanqingshi <1356292400@qq.com>
Cc: pbonzini@redhat.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] KVM: VMX: Use _safe MSR accessors in LBR handler
Date: Tue, 26 May 2026 11:56:26 -0700 [thread overview]
Message-ID: <ahXs2mVqtahs7iG7@google.com> (raw)
In-Reply-To: <tencent_744B87186CA59CFD106992329A6510F7F60A@qq.com>
On Wed, May 27, 2026, xuanqingshi wrote:
> From: Xuanqing Shi <1356292400@qq.com>
>
> intel_pmu_handle_lbr_msrs_access() uses rdmsrq()/wrmsrq() to directly
> access LBR-related MSRs on the physical CPU. If the guest provides an
> out-of-range or otherwise invalid MSR index,
The fault isn't due to an invalid index, it's due to setting reserved bits.
> the unchecked access
> triggers a #GP fault, resulting in an "unchecked MSR access error"
> warning and a host crash when panic_on_warn is enabled.
>
> The crash was observed in a nested virtualization setup where a
> VMCS-targeted fuzzer triggered
Please stop describing this as a fuzzer. Pulling in information from an off-list
discussion:
: The fuzzer works by patching the L1 KVM exit dispatch path via a kernel
: module. Before KVM dispatches to the handler, the module replaces the
: EXIT_REASON field in the VMCS with a target value (e.g.,
: EXIT_REASON_TPR_BELOW_THRESHOLD). The L1 vCPU was created without calling
: KVM_CREATE_IRQCHIP, so vcpu->arch.apic is NULL. When the injected exit reason
: steers execution into the TPR handler, the NULL dereference occurs.
That's not a fuzzer, that's "fault" injection, where even that doesn't match the
kernel's typical terminology for "fault injection". Kernel usage of "fault
injection" is to inject _legitimate_ faults in paths where a "fault" is unlikely
to occur inpractice, e.g. an -ENOMEM due to OOM on an order-0 allocation.
The faults being injected here _can't_ happen absent a buggy (virtual) CPU. And
if the (virtual) CPU is buggy, we _want_ the WARNs.
That's not relevant to this bug though, this is a pretty straightforward KVM goof.
> a WRMSR to MSR 0x1c8 (LBR_SELECT) that propagated through the PMU emulation
> path to the physical host:
>
> unchecked MSR access error: WRMSR to 0x1c8
> (tried to write 0x0000000000004000)
^^^^
|
-- This is the culprit.
E.g. it's trivially easy to reproduce with:
diff --git tools/testing/selftests/kvm/x86/vmx_pmu_caps_test.c tools/testing/selftests/kvm/x86/vmx_pmu_caps_test.c
index d004108dbdc6..9e9362e1a0a5 100644
--- tools/testing/selftests/kvm/x86/vmx_pmu_caps_test.c
+++ tools/testing/selftests/kvm/x86/vmx_pmu_caps_test.c
@@ -201,6 +201,7 @@ KVM_ONE_VCPU_TEST(vmx_pmu_caps, lbr_perf_capabilities, guest_code)
vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
vcpu_set_msr(vcpu, MSR_LBR_TOS, 7);
+ vcpu_set_msr(vcpu, MSR_LBR_SELECT, 0x4000);
vcpu_clear_cpuid_entry(vcpu, X86_PROPERTY_PMU_VERSION.function);
> Call Trace:
> ? native_write_msr+0x4/0x30
> ? intel_pmu_handle_lbr_msrs_access+0xff/0x120 [kvm_intel]
> intel_pmu_set_msr+0x4e0/0x7f0 [kvm_intel]
> kvm_pmu_set_msr+0x17e/0x1c0 [kvm]
> kvm_set_msr_common+0xc76/0x1440 [kvm]
> vmx_set_msr+0x5e6/0x1570 [kvm_intel]
> kvm_emulate_wrmsr+0x54/0x1d0 [kvm]
> vmx_handle_exit+0x7fc/0x970 [kvm_intel]
>
> Replace rdmsrq()/wrmsrq() with their _safe variants so that invalid
> MSR accesses are caught gracefully and reported back to the guest as
> errors instead of crashing the host.
>
> Found by a VMCS-targeted fuzzer based on syzkaller.
>
> Fixes: 1b5ac3226a1a ("KVM: vmx/pmu: Pass-through LBR msrs when the guest LBR event is ACTIVE")
> Signed-off-by: Xuanqing Shi <1356292400@qq.com>
> ---
> arch/x86/kvm/vmx/pmu_intel.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
> index 27eb76e6b6a0..94d2cbffcff4 100644
> --- a/arch/x86/kvm/vmx/pmu_intel.c
> +++ b/arch/x86/kvm/vmx/pmu_intel.c
> @@ -293,6 +293,7 @@ static bool intel_pmu_handle_lbr_msrs_access(struct kvm_vcpu *vcpu,
> {
> struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu);
> u32 index = msr_info->index;
> + int err;
>
> if (!intel_pmu_is_valid_lbr_msr(vcpu, index))
> return false;
> @@ -309,12 +310,12 @@ static bool intel_pmu_handle_lbr_msrs_access(struct kvm_vcpu *vcpu,
> local_irq_disable();
> if (lbr_desc->event->state == PERF_EVENT_STATE_ACTIVE) {
> if (read)
> - rdmsrq(index, msr_info->data);
> + err = rdmsrq_safe(index, &msr_info->data);
> else
> - wrmsrq(index, msr_info->data);
> + err = wrmsrq_safe(index, msr_info->data);
I don't love throwing a value at hardware to see what sticks, but given that KVM
disables interception of these MSRs, it's not like there's a better option.
No need for a v2, I'll rewrite the changelog when applying.
next prev parent reply other threads:[~2026-05-26 18:56 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-26 17:44 [PATCH] KVM: VMX: Use _safe MSR accessors in LBR handler xuanqingshi
2026-05-26 18:56 ` Sean Christopherson [this message]
2026-05-26 22:12 ` Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ahXs2mVqtahs7iG7@google.com \
--to=seanjc@google.com \
--cc=1356292400@qq.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.