From: Adalbert Lazar <alazar@xxxxxxxxxxxxxxx> Inform the guest introspection tool that a system table pointer register (GDTR, IDTR, LDTR, TR) has been accessed. Signed-off-by: Nicușor Cîțu <ncitu@xxxxxxxxxxxxxxx> --- arch/x86/kvm/svm.c | 41 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/vmx.c | 27 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 8903e0c58609..3b4911205081 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -4109,6 +4109,39 @@ static int avic_unaccelerated_access_interception(struct vcpu_svm *svm) return ret; } +static int descriptor_access_interception(struct vcpu_svm *svm) +{ + struct kvm_vcpu *vcpu = &svm->vcpu; + struct vmcb_control_area *c = &svm->vmcb->control; + + switch (c->exit_code) { + case SVM_EXIT_IDTR_READ: + case SVM_EXIT_IDTR_WRITE: + kvmi_descriptor_event(vcpu, c->exit_info_1, 0, + KVMI_DESC_IDTR, c->exit_code == SVM_EXIT_IDTR_WRITE); + break; + case SVM_EXIT_GDTR_READ: + case SVM_EXIT_GDTR_WRITE: + kvmi_descriptor_event(vcpu, c->exit_info_1, 0, + KVMI_DESC_GDTR, c->exit_code == SVM_EXIT_GDTR_WRITE); + break; + case SVM_EXIT_LDTR_READ: + case SVM_EXIT_LDTR_WRITE: + kvmi_descriptor_event(vcpu, c->exit_info_1, 0, + KVMI_DESC_LDTR, c->exit_code == SVM_EXIT_LDTR_WRITE); + break; + case SVM_EXIT_TR_READ: + case SVM_EXIT_TR_WRITE: + kvmi_descriptor_event(vcpu, c->exit_info_1, 0, + KVMI_DESC_TR, c->exit_code == SVM_EXIT_TR_WRITE); + break; + default: + break; + } + + return 1; +} + static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = { [SVM_EXIT_READ_CR0] = cr_interception, [SVM_EXIT_READ_CR3] = cr_interception, @@ -4173,6 +4206,14 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = { [SVM_EXIT_RSM] = emulate_on_interception, [SVM_EXIT_AVIC_INCOMPLETE_IPI] = avic_incomplete_ipi_interception, [SVM_EXIT_AVIC_UNACCELERATED_ACCESS] = avic_unaccelerated_access_interception, + [SVM_EXIT_IDTR_READ] = descriptor_access_interception, + [SVM_EXIT_GDTR_READ] = descriptor_access_interception, + [SVM_EXIT_LDTR_READ] = descriptor_access_interception, + [SVM_EXIT_TR_READ] = descriptor_access_interception, + [SVM_EXIT_IDTR_WRITE] = descriptor_access_interception, + [SVM_EXIT_GDTR_WRITE] = descriptor_access_interception, + [SVM_EXIT_LDTR_WRITE] = descriptor_access_interception, + [SVM_EXIT_TR_WRITE] = descriptor_access_interception, }; static void dump_vmcb(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index fbdfa8507d4f..ab744f04ae90 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8047,6 +8047,31 @@ static int handle_preemption_timer(struct kvm_vcpu *vcpu) return 1; } +static int handle_descriptor_access(struct kvm_vcpu *vcpu) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + u32 exit_reason = vmx->exit_reason; + unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); + u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO); + unsigned char store = (vmx_instruction_info >> 29) & 0x1; + unsigned char descriptor = 0; + + if (exit_reason == EXIT_REASON_GDTR_IDTR) { + if ((vmx_instruction_info >> 28) & 0x1) + descriptor = KVMI_DESC_IDTR; + else + descriptor = KVMI_DESC_GDTR; + } else { + if ((vmx_instruction_info >> 28) & 0x1) + descriptor = KVMI_DESC_TR; + else + descriptor = KVMI_DESC_LDTR; + } + + return kvmi_descriptor_event(vcpu, vmx_instruction_info, + exit_qualification, descriptor, store); +} + static bool valid_ept_address(struct kvm_vcpu *vcpu, u64 address) { struct vcpu_vmx *vmx = to_vmx(vcpu); @@ -8219,6 +8244,8 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { [EXIT_REASON_PML_FULL] = handle_pml_full, [EXIT_REASON_VMFUNC] = handle_vmfunc, [EXIT_REASON_PREEMPTION_TIMER] = handle_preemption_timer, + [EXIT_REASON_GDTR_IDTR] = handle_descriptor_access, + [EXIT_REASON_LDTR_TR] = handle_descriptor_access, }; static const int kvm_vmx_max_exit_handlers =