From: Sean Christopherson <seanjc@google.com>
To: Marco Elver <elver@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
Vitaly Kuznetsov <vkuznets@redhat.com>,
Kiryl Shutsemau <kas@kernel.org>,
Rick Edgecombe <rick.p.edgecombe@intel.com>,
David Hildenbrand <david@kernel.org>,
kvm@vger.kernel.org, linux-coco@lists.linux.dev,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH RFC 01/10] KVM: x86/pmu: Acquire SRCU in pmc_is_event_allowed() to protect filter lookup
Date: Thu, 10 Sep 2026 09:46:32 -0700 [thread overview]
Message-ID: <aqLe6FcPZIgj2RA6@google.com> (raw)
In-Reply-To: <20260910162343.4092060-2-elver@google.com>
On Thu, Sep 10, 2026, Marco Elver wrote:
> Dereferencing kvm->arch.pmu_event_filter via srcu_dereference() requires
> holding kvm->srcu to guard against concurrent filter replacement and
> freeing by kvm_vm_ioctl_set_pmu_event_filter().
>
> Counter reprogramming can reach pmc_is_event_allowed() without holding
> kvm->srcu. Specifically, on AMD SVM, toggling EFER.SVME via KVM_SET_SREGS
> or KVM_SET_SREGS2 triggers synchronous counter reprogramming outside of
> any SRCU read-side critical section:
>
> kvm_vcpu_ioctl(KVM_SET_SREGS{,2})
> kvm_vcpu_ioctl_x86_set_sregs{,2}()
> __set_sregs_common()
> kvm_x86_call(set_efer)()
> svm_set_efer()
> svm_pmu_handle_nested_transition()
> __svm_pmu_handle_nested_transition(..., defer=false)
> __kvm_pmu_reprogram_counters()
> kvm_pmu_handle_event()
> reprogram_counter()
> pmc_is_event_allowed()
> srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu)
>
> If userspace concurrently updates the filter (KVM_SET_PMU_EVENT_FILTER),
> a concurrent free and subsequent use-after-free is possible.
>
> Protect filter lookups directly in pmc_is_event_allowed():
> 1. check rcu_access_pointer() first for the common fast path;
> 2. acquire guard(srcu)(&kvm->srcu) only when a filter is present;
> 3. drop redundant outer srcu_read_lock() in kvm_pmu_trigger_event().
>
> Found with Clang context analysis.
>
> Fixes: a02a25a65246 ("KVM: x86/pmu: Reprogram Host/Guest-Only counters on nested transitions")
> Signed-off-by: Marco Elver <elver@google.com>
> ---
> arch/x86/kvm/pmu.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> index a7d60c8785cd..3ad1e696edca 100644
> --- a/arch/x86/kvm/pmu.c
> +++ b/arch/x86/kvm/pmu.c
> @@ -536,6 +536,11 @@ static bool pmc_is_event_allowed(struct kvm_pmc *pmc)
> struct kvm_x86_pmu_event_filter *filter;
> struct kvm *kvm = pmc->vcpu->kvm;
>
> + if (!rcu_access_pointer(kvm->arch.pmu_event_filter))
> + return true;
> +
> + guard(srcu)(&kvm->srcu);
> +
> filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
> if (!filter)
> return true;
> @@ -1132,7 +1137,7 @@ static void kvm_pmu_trigger_event(struct kvm_vcpu *vcpu,
> DECLARE_BITMAP(bitmap, X86_PMC_IDX_MAX);
> struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
> struct kvm_pmc *pmc;
> - int i, idx;
> + int i;
>
> BUILD_BUG_ON(sizeof(pmu->global_ctrl) * BITS_PER_BYTE != X86_PMC_IDX_MAX);
>
> @@ -1145,14 +1150,12 @@ static void kvm_pmu_trigger_event(struct kvm_vcpu *vcpu,
> (unsigned long *)&pmu->global_ctrl, X86_PMC_IDX_MAX))
> return;
>
> - idx = srcu_read_lock(&vcpu->kvm->srcu);
> kvm_for_each_pmc(pmu, pmc, i, bitmap) {
> if (!pmc_is_event_allowed(pmc) || !cpl_is_matched(pmc))
> continue;
>
> kvm_pmu_incr_counter(pmc);
> }
> - srcu_read_unlock(&vcpu->kvm->srcu, idx);
> }
I would very strongly prefer to fix this in __set_sregs_common():
diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c
index 8f66438989e4..2ce16e96d796 100644
--- a/arch/x86/kvm/regs.c
+++ b/arch/x86/kvm/regs.c
@@ -571,9 +571,10 @@ static bool kvm_is_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
int *mmu_reset_needed, bool update_pdptrs)
{
- int idx;
struct desc_ptr dt;
+ guard(srcu)(&vcpu->kvm->srcu);
+
if (!kvm_is_valid_sregs(vcpu, sregs))
return -EINVAL;
@@ -605,13 +606,9 @@ static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
*mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;
kvm_x86_call(set_cr4)(vcpu, sregs->cr4);
- if (update_pdptrs) {
- idx = srcu_read_lock(&vcpu->kvm->srcu);
- if (is_pae_paging(vcpu)) {
- load_pdptrs(vcpu, kvm_read_cr3(vcpu));
- *mmu_reset_needed = 1;
- }
- srcu_read_unlock(&vcpu->kvm->srcu, idx);
+ if (update_pdptrs && is_pae_paging(vcpu)) {
+ load_pdptrs(vcpu, kvm_read_cr3(vcpu));
+ *mmu_reset_needed = 1;
}
kvm_set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
>
> void kvm_pmu_instruction_retired(struct kvm_vcpu *vcpu)
> --
> 2.55.0.1003.g10538fe699-goog
>
next prev parent reply other threads:[~2026-09-10 16:46 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 16:21 [PATCH RFC 00/10] KVM: Enable Clang Context Analysis Marco Elver
2026-09-10 16:21 ` [PATCH RFC 01/10] KVM: x86/pmu: Acquire SRCU in pmc_is_event_allowed() to protect filter lookup Marco Elver
2026-09-10 16:46 ` Sean Christopherson [this message]
2026-09-10 16:21 ` [PATCH RFC 02/10] KVM: Allow reading memslots while holding slots_arch_lock Marco Elver
2026-09-10 16:30 ` Sean Christopherson
2026-09-10 17:11 ` Marco Elver
2026-09-10 17:52 ` Sean Christopherson
2026-09-10 19:05 ` Marco Elver
2026-09-10 16:39 ` sashiko-bot
2026-09-10 16:21 ` [PATCH RFC 03/10] KVM: guest_memfd: Avoid conditional mmu_lock acquisition Marco Elver
2026-09-10 16:42 ` sashiko-bot
2026-09-10 16:21 ` [PATCH RFC 04/10] KVM: Refactor kvm_handle_hva_range() to avoid conditional mmu_lock Marco Elver
2026-09-10 16:38 ` Sean Christopherson
2026-09-10 16:21 ` [PATCH RFC 05/10] KVM: Refactor kvm_handle_gfn_range() " Marco Elver
2026-09-10 16:21 ` [PATCH RFC 06/10] KVM: Add basic lock context annotations Marco Elver
2026-09-10 16:34 ` sashiko-bot
2026-09-10 16:53 ` Marco Elver
2026-09-10 16:21 ` [PATCH RFC 07/10] KVM: x86: " Marco Elver
2026-09-10 16:21 ` [PATCH RFC 08/10] KVM: Add guarded_by to members in struct kvm Marco Elver
2026-09-10 16:21 ` [PATCH RFC 09/10] KVM: x86: Add guarded_by annotations for kvm_arch, kvm_hv, and ioapic Marco Elver
2026-09-10 16:46 ` sashiko-bot
2026-09-10 16:21 ` [PATCH RFC 10/10] KVM: x86: Enable CONTEXT_ANALYSIS with opt-outs Marco Elver
2026-09-10 16:55 ` [PATCH RFC 00/10] KVM: Enable Clang Context Analysis Sean Christopherson
2026-09-10 19:19 ` Marco Elver
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=aqLe6FcPZIgj2RA6@google.com \
--to=seanjc@google.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=david@kernel.org \
--cc=elver@google.com \
--cc=hpa@zytor.com \
--cc=kas@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=rick.p.edgecombe@intel.com \
--cc=tglx@kernel.org \
--cc=vkuznets@redhat.com \
--cc=x86@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 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.