From nobody Sat Jul 25 20:46:42 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D4D8134D3A9; Mon, 13 Jul 2026 18:02:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783965742; cv=none; b=oRgWTST0MmJWUf4a64HvKotGcKLlPyzicK0stk4eN+BmFFT0ll1B59S4bbbzJZArX1iw9jvxN26ZMMjU2GcFRemNMOxuISn1XfPD90HG0nmC8ycuV9U8sOYNnWbuDX1E61TJylDnRKNVwzXHF6fFiRffwkjJx1Gv/mw1+7jtNzk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783965742; c=relaxed/simple; bh=BeOXUDr/kv2WzNFdRg+92KWiqkvRAsJbfzlhEOqNMTA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TUfQuRHO6g9h0l1dVEBU+fnAYCKd6QsXcTNRKTnofGwkzUuNDZRLLfCzNe4gXvs5b3wVvQrRf3Ob92RxAlEHletZFG3prpyskWnoZK9pxdFJAAyTrsbKT0zI3V5EbIrtgOHzPokMRltngUrEmYZY9pku38HTrnQk0OzvrmW1ys4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Q+IpVSWE; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Q+IpVSWE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 842E81F00A3D; Mon, 13 Jul 2026 18:02:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1783965740; bh=M/9xkFzTJN6MchzaNzn3CvlAokWR07Ud0R0Iaok52ys=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Q+IpVSWEmNzwLfYFkQbN6Rk6zN6/KZqfXIMAvlUTiMAvBthWmvJW2l8kqU68UXWyf 8lEgeB46yYGX6j3fpuJITal6EoxQV6LKOaop8BNSc7ZtezApTFIXyh8YOIiS3IwX7d 0bH4zyHsaLYgnvFXIAJnvOPT5F4do9YeD+7V0qCZq/07K/dXsr++XIa9I1DYpE+1h7 ZyI1GFMA6m2ZfphWP1SCaHSpaddl23/wkJ617Xi2900Ku8jq+sYLZJ18waEF/tIuVM fKOjxdJYIu6onJ3X27ZWnXkh/qgcDoXpQy8vjnFjhIhLhad+dHt1ZY0DPfQgMILerO oJKMMIIZhMzkQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , stable@vger.kernel.org Subject: [PATCH v3 1/2] KVM: x86: Check EFER validity on KVM_SET_SREGS* Date: Mon, 13 Jul 2026 18:01:52 +0000 Message-ID: <20260713180153.2728382-2-yosry@kernel.org> X-Mailer: git-send-email 2.55.0.141.g00534a21ce-goog In-Reply-To: <20260713180153.2728382-1-yosry@kernel.org> References: <20260713180153.2728382-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When handling userspace SREGS writes, check the validity of EFER (i.e. allowed bits) before writing the new value of EFER through the per-vendor set_efer callbacks. This prevents userspace from writing bogus values (e.g. EFER.SVME=3D1 with nested=3D0). Note: on KVM_SET_MSRS, KVM only checks EFER validity in terms of KVM caps, not guest caps, so it is possible to set EFER bits that are supported by KVM but not by the guest CPUID. Potentially allowing userspace to set msrs before CPUID. However, for KVM_SET_SREGS*, check the validity of the set bits against both KVM and guest caps. This is consistent with other validity checks (e.g. for CR4) that check validity against guest caps, which already imposes the need to set CPUID before SREGS. Cc: stable@vger.kernel.org Change-Id: I45701ec440e4fdd8f086eb70db0c0845fb0ed509 Signed-off-by: Yosry Ahmed --- arch/x86/kvm/regs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c index bd8147798cc3e..8f66438989e47 100644 --- a/arch/x86/kvm/regs.c +++ b/arch/x86/kvm/regs.c @@ -564,7 +564,8 @@ static bool kvm_is_valid_sregs(struct kvm_vcpu *vcpu, s= truct kvm_sregs *sregs) } =20 return kvm_is_valid_cr4(vcpu, sregs->cr4) && - kvm_is_valid_cr0(vcpu, sregs->cr0); + kvm_is_valid_cr0(vcpu, sregs->cr0) && + kvm_valid_efer(vcpu, sregs->efer); } =20 static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sre= gs, --=20 2.55.0.141.g00534a21ce-goog From nobody Sat Jul 25 20:46:42 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37F3D34D3B0; Mon, 13 Jul 2026 18:02:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783965742; cv=none; b=iNsBbdctPsMAInUJq56OggSoemwX8kda3vBIJxZkZw5hIrjDvWsvqsNtkWXwuUmI1OsX38agDDvN3siE+GqvTEefr2eJ2wcQgREPpAtcTmyxk3E1FxRD9iTtUeaj0x1XyjiOMbOpNwYFGfBkB0r6iE8fJDrjvxGhlIO97E21jl4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783965742; c=relaxed/simple; bh=tRbLclaxSYxNS0L4/oigYMlAtYJxDb4wcf8OTtIpHJw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kvYp8nEMwlo4AqFLD1NmG6fHJ227gs2aTLzfBeochFonFotjs7pWcwHAosAvRNvf8maZsnavYK65YCBOXkZW0qatgi1fmJKfrVdo72XL45QvvFpwqg+izUjbwORBOtfOFFoeX0iCkUmuj5Ptz0MRCIbfkxylTHoDWspKDlIZov0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=frv7i9ax; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="frv7i9ax" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E3D8E1F00A3A; Mon, 13 Jul 2026 18:02:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1783965741; bh=qCO55NC2P/PZ9Sue0HsGZx8cyUGbA4nqnRCn3uwivFc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=frv7i9ax8wNo/lFUjfphdJZWPKS2kYjlnnlDpJzPvcoKzizGoF8lFwCEemVztba0g ytsC0W8hbSgnS1GjOq9vrHYf+HbyUnLVpTwkQuAU75qxaBLoloV/57aGFuFBohGXak vnPf11lG+dgHVbWCKA26av5ne6UwWafimKC9tGACOHjM1sObVzheH5D51L0KLpWRWP hvgS8YY3VqfjWU+sZDS+VDPQ6Ev+ZKca/k9SEJuaQAbycDKwSn4vyeKE7iFCa7ELHC N2SL7sxAVKvh4CLceUVaipnyByIWKkO2R/Xpv8cy8V5Cp2S59Tcgu8CoFb99AbOp8a IG/4RPmJmUFew== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v3 2/2] KVM: selftests: Extend set_sregs test to cover EFER Date: Mon, 13 Jul 2026 18:01:53 +0000 Message-ID: <20260713180153.2728382-3-yosry@kernel.org> X-Mailer: git-send-email 2.55.0.141.g00534a21ce-goog In-Reply-To: <20260713180153.2728382-1-yosry@kernel.org> References: <20260713180153.2728382-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the set_sregs test to cover various bits in EFER. Update TEST_INVALID_CR_BIT() to operate on EFER as well as CRx (and rename it accordingly). Add test cases to check that EFER bits are disallowed without the relevant CPUID enablement. Assisted-by: Gemini:unknown-version Change-Id: I588e7259c6257f40640127a52ce808a0f5afa016 Signed-off-by: Yosry Ahmed --- .../selftests/kvm/include/x86/processor.h | 2 + .../selftests/kvm/x86/set_sregs_test.c | 83 ++++++++++++++----- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 7d3a27bc0d842..b161174ece453 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -208,6 +208,7 @@ struct kvm_x86_cpu_feature { #define X86_FEATURE_PERFCTR_NB KVM_X86_CPU_FEATURE(0x80000001, 0, ECX, 24) #define X86_FEATURE_PERFCTR_LLC KVM_X86_CPU_FEATURE(0x80000001, 0, ECX, 2= 8) #define X86_FEATURE_NX KVM_X86_CPU_FEATURE(0x80000001, 0, EDX, 20) +#define X86_FEATURE_FXSR_OPT KVM_X86_CPU_FEATURE(0x80000001, 0, EDX, 25) #define X86_FEATURE_GBPAGES KVM_X86_CPU_FEATURE(0x80000001, 0, EDX, 26) #define X86_FEATURE_RDTSCP KVM_X86_CPU_FEATURE(0x80000001, 0, EDX, 27) #define X86_FEATURE_LM KVM_X86_CPU_FEATURE(0x80000001, 0, EDX, 29) @@ -226,6 +227,7 @@ struct kvm_x86_cpu_feature { #define X86_FEATURE_SEV KVM_X86_CPU_FEATURE(0x8000001F, 0, EAX, 1) #define X86_FEATURE_SEV_ES KVM_X86_CPU_FEATURE(0x8000001F, 0, EAX, 3) #define X86_FEATURE_SEV_SNP KVM_X86_CPU_FEATURE(0x8000001F, 0, EAX, 4) +#define X86_FEATURE_AUTOIBRS KVM_X86_CPU_FEATURE(0x80000021, 0, EAX, 8) #define X86_FEATURE_GP_ON_USER_CPUID KVM_X86_CPU_FEATURE(0x80000021, 0, EA= X, 17) #define X86_FEATURE_PERFMON_V2 KVM_X86_CPU_FEATURE(0x80000022, 0, EAX, 0) #define X86_FEATURE_LBR_PMC_FREEZE KVM_X86_CPU_FEATURE(0x80000022, 0, EAX,= 2) diff --git a/tools/testing/selftests/kvm/x86/set_sregs_test.c b/tools/testi= ng/selftests/kvm/x86/set_sregs_test.c index 8e654cc9ab168..562afab378d11 100644 --- a/tools/testing/selftests/kvm/x86/set_sregs_test.c +++ b/tools/testing/selftests/kvm/x86/set_sregs_test.c @@ -21,20 +21,20 @@ #include "kvm_util.h" #include "processor.h" =20 -#define TEST_INVALID_CR_BIT(vcpu, cr, orig, bit) \ +#define TEST_INVALID_SREG_BIT(vcpu, reg, orig, bit) \ do { \ struct kvm_sregs new; \ int rc; \ \ /* Skip the sub-test, the feature/bit is supported. */ \ - if (orig.cr & bit) \ + if (orig.reg & bit) \ break; \ \ - memcpy(&new, &orig, sizeof(sregs)); \ - new.cr |=3D bit; \ + memcpy(&new, &orig, sizeof(new)); \ + new.reg |=3D bit; \ \ rc =3D _vcpu_sregs_set(vcpu, &new); \ - TEST_ASSERT(rc, "KVM allowed invalid " #cr " bit (0x%lx)", bit); \ + TEST_ASSERT(rc, "KVM allowed invalid " #reg " bit (0x%llx)", (unsigned lo= ng long)bit); \ \ /* Sanity check that KVM didn't change anything. */ \ vcpu_sregs_get(vcpu, &new); \ @@ -46,6 +46,8 @@ do { \ X86_CR4_MCE | X86_CR4_PGE | X86_CR4_PCE | \ X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT) =20 +#define KVM_ALWAYS_ALLOWED_EFER EFER_SCE + static u64 calc_supported_cr4_feature_bits(void) { u64 cr4 =3D KVM_ALWAYS_ALLOWED_CR4; @@ -74,6 +76,24 @@ static u64 calc_supported_cr4_feature_bits(void) return cr4; } =20 +static u64 calc_supported_efer_feature_bits(void) +{ + u64 efer =3D KVM_ALWAYS_ALLOWED_EFER; + + if (kvm_cpu_has(X86_FEATURE_LM)) + efer |=3D (EFER_LME | EFER_LMA); + if (kvm_cpu_has(X86_FEATURE_NX)) + efer |=3D EFER_NX; + if (kvm_cpu_has(X86_FEATURE_SVM)) + efer |=3D EFER_SVME; + if (kvm_cpu_has(X86_FEATURE_FXSR_OPT)) + efer |=3D EFER_FFXSR; + if (kvm_cpu_has(X86_FEATURE_AUTOIBRS)) + efer |=3D EFER_AUTOIBRS; + + return efer; +} + static void test_cr_bits(struct kvm_vcpu *vcpu, u64 cr4) { struct kvm_sregs sregs; @@ -96,26 +116,45 @@ static void test_cr_bits(struct kvm_vcpu *vcpu, u64 cr= 4) (sregs.cr4 & X86_CR4_PKE) ? "set" : "clear"); =20 vcpu_sregs_get(vcpu, &sregs); - TEST_ASSERT(sregs.cr4 =3D=3D cr4, "sregs.CR4 (0x%llx) !=3D CR4 (0x%lx)", - sregs.cr4, cr4); - - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_UMIP); - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_LA57); - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_VMXE); - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMXE); - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_FSGSBASE); - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PCIDE); - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_OSXSAVE); - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMEP); - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMAP); - TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PKE); + TEST_ASSERT_EQ(sregs.cr4, cr4); + + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_UMIP); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_LA57); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_VMXE); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_SMXE); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_FSGSBASE); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_PCIDE); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_OSXSAVE); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_SMEP); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_SMAP); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_PKE); =20 for (i =3D 32; i < 64; i++) - TEST_INVALID_CR_BIT(vcpu, cr0, sregs, BIT(i)); + TEST_INVALID_SREG_BIT(vcpu, cr0, sregs, BIT(i)); =20 /* NW without CD is illegal, as is PG without PE. */ - TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_NW); - TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_PG); + TEST_INVALID_SREG_BIT(vcpu, cr0, sregs, X86_CR0_NW); + TEST_INVALID_SREG_BIT(vcpu, cr0, sregs, X86_CR0_PG); +} + +static void test_efer_bits(struct kvm_vcpu *vcpu, u64 efer) +{ + struct kvm_sregs sregs; + int rc; + + vcpu_sregs_get(vcpu, &sregs); + sregs.efer |=3D efer; + rc =3D _vcpu_sregs_set(vcpu, &sregs); + TEST_ASSERT(!rc, "Failed to set supported EFER bits (0x%llx)", sregs.efer= ); + + vcpu_sregs_get(vcpu, &sregs); + TEST_ASSERT_EQ(sregs.efer, efer); + + TEST_INVALID_SREG_BIT(vcpu, efer, sregs, EFER_LME); + TEST_INVALID_SREG_BIT(vcpu, efer, sregs, EFER_NX); + TEST_INVALID_SREG_BIT(vcpu, efer, sregs, EFER_SVME); + TEST_INVALID_SREG_BIT(vcpu, efer, sregs, EFER_FFXSR); + TEST_INVALID_SREG_BIT(vcpu, efer, sregs, EFER_AUTOIBRS); } =20 int main(int argc, char *argv[]) @@ -132,6 +171,7 @@ int main(int argc, char *argv[]) */ vm =3D vm_create_barebones(); vcpu =3D __vm_vcpu_add(vm, 0); + test_efer_bits(vcpu, KVM_ALWAYS_ALLOWED_EFER); test_cr_bits(vcpu, KVM_ALWAYS_ALLOWED_CR4); kvm_vm_free(vm); =20 @@ -151,6 +191,7 @@ int main(int argc, char *argv[]) sregs.apic_base); =20 test_cr_bits(vcpu, calc_supported_cr4_feature_bits()); + test_efer_bits(vcpu, calc_supported_efer_feature_bits()); =20 kvm_vm_free(vm); =20 --=20 2.55.0.141.g00534a21ce-goog