From nobody Sat Feb 7 08:07:32 2026 Received: from mail-pg1-f202.google.com (mail-pg1-f202.google.com [209.85.215.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9355E263F52 for ; Wed, 28 Jan 2026 01:43:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769564598; cv=none; b=ZY98LYvaB76irV4X6/pT9hDuZhxjKIjWhJ57h2glrDs28yNZ4Y28IEqpPBlSy3KITWHrak8waCgN9MRXVfmeTX7pI4/9DiX83EIKIuMhUO9/slLbaVt8TH88bMkaimfw5cPO/TLi1A7kuEFe0SI5k7FT3Zpy9vGwoc+GwIt+9nA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769564598; c=relaxed/simple; bh=gjNPSqmL0Tbn8NDFbPUIQp/fE+kR/OlsEcl9q9Y4XdU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=WYLfgo1M5NZeJQLulngFCWJGoOFhcXMHEHhEw8BmPSgdslnHX18AYWe9dGEwZwYJrk4f8wvP45FouWFvkja2OdVgWujdE75NMhNP52kdF7hxf4iX1EbWzRKx5F3Y6+75liAnmpFFOtiJpBxeraP1p2qePgc3ouq9PXzn2ubEYkU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=4TVi2q01; arc=none smtp.client-ip=209.85.215.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="4TVi2q01" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-c5eed9a994dso3357994a12.2 for ; Tue, 27 Jan 2026 17:43:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1769564596; x=1770169396; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=4DtlW/gC7gteJd+CFkna93VzdyPdpEl+ULoZd8O0aTU=; b=4TVi2q01ibw3AppQkC2naOJRq24+WuBTUqehM7HQyLyI+WT6DKiHr5z1stQDGK9/HJ e7p5+3KdIrvl5c3KbQu2VeMy9GCCKedlccNqkNK1sCE+LLr7PU0js+lyVsQin18bl142 tCNmvfCz11RyplfsaHVVADP9VgS5LQUclCM7Tpg/mFTRqBp8SoHKv9iB3tdoVkXqOgHd P02btg8rvRY3dqZlFPspYUXxXql0fMshGX9fZhOLptfU60ydJ7FZ0iBgDAPP2SIhpsix r1H7NI+bGV/3P/e+eISDOc67v7y12Iegk9aWDsYKOmqTsSsDcWCOM8r+QF7u//FqGNMS 9laA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769564596; x=1770169396; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=4DtlW/gC7gteJd+CFkna93VzdyPdpEl+ULoZd8O0aTU=; b=HmVewjZZMyev13CstxwGwrhBhnlNq5EEIHx6UZUfs4docWAjtOxijNTsU4bN1UfTI8 vBprPlDGYFDNFarG03BESZvJpiU8C3KXP4LbReINME52Xg/VFL+ZiHC0Dr0FMqtcR7gI UVFfEPubmwYFCAmmKYHKPmBiW5G/q0DyAuwmC5k1J/sIa2zSeH0btYieYbXQBNO9Tvyk 371KqGDnfm3F6yfs+JgyQF8Ku0+hurVXK/gzT7JP8Uoo74Fkd/q0Y7cGE6/dcxp3fCDf UfZAC9Ntiy5B7HXz+SYMnOZmuBYdncI5g/u90pr4rWw0CgqUxc2+lDtSeHdT7eXHTXpk PEUA== X-Forwarded-Encrypted: i=1; AJvYcCX85IEJzyDbPvaIz5639KV2Fqt+SGzdEP4B6tKmdKvxYVrCG7wBAFoEXrb4MWg0lS8QyOJ0jgHX6f9S930=@vger.kernel.org X-Gm-Message-State: AOJu0YxHL2YlS6O7D7XJoQJhp7NNV9wwrFKtEXjfYqRRW3mrJCKNc9M8 xKqd1zc6zlI/imddE/3c57iLgTEfkH15d6et4uQAs5bd18Ws2k1rBQjVc1R4As2SPSr930hWH4V 26ij3vg== X-Received: from pgah16.prod.google.com ([2002:a05:6a02:4e90:b0:c1e:18e8:e532]) (user=seanjc job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:498:b0:38d:e6f8:fd96 with SMTP id adf61e73a8af0-38ec6428c3dmr3264203637.60.1769564595826; Tue, 27 Jan 2026 17:43:15 -0800 (PST) Reply-To: Sean Christopherson Date: Tue, 27 Jan 2026 17:43:09 -0800 In-Reply-To: <20260128014310.3255561-1-seanjc@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260128014310.3255561-1-seanjc@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260128014310.3255561-3-seanjc@google.com> Subject: [PATCH v2 2/3] KVM: x86: Harden against unexpected adjustments to kvm_cpu_caps From: Sean Christopherson To: Sean Christopherson , Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Mathias Krause , John Allen , Rick Edgecombe , Chao Gao , Binbin Wu , Xiaoyao Li , Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a flag to track when KVM is actively configuring its CPU caps, and WARN if a cap is set or cleared if KVM isn't in its configuration stage. Modifying CPU caps after {svm,vmx}_set_cpu_caps() can be fatal to KVM, as vendor setup code expects the CPU caps to be frozen at that point, e.g. will do additional configuration based on the caps. Rename kvm_set_cpu_caps() to kvm_initialize_cpu_caps() to pair with the new "finalize", and to make it more obvious that KVM's CPU caps aren't fully configured within the function. Signed-off-by: Sean Christopherson Reviewed-by: Binbin Wu Reviewed-by: Xiaoyao Li --- arch/x86/kvm/cpuid.c | 10 ++++++++-- arch/x86/kvm/cpuid.h | 12 +++++++++++- arch/x86/kvm/svm/svm.c | 4 +++- arch/x86/kvm/vmx/vmx.c | 4 +++- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 575244af9c9f..7fe4e58a6ebf 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -36,6 +36,9 @@ u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly; EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_cpu_caps); =20 +bool kvm_is_configuring_cpu_caps __read_mostly; +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_is_configuring_cpu_caps); + struct cpuid_xstate_sizes { u32 eax; u32 ebx; @@ -826,10 +829,13 @@ do { \ /* DS is defined by ptrace-abi.h on 32-bit builds. */ #undef DS =20 -void kvm_set_cpu_caps(void) +void kvm_initialize_cpu_caps(void) { memset(kvm_cpu_caps, 0, sizeof(kvm_cpu_caps)); =20 + WARN_ON_ONCE(kvm_is_configuring_cpu_caps); + kvm_is_configuring_cpu_caps =3D true; + BUILD_BUG_ON(sizeof(kvm_cpu_caps) - (NKVMCAPINTS * sizeof(*kvm_cpu_caps))= > sizeof(boot_cpu_data.x86_capability)); =20 @@ -1289,7 +1295,7 @@ void kvm_set_cpu_caps(void) kvm_cpu_cap_clear(X86_FEATURE_RDPID); } } -EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_cpu_caps); +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_initialize_cpu_caps); =20 #undef F #undef SCATTERED_F diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index d3f5ae15a7ca..039b8e6f40ba 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -8,7 +8,15 @@ #include =20 extern u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly; -void kvm_set_cpu_caps(void); +extern bool kvm_is_configuring_cpu_caps __read_mostly; + +void kvm_initialize_cpu_caps(void); + +static inline void kvm_finalize_cpu_caps(void) +{ + WARN_ON_ONCE(!kvm_is_configuring_cpu_caps); + kvm_is_configuring_cpu_caps =3D false; +} =20 void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu); struct kvm_cpuid_entry2 *kvm_find_cpuid_entry2(struct kvm_cpuid_entry2 *en= tries, @@ -188,6 +196,7 @@ static __always_inline void kvm_cpu_cap_clear(unsigned = int x86_feature) { unsigned int x86_leaf =3D __feature_leaf(x86_feature); =20 + WARN_ON_ONCE(!kvm_is_configuring_cpu_caps); kvm_cpu_caps[x86_leaf] &=3D ~__feature_bit(x86_feature); } =20 @@ -195,6 +204,7 @@ static __always_inline void kvm_cpu_cap_set(unsigned in= t x86_feature) { unsigned int x86_leaf =3D __feature_leaf(x86_feature); =20 + WARN_ON_ONCE(!kvm_is_configuring_cpu_caps); kvm_cpu_caps[x86_leaf] |=3D __feature_bit(x86_feature); } =20 diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index c00a696dacfc..5f0136dbdde6 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5305,7 +5305,7 @@ static __init void svm_adjust_mmio_mask(void) =20 static __init void svm_set_cpu_caps(void) { - kvm_set_cpu_caps(); + kvm_initialize_cpu_caps(); =20 kvm_caps.supported_perf_cap =3D 0; =20 @@ -5389,6 +5389,8 @@ static __init void svm_set_cpu_caps(void) kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM); =20 kvm_setup_xss_caps(); + + kvm_finalize_cpu_caps(); } =20 static __init int svm_hardware_setup(void) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 9f85c3829890..93ec1e6181e4 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8173,7 +8173,7 @@ static __init u64 vmx_get_perf_capabilities(void) =20 static __init void vmx_set_cpu_caps(void) { - kvm_set_cpu_caps(); + kvm_initialize_cpu_caps(); =20 /* CPUID 0x1 */ if (nested) @@ -8232,6 +8232,8 @@ static __init void vmx_set_cpu_caps(void) } =20 kvm_setup_xss_caps(); + + kvm_finalize_cpu_caps(); } =20 static bool vmx_is_io_intercepted(struct kvm_vcpu *vcpu, --=20 2.52.0.457.g6b5491de43-goog