Message ID | 20221103141351.50662-7-mlevitsk@redhat.com |
---|---|
State | Superseded |
Headers | show |
Series | nSVM: Security and correctness fixes | expand |
On 03/11/2022 14:28, Maxim Levitsky wrote: > On Thu, 2022-11-03 at 16:13 +0200, Maxim Levitsky wrote: >> Add test that tests that on SVM if L1 doesn't intercept SHUTDOWN, >> then L2 crashes L1 and doesn't crash L2 > I mean doesn't crash L0, sorry for typo. > > Best regards, > Maxim Levitsky >> >> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Reviewed-by: Liam Merwick <liam.merwick@oracle.com> >> --- >> tools/testing/selftests/kvm/.gitignore | 1 + >> tools/testing/selftests/kvm/Makefile | 1 + >> .../kvm/x86_64/svm_nested_shutdown_test.c | 67 +++++++++++++++++++ >> 3 files changed, 69 insertions(+) >> create mode 100644 tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c >> >> diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore >> index 2f0d705db9dba5..05d980fb083d17 100644 >> --- a/tools/testing/selftests/kvm/.gitignore >> +++ b/tools/testing/selftests/kvm/.gitignore >> @@ -41,6 +41,7 @@ >> /x86_64/svm_vmcall_test >> /x86_64/svm_int_ctl_test >> /x86_64/svm_nested_soft_inject_test >> +/x86_64/svm_nested_shutdown_test >> /x86_64/sync_regs_test >> /x86_64/tsc_msrs_test >> /x86_64/tsc_scaling_sync >> diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile >> index 0172eb6cb6eee2..4a2caef2c9396f 100644 >> --- a/tools/testing/selftests/kvm/Makefile >> +++ b/tools/testing/selftests/kvm/Makefile >> @@ -101,6 +101,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/state_test >> TEST_GEN_PROGS_x86_64 += x86_64/vmx_preemption_timer_test >> TEST_GEN_PROGS_x86_64 += x86_64/svm_vmcall_test >> TEST_GEN_PROGS_x86_64 += x86_64/svm_int_ctl_test >> +TEST_GEN_PROGS_x86_64 += x86_64/svm_nested_shutdown_test >> TEST_GEN_PROGS_x86_64 += x86_64/svm_nested_soft_inject_test >> TEST_GEN_PROGS_x86_64 += x86_64/tsc_scaling_sync >> TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test >> diff --git a/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c b/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c >> new file mode 100644 >> index 00000000000000..e73fcdef47bbe9 >> --- /dev/null >> +++ b/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c >> @@ -0,0 +1,67 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * svm_nested_shutdown_test >> + * >> + * Copyright (C) 2022, Red Hat, Inc. >> + * >> + * Nested SVM testing: test that unintercepted shutdown in L2 doesn't crash the host >> + */ >> + >> +#include "test_util.h" >> +#include "kvm_util.h" >> +#include "processor.h" >> +#include "svm_util.h" >> + >> +static void l2_guest_code(struct svm_test_data *svm) >> +{ >> + __asm__ __volatile__("ud2"); >> +} >> + >> +static void l1_guest_code(struct svm_test_data *svm, struct idt_entry *idt) >> +{ >> + #define L2_GUEST_STACK_SIZE 64 >> + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; >> + struct vmcb *vmcb = svm->vmcb; >> + >> + generic_svm_setup(svm, l2_guest_code, >> + &l2_guest_stack[L2_GUEST_STACK_SIZE]); >> + >> + vmcb->control.intercept &= ~(BIT(INTERCEPT_SHUTDOWN)); >> + >> + idt[6].p = 0; // #UD is intercepted but its injection will cause #NP >> + idt[11].p = 0; // #NP is not intercepted and will cause another >> + // #NP that will be converted to #DF >> + idt[8].p = 0; // #DF will cause #NP which will cause SHUTDOWN >> + >> + run_guest(vmcb, svm->vmcb_gpa); >> + >> + /* should not reach here */ >> + GUEST_ASSERT(0); >> +} >> + >> +int main(int argc, char *argv[]) >> +{ >> + struct kvm_vcpu *vcpu; >> + struct kvm_run *run; >> + vm_vaddr_t svm_gva; >> + struct kvm_vm *vm; >> + >> + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); >> + >> + vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); >> + vm_init_descriptor_tables(vm); >> + vcpu_init_descriptor_tables(vcpu); >> + >> + vcpu_alloc_svm(vm, &svm_gva); >> + >> + vcpu_args_set(vcpu, 2, svm_gva, vm->idt); >> + run = vcpu->run; >> + >> + vcpu_run(vcpu); >> + TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN, >> + "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n", >> + run->exit_reason, >> + exit_reason_str(run->exit_reason)); >> + >> + kvm_vm_free(vm); >> +} > >
diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index 2f0d705db9dba5..05d980fb083d17 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -41,6 +41,7 @@ /x86_64/svm_vmcall_test /x86_64/svm_int_ctl_test /x86_64/svm_nested_soft_inject_test +/x86_64/svm_nested_shutdown_test /x86_64/sync_regs_test /x86_64/tsc_msrs_test /x86_64/tsc_scaling_sync diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 0172eb6cb6eee2..4a2caef2c9396f 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -101,6 +101,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/state_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_preemption_timer_test TEST_GEN_PROGS_x86_64 += x86_64/svm_vmcall_test TEST_GEN_PROGS_x86_64 += x86_64/svm_int_ctl_test +TEST_GEN_PROGS_x86_64 += x86_64/svm_nested_shutdown_test TEST_GEN_PROGS_x86_64 += x86_64/svm_nested_soft_inject_test TEST_GEN_PROGS_x86_64 += x86_64/tsc_scaling_sync TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test diff --git a/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c b/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c new file mode 100644 index 00000000000000..e73fcdef47bbe9 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * svm_nested_shutdown_test + * + * Copyright (C) 2022, Red Hat, Inc. + * + * Nested SVM testing: test that unintercepted shutdown in L2 doesn't crash the host + */ + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" +#include "svm_util.h" + +static void l2_guest_code(struct svm_test_data *svm) +{ + __asm__ __volatile__("ud2"); +} + +static void l1_guest_code(struct svm_test_data *svm, struct idt_entry *idt) +{ + #define L2_GUEST_STACK_SIZE 64 + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + struct vmcb *vmcb = svm->vmcb; + + generic_svm_setup(svm, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + vmcb->control.intercept &= ~(BIT(INTERCEPT_SHUTDOWN)); + + idt[6].p = 0; // #UD is intercepted but its injection will cause #NP + idt[11].p = 0; // #NP is not intercepted and will cause another + // #NP that will be converted to #DF + idt[8].p = 0; // #DF will cause #NP which will cause SHUTDOWN + + run_guest(vmcb, svm->vmcb_gpa); + + /* should not reach here */ + GUEST_ASSERT(0); +} + +int main(int argc, char *argv[]) +{ + struct kvm_vcpu *vcpu; + struct kvm_run *run; + vm_vaddr_t svm_gva; + struct kvm_vm *vm; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); + + vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); + vm_init_descriptor_tables(vm); + vcpu_init_descriptor_tables(vcpu); + + vcpu_alloc_svm(vm, &svm_gva); + + vcpu_args_set(vcpu, 2, svm_gva, vm->idt); + run = vcpu->run; + + vcpu_run(vcpu); + TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN, + "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n", + run->exit_reason, + exit_reason_str(run->exit_reason)); + + kvm_vm_free(vm); +}
Add test that tests that on SVM if L1 doesn't intercept SHUTDOWN, then L2 crashes L1 and doesn't crash L2 Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../kvm/x86_64/svm_nested_shutdown_test.c | 67 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c