From: Sean Christopherson <seanjc@google.com>
To: sashiko-reviews@lists.linux.dev
Cc: Yosry Ahmed <yosry@kernel.org>, kvm@vger.kernel.org
Subject: Re: [PATCH v7 08/17] KVM: x86/pmu: Check mediated PMU counter enablement before event filters
Date: Fri, 29 May 2026 17:35:00 -0700 [thread overview]
Message-ID: <ahowtCCtnr9t5DGy@google.com> (raw)
In-Reply-To: <20260528005419.0228F1F00A3A@smtp.kernel.org>
On Thu, May 28, 2026, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] Guest can bypass PMU event filters for fixed counters by modifying MSR_CORE_PERF_FIXED_CTR_CTRL.
> --
>
> commit 270fc772a7eb457f31ead154a0c426817961ae8a
> Author: Yosry Ahmed <yosry@kernel.org>
>
> KVM: x86/pmu: Check mediated PMU counter enablement before event filters
>
> This commit checks if a PMU counter is enabled by the guest before performing
> the potentially expensive PMU event filter lookup. It modifies
> kvm_mediated_pmu_refresh_event_filter to use pmc_is_locally_enabled.
>
> > diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> > index afbc731e72174..67dbbd4c73036 100644
> > --- a/arch/x86/kvm/pmu.c
> > +++ b/arch/x86/kvm/pmu.c
> > @@ -532,7 +532,7 @@ static bool pmc_is_event_allowed(struct kvm_pmc *pmc)
> >
> > static void kvm_mediated_pmu_refresh_event_filter(struct kvm_pmc *pmc)
> > {
> > - bool allowed = pmc_is_event_allowed(pmc);
> > + bool allowed = pmc_is_locally_enabled(pmc) && pmc_is_event_allowed(pmc);
>
> [Severity: High]
> This is a pre-existing issue, but was it intended for guests to be able to
> bypass PMU event filters for fixed counters by writing to the MSR twice?
>
> Looking at reprogram_fixed_counters() in arch/x86/kvm/vmx/pmu_intel.c,
> pmu->fixed_ctr_ctrl_hw is unconditionally overwritten with raw guest data
> before checking which counters changed:
>
> arch/x86/kvm/vmx/pmu_intel.c:reprogram_fixed_counters() {
> ...
> pmu->fixed_ctr_ctrl = data;
> pmu->fixed_ctr_ctrl_hw = data;
> for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
> u8 new_ctrl = fixed_ctrl_field(data, i);
> u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i);
>
> if (old_ctrl == new_ctrl)
> continue;
> ...
> kvm_pmu_request_counter_reprogram(pmc);
> }
> }
>
> Because kvm_pmu_request_counter_reprogram() is skipped when the counter's
> control bits haven't changed, kvm_mediated_pmu_refresh_event_filter() is
> never called to apply the filter mask.
>
> Could a guest enable a rejected counter (which gets correctly filtered and
> cleared in fixed_ctr_ctrl_hw by the first write), and then write the MSR a
> second time to enable a different counter while leaving the rejected
> counter's bits set?
>
> The second write would inject the unfiltered enable bits into
> fixed_ctr_ctrl_hw, and since the software state (old_ctrl == new_ctrl)
> matches, KVM skips reprogramming it. Does this allow the rejected counter to
> remain enabled in hardware upon the next VM-enter, completely bypassing the
> event filters?
Hrm, does look like that's the case. If the guest toggles a different PMC, KVM
will update pmu->fixed_ctr_ctrl_hw and reprogram the PMC that is changing, but
not the others that are enabled in pmu->fixed_ctr_ctrl_hw.
Aha! I think this is quite easy to fix: use fixed_ctr_ctrl_hw as the basis for
the diff. For the perf-based PMU, fixed_ctr_ctrl_hw == fixed_ctr_ctrl at all
times. For the mediated PMU, "reprogramming" means changes the values that are
loaded into hardware, and so unless I'm missing something, this? I'll test and
send a patch next week.
idiff --git arch/x86/kvm/vmx/pmu_intel.c arch/x86/kvm/vmx/pmu_intel.c
index 453cb3d3ec9b..a73a9515d96c 100644
--- arch/x86/kvm/vmx/pmu_intel.c
+++ arch/x86/kvm/vmx/pmu_intel.c
@@ -56,8 +56,16 @@ static struct x86_pmu_lbr *vcpu_to_lbr_records(struct kvm_vcpu *vcpu)
static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
{
+ /*
+ * Compare against the value the mediated PMU shoves into hardware, not
+ * the guest's desired value. For the emulated PMU (proxied via perf),
+ * they are one and the same (fixed_ctr_ctrl_hw isn't used other than
+ * here). For the mediated PMU, KVM needs to reprogram the actual MSR,
+ * and so needs to react to potential changes in the value shoved into
+ * hardware, e.g. to ensure the event filter is enforced.
+ */
+ u64 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl_hw;
struct kvm_pmc *pmc;
- u64 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl;
int i;
pmu->fixed_ctr_ctrl = data;
Note, general purpose counters (thankfully) don't have the same bug.
if (data != pmc->eventsel) {
pmc->eventsel = data;
pmc->eventsel_hw = data;
kvm_pmu_request_counter_reprogram(pmc);
}
Oh, and for posterity, using fixed_ctr_ctrl_hw won't mess up pmc_in_use, because
it's unused by the mediated PMU. It's purpose is solely for releasing perf events
that are no longer being actively used. It's a bit hard to see, but need_cleanup
will never be set for the mediated PMU, because pmu->event_count will always be
zero.
if (vcpu->scheduled_out && pmu->version && pmu->event_count) {
pmu->need_cleanup = true;
kvm_make_request(KVM_REQ_PMU, vcpu);
}
To make that more obvious, I think it makes sense to add
static inline void __kvm_pmu_mark_pmc_in_use(struct kvm_vcpu *vcpu, u8 idx)
{
if (kvm_vcpu_has_mediated_pmu(vcpu))
return;
__set_bit(idx, vcpu_to_pmu(vcpu)->pmc_in_use);
}
and then use that everywhere, and WARN if kvm_pmu_cleanup() is ever called with
a mediated PMU.
next prev parent reply other threads:[~2026-05-30 0:35 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-27 23:46 [PATCH v7 00/17] KVM: x86/pmu: Add support for AMD Host-Only/Guest-Only bits Yosry Ahmed
2026-05-27 23:46 ` [PATCH v7 01/17] KVM: nSVM: Stop leaking single-stepping on VMRUN into L2 Yosry Ahmed
2026-05-27 23:46 ` [PATCH v7 02/17] KVM: nSVM: Bail early out of VMRUN emulation if advancing RIP fails Yosry Ahmed
2026-05-27 23:46 ` [PATCH v7 03/17] KVM: nSVM: Unify RIP and PMU handling calls when emulating VMRUN Yosry Ahmed
2026-05-27 23:46 ` [PATCH v7 04/17] KVM: nSVM: Move VMRUN instruction retirement after entering guest mode Yosry Ahmed
2026-05-27 23:46 ` [PATCH v7 05/17] KVM: x86: Move enable_pmu/enable_mediated_pmu to pmu.h and pmu.c Yosry Ahmed
2026-05-27 23:47 ` [PATCH v7 06/17] KVM: x86/pmu: Rename reprogram_counters() to clarify usage Yosry Ahmed
2026-05-27 23:47 ` [PATCH v7 07/17] KVM: x86/pmu: Do a single atomic OR when reprogramming counters Yosry Ahmed
2026-05-27 23:47 ` [PATCH v7 08/17] KVM: x86/pmu: Check mediated PMU counter enablement before event filters Yosry Ahmed
2026-05-28 0:54 ` sashiko-bot
2026-05-30 0:35 ` Sean Christopherson [this message]
2026-05-27 23:47 ` [PATCH v7 09/17] KVM: x86/pmu: Add support for KVM_X86_PMU_OP_OPTIONAL_RET0 Yosry Ahmed
2026-05-27 23:47 ` [PATCH v7 10/17] KVM: x86/pmu: Disable counters based on Host-Only/Guest-Only bits in SVM Yosry Ahmed
2026-05-28 0:34 ` sashiko-bot
2026-05-28 1:43 ` Sean Christopherson
2026-05-27 23:47 ` [PATCH v7 11/17] KVM: x86/pmu: Track mediated PMU counters with mode-specific enables Yosry Ahmed
2026-05-28 0:45 ` sashiko-bot
2026-05-27 23:47 ` [PATCH v7 12/17] KVM: x86/pmu: Reprogram Host/Guest-Only counters on nested transitions Yosry Ahmed
2026-05-27 23:47 ` [PATCH v7 13/17] KVM: x86/pmu: Allow Host-Only/Guest-Only bits with nSVM and mediated PMU Yosry Ahmed
2026-05-27 23:47 ` [PATCH v7 14/17] KVM: selftests: Refactor allocating guest stack into a helper Yosry Ahmed
2026-05-27 23:47 ` [PATCH v7 15/17] KVM: selftests: Allocate a dedicated guest page for x86 L2 guest stack Yosry Ahmed
2026-05-28 2:56 ` Sean Christopherson
2026-05-28 17:58 ` Yosry Ahmed
2026-05-28 18:01 ` Sean Christopherson
2026-05-28 18:03 ` Yosry Ahmed
2026-05-27 23:47 ` [PATCH v7 16/17] KVM: selftests: Drop L1-provided stacks for L2 guests on x86 Yosry Ahmed
2026-05-27 23:47 ` [PATCH v7 17/17] KVM: selftests: Add svm_pmu_host_guest_test for Host-Only/Guest-Only bits Yosry Ahmed
2026-05-28 2:25 ` Sean Christopherson
2026-05-28 18:01 ` Yosry Ahmed
2026-05-28 18:04 ` Sean Christopherson
2026-05-28 18:15 ` Jim Mattson
2026-05-28 2:27 ` [PATCH v7 00/17] KVM: x86/pmu: Add support for AMD " Sean Christopherson
2026-05-28 18:02 ` Yosry Ahmed
2026-05-28 18:05 ` Sean Christopherson
2026-05-28 8:30 ` Mi, Dapeng
2026-05-28 18:01 ` Yosry Ahmed
2026-05-29 22:47 ` 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=ahowtCCtnr9t5DGy@google.com \
--to=seanjc@google.com \
--cc=kvm@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=yosry@kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox