lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aYOF0LNp173xAEsy@google.com>
Date: Wed, 4 Feb 2026 09:45:52 -0800
From: Sean Christopherson <seanjc@...gle.com>
To: Yosry Ahmed <yosry.ahmed@...ux.dev>
Cc: Paolo Bonzini <pbonzini@...hat.com>, Kevin Cheng <chengkev@...gle.com>, kvm@...r.kernel.org, 
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/3] KVM: nSVM: Rename recalc_intercepts() to clarify
 vmcb02 as the target

On Mon, Jan 12, 2026, Yosry Ahmed wrote:
> recalc_intercepts() updates the intercept bits in vmcb02 based on vmcb01
> and (cached) vmcb12.

Ah, but it does more than that.  More below.

> However, the name is too generic to make this
> clear, and is especially confusing while searching through the code as
> it shares the same name as the recalc_intercepts callback in
> kvm_x86_ops.
> 
> Rename it to nested_vmcb02_recalc_intercepts() (similar to other
> nested_vmcb02_* scoped functions), to make it clear what it is doing.
> 
> No functional change intended.
> 
> Signed-off-by: Yosry Ahmed <yosry.ahmed@...ux.dev>
> ---
>  arch/x86/kvm/svm/nested.c |  4 ++--
>  arch/x86/kvm/svm/sev.c    |  2 +-
>  arch/x86/kvm/svm/svm.c    |  4 ++--
>  arch/x86/kvm/svm/svm.h    | 10 +++++-----
>  4 files changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
> index 2dda52221fd8..bacb2ac4c59e 100644
> --- a/arch/x86/kvm/svm/nested.c
> +++ b/arch/x86/kvm/svm/nested.c
> @@ -123,7 +123,7 @@ static bool nested_vmcb_needs_vls_intercept(struct vcpu_svm *svm)
>  	return false;
>  }
>  
> -void recalc_intercepts(struct vcpu_svm *svm)
> +void nested_vmcb02_recalc_intercepts(struct vcpu_svm *svm)
>  {
>  	struct vmcb *vmcb01, *vmcb02;
>  	unsigned int i;

Drat, I should have responded to the previous patch.  Lurking out of sight is a
pre-existing bug that effectively invalidates this entire rename.

The existing code is:

  void recalc_intercepts(struct vcpu_svm *svm)
  {
	struct vmcb *vmcb01, *vmcb02;
	unsigned int i;

	vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS);  <======= not vmcb01!!!!!

	if (!is_guest_mode(&svm->vcpu))
		return;

When L2 is active, svm->vmcb is vmcb02.  Which, at first glance, _looks_ right,
but (the *horribly* named) recalc_intercepts() isn't _just_ recalculating
intercepts for L2, it's also responsible for marking the VMCB_INTERCEPTS dirty
(obviously).

But what isn't so obvious is that _all_ callers operate on vmcb01, because the
pattern is to modify vmcb01 intercepts, and then merge the new vmcb01 intercepts
with vmcb12, i.e. the "recalc intercepts" aspect is "part 2" of the overall
function.

Lost in all of this is that KVM forgets to mark vmcb01 dirty, and unless there's
a call buried somewhere deep, nested_svm_vmexit() isn't guaranteed to mark
VMCB_INTERCEPTS dirty, e.g. if PAUSE interception is disabled.

It's probably a benign bug in practice, as AMD CPUs don't appear to do anything
with the clean fields, but easy to fix.

As a bonus, fixing that bug yields for even better naming and code.  After the
dust settles, we can end up with this in svm.h:

  void nested_vmcb02_recalc_intercepts(struct vcpu_svm *svm);

  static inline void svm_mark_intercepts_dirty(struct vcpu_svm *svm)
  {
	vmcb_mark_dirty(svm->vmcb01.ptr, VMCB_INTERCEPTS);

	/*
	 * If L2 is active, recalculate the intercepts for vmcb02 to account
	 * for the changes made to vmcb01.  All intercept configuration is done
	 * for vmcb01 and then propagated to vmcb02 to combine KVM's intercepts
	 * with L1's intercepts (from the vmcb12 snapshot).
	 */
	if (is_guest_mode(&svm->vcpu))
		nested_vmcb02_recalc_intercepts(svm);
  }

and this for nested_vmcb02_recalc_intercepts():

  void nested_vmcb02_recalc_intercepts(struct vcpu_svm *svm)
  {
	struct vmcb_ctrl_area_cached *vmcb12_ctrl = &svm->nested.ctl;
	struct vmcb *vmcb02 = svm->nested.vmcb02.ptr;
	struct vmcb *vmcb01 = svm->vmcb01.ptr;
	unsigned int i;

	if (WARN_ON_ONCE(svm->vmcb != vmcb02))
		return;

	...
  }

with the only other caller of nested_vmcb02_recalc_intercepts() being
nested_vmcb02_prepare_control().

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ