lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 1 Mar 2016 22:11:57 +0100
From:	Paolo Bonzini <pbonzini@...hat.com>
To:	Borislav Petkov <bp@...en8.de>
Cc:	Jörg Rödel <joro@...tes.org>,
	Andy Lutomirski <luto@...capital.net>, x86-ml <x86@...nel.org>,
	kvm ML <kvm@...r.kernel.org>,
	lkml <linux-kernel@...r.kernel.org>
Subject: Re: [RFC PATCH] kvm: Make KVM DF intercept configurable



On 01/03/2016 20:28, Borislav Petkov wrote:
> Hi Paolo,
> 
> so I've been hacking at early code recently and found this to be pretty
> useful. Thoughts?

I just use QEMU's binary translation mode to debug this kind of code (-d
in_asm is useful and relatively compact (because it only shows loops
once), or alternatively ept=0.  But perhaps... why not. :)  It's not
like it adds overhead.

Paolo

> This is AMD-only now but I'll extend it to Intel too, if there's
> interest.
> 
> ---
> From: Borislav Petkov <bp@...e.de>
> Date: Tue, 1 Mar 2016 14:34:28 +0100
> Subject: [RFC PATCH] kvm: Make KVM DF intercept configurable
> 
> Sometimes it is useful when testing kernels in guests to know why the
> guest triple-faults, especially if one is poking at early kernel code
> where there's no debugging output yet.
> 
> So add a module parameter which makes the guest exit on a #DF and log
> error info into a #DF tracepoint. Which turns out to be very useful:
> 
> 1. Early PF causing a DF:
> -------------------------
> 
> diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
> index 22fbf9df61bb..57d7d7a68c7d 100644
> --- a/arch/x86/kernel/head_64.S
> +++ b/arch/x86/kernel/head_64.S
> @@ -64,6 +64,8 @@ startup_64:
>          * tables and then reload them.
>          */
> 
> +       movq stack_start, %rsp
> ---
> 
> We can't read that early from stack_start because we haven't enabled
> paging yet. KVM logs:
> 
>  qemu-system-x86-9523  [001] ....  1941.666236: kvm_df: Guest DF! rIP: 0x1000000, prev exception: 0xe, error_code: 0x0
> 
> and the exception causing the #DF is a #PF (vector 0xe).
> 
> 2. #GP
> -------------------------
> 
> diff --git a/init/main.c b/init/main.c
> index 7c27de4577ed..869eb6110765 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -967,6 +969,9 @@ static int __ref kernel_init(void *unused)
>                        ramdisk_execute_command, ret);
>         }
> 
> +       load_idt(&no_idt);
> +       __asm__ __volatile__("int3");
> ---
> 
> Loading a NULL IDT and causing a debug interrupt, causes a #GP.
> 
> KVM logs:
> 
>  qemu-system-x86-12853 [000] ....  2463.500732: kvm_df: Guest DF! rIP: 0xffffffff815ba8ba, prev exception: 0xd, error_code: 0x1a
> 
> and the previous exception was a #GP (vector 0xd).
> 
> Signed-off-by: Borislav Petkov <bp@...e.de>
> ---
>  arch/x86/kvm/svm.c   | 15 +++++++++++++++
>  arch/x86/kvm/trace.h | 20 ++++++++++++++++++++
>  arch/x86/kvm/x86.c   |  1 +
>  3 files changed, 36 insertions(+)
> 
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index c13a64b7d789..09f78bbd8b47 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -205,6 +205,9 @@ module_param(npt, int, S_IRUGO);
>  static int nested = true;
>  module_param(nested, int, S_IRUGO);
>  
> +static int intercept_df = 0;
> +module_param(intercept_df, int, S_IRUGO);
> +
>  static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
>  static void svm_flush_tlb(struct kvm_vcpu *vcpu);
>  static void svm_complete_interrupts(struct vcpu_svm *svm);
> @@ -1023,6 +1026,8 @@ static void init_vmcb(struct vcpu_svm *svm)
>  	set_exception_intercept(svm, MC_VECTOR);
>  	set_exception_intercept(svm, AC_VECTOR);
>  	set_exception_intercept(svm, DB_VECTOR);
> +	if (intercept_df)
> +		set_exception_intercept(svm, DF_VECTOR);
>  
>  	set_intercept(svm, INTERCEPT_INTR);
>  	set_intercept(svm, INTERCEPT_NMI);
> @@ -1728,6 +1733,15 @@ static int nm_interception(struct vcpu_svm *svm)
>  	return 1;
>  }
>  
> +static int df_interception(struct vcpu_svm *svm)
> +{
> +	trace_kvm_df(svm->vmcb->save.rip,
> +		     svm->vcpu.arch.exception.nr,
> +		     svm->vcpu.arch.exception.has_error_code ?
> +		     svm->vcpu.arch.exception.error_code : 0);
> +	return 1;
> +}
> +
>  static bool is_erratum_383(void)
>  {
>  	int err, i;
> @@ -3308,6 +3322,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
>  	[SVM_EXIT_EXCP_BASE + UD_VECTOR]	= ud_interception,
>  	[SVM_EXIT_EXCP_BASE + PF_VECTOR]	= pf_interception,
>  	[SVM_EXIT_EXCP_BASE + NM_VECTOR]	= nm_interception,
> +	[SVM_EXIT_EXCP_BASE + DF_VECTOR]	= df_interception,
>  	[SVM_EXIT_EXCP_BASE + MC_VECTOR]	= mc_interception,
>  	[SVM_EXIT_EXCP_BASE + AC_VECTOR]	= ac_interception,
>  	[SVM_EXIT_INTR]				= intr_interception,
> diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
> index ad9f6a23f139..6143c53f7bde 100644
> --- a/arch/x86/kvm/trace.h
> +++ b/arch/x86/kvm/trace.h
> @@ -89,6 +89,26 @@ TRACE_EVENT(kvm_hv_hypercall,
>  		  __entry->outgpa)
>  );
>  
> +TRACE_EVENT(kvm_df,
> +	TP_PROTO(unsigned long rip, u8 nr, u32 error_code),
> +	TP_ARGS(rip, nr, error_code),
> +
> +	TP_STRUCT__entry(
> +		__field(	unsigned long, rip		)
> +		__field(		   u8, nr		)
> +		__field(		  u32, error_code	)
> +	),
> +
> +	TP_fast_assign(
> +		__entry->rip		= rip;
> +		__entry->nr		= nr;
> +		__entry->error_code	= error_code;
> +	),
> +
> +	TP_printk("Guest DF! rIP: 0x%lx, prev exception: 0x%x, error_code: 0x%x",
> +		  __entry->rip, __entry->nr, __entry->error_code)
> +);
> +
>  /*
>   * Tracepoint for PIO.
>   */
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index f18a08281015..49f1bd3279f2 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -8388,3 +8388,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_write_tsc_offset);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_ple_window);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pml_full);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pi_irte_update);
> +EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_df);
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ