Skip to content

Commit 5a75911

Browse files
sean-jcbonzini
authored andcommitted
KVM: selftests: Expand x86's sregs test to cover illegal CR0 values
Add coverage to x86's set_sregs_test to verify KVM rejects vendor-agnostic illegal CR0 values, i.e. CR0 values whose legality doesn't depend on the current VMX mode. KVM historically has neglected to reject bad CR0s from userspace, i.e. would happily accept a completely bogus CR0 via KVM_SET_SREGS{2}. Punt VMX specific subtests to future work, as they would require quite a bit more effort, and KVM gets coverage for CR0 checks in general through other means, e.g. KVM-Unit-Tests. Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20230613203037.1968489-4-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent c4abd73 commit 5a75911

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

tools/testing/selftests/kvm/x86_64/set_sregs_test.c

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,25 @@
2222
#include "kvm_util.h"
2323
#include "processor.h"
2424

25-
static void test_cr4_feature_bit(struct kvm_vcpu *vcpu, struct kvm_sregs *orig,
26-
uint64_t feature_bit)
27-
{
28-
struct kvm_sregs sregs;
29-
int rc;
30-
31-
/* Skip the sub-test, the feature is supported. */
32-
if (orig->cr4 & feature_bit)
33-
return;
34-
35-
memcpy(&sregs, orig, sizeof(sregs));
36-
sregs.cr4 |= feature_bit;
37-
38-
rc = _vcpu_sregs_set(vcpu, &sregs);
39-
TEST_ASSERT(rc, "KVM allowed unsupported CR4 bit (0x%lx)", feature_bit);
40-
41-
/* Sanity check that KVM didn't change anything. */
42-
vcpu_sregs_get(vcpu, &sregs);
43-
TEST_ASSERT(!memcmp(&sregs, orig, sizeof(sregs)), "KVM modified sregs");
44-
}
25+
#define TEST_INVALID_CR_BIT(vcpu, cr, orig, bit) \
26+
do { \
27+
struct kvm_sregs new; \
28+
int rc; \
29+
\
30+
/* Skip the sub-test, the feature/bit is supported. */ \
31+
if (orig.cr & bit) \
32+
break; \
33+
\
34+
memcpy(&new, &orig, sizeof(sregs)); \
35+
new.cr |= bit; \
36+
\
37+
rc = _vcpu_sregs_set(vcpu, &new); \
38+
TEST_ASSERT(rc, "KVM allowed invalid " #cr " bit (0x%lx)", bit); \
39+
\
40+
/* Sanity check that KVM didn't change anything. */ \
41+
vcpu_sregs_get(vcpu, &new); \
42+
TEST_ASSERT(!memcmp(&new, &orig, sizeof(new)), "KVM modified sregs"); \
43+
} while (0)
4544

4645
static uint64_t calc_supported_cr4_feature_bits(void)
4746
{
@@ -80,7 +79,7 @@ int main(int argc, char *argv[])
8079
struct kvm_vcpu *vcpu;
8180
struct kvm_vm *vm;
8281
uint64_t cr4;
83-
int rc;
82+
int rc, i;
8483

8584
/*
8685
* Create a dummy VM, specifically to avoid doing KVM_SET_CPUID2, and
@@ -92,6 +91,7 @@ int main(int argc, char *argv[])
9291

9392
vcpu_sregs_get(vcpu, &sregs);
9493

94+
sregs.cr0 = 0;
9595
sregs.cr4 |= calc_supported_cr4_feature_bits();
9696
cr4 = sregs.cr4;
9797

@@ -103,16 +103,24 @@ int main(int argc, char *argv[])
103103
sregs.cr4, cr4);
104104

105105
/* Verify all unsupported features are rejected by KVM. */
106-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_UMIP);
107-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_LA57);
108-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_VMXE);
109-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_SMXE);
110-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_FSGSBASE);
111-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_PCIDE);
112-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_OSXSAVE);
113-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_SMEP);
114-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_SMAP);
115-
test_cr4_feature_bit(vcpu, &sregs, X86_CR4_PKE);
106+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_UMIP);
107+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_LA57);
108+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_VMXE);
109+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMXE);
110+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_FSGSBASE);
111+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PCIDE);
112+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_OSXSAVE);
113+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMEP);
114+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMAP);
115+
TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PKE);
116+
117+
for (i = 32; i < 64; i++)
118+
TEST_INVALID_CR_BIT(vcpu, cr0, sregs, BIT(i));
119+
120+
/* NW without CD is illegal, as is PG without PE. */
121+
TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_NW);
122+
TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_PG);
123+
116124
kvm_vm_free(vm);
117125

118126
/* Create a "real" VM and verify APIC_BASE can be set. */

0 commit comments

Comments
 (0)