Inform the guest introspection tool that a breakpoint instruction (INT3) is being executed. These one-byte intructions are placed in the slack space of various functions and used as notification for when the OS or an application has reached a certain state or is trying to perform a certain operation (like creating a process). Signed-off-by: Mihai Donțu <mdontu@xxxxxxxxxxxxxxx> Signed-off-by: Nicușor Cîțu <ncitu@xxxxxxxxxxxxxxx> --- arch/x86/kvm/svm.c | 4 ++++ arch/x86/kvm/vmx.c | 15 +++++++++++---- arch/x86/kvm/x86.c | 7 +++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index d6c7680e224b..17902a9e518d 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -2721,6 +2721,10 @@ static int bp_interception(struct vcpu_svm *svm) { struct kvm_run *kvm_run = svm->vcpu.run; + if (!kvmi_breakpoint_event(&svm->vcpu, + svm->vmcb->save.cs.base + svm->vmcb->save.rip)) + return 1; + kvm_run->exit_reason = KVM_EXIT_DEBUG; kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip; kvm_run->debug.arch.exception = BP_VECTOR; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index fd92267a7a65..72d4b521fed7 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -7088,7 +7088,7 @@ static int handle_exception(struct kvm_vcpu *vcpu) struct vcpu_vmx *vmx = to_vmx(vcpu); struct kvm_run *kvm_run = vcpu->run; u32 intr_info, ex_no, error_code; - unsigned long cr2, rip, dr6; + unsigned long cr2, dr6; u32 vect_info; enum emulation_result er; @@ -7166,7 +7166,10 @@ static int handle_exception(struct kvm_vcpu *vcpu) kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1; kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7); /* fall through */ - case BP_VECTOR: + case BP_VECTOR: { + unsigned long gva = vmcs_readl(GUEST_CS_BASE) + + kvm_rip_read(vcpu); + /* * Update instruction length as we may reinject #BP from * user space while in guest debugging mode. Reading it for @@ -7174,11 +7177,15 @@ static int handle_exception(struct kvm_vcpu *vcpu) */ vmx->vcpu.arch.event_exit_inst_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN); + + if (!kvmi_breakpoint_event(vcpu, gva)) + return 1; + kvm_run->exit_reason = KVM_EXIT_DEBUG; - rip = kvm_rip_read(vcpu); - kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip; + kvm_run->debug.arch.pc = gva; kvm_run->debug.arch.exception = ex_no; break; + } default: kvm_run->exit_reason = KVM_EXIT_EXCEPTION; kvm_run->ex.exception = ex_no; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6ab052fdb786..b1cbcf44cf70 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8546,6 +8546,13 @@ int kvm_arch_vcpu_set_guest_debug(struct kvm_vcpu *vcpu, kvm_queue_exception(vcpu, BP_VECTOR); } +#ifdef CONFIG_KVM_INTROSPECTION + if (kvmi_bp_intercepted(vcpu, dbg->control)) { + ret = -EBUSY; + goto out; + } +#endif + /* * Read rflags as long as potentially injected trace flags are still * filtered out.