All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@kernel.org>
To: Jann Horn <jannh@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	"H. Peter Anvin" <hpa@zytor.com>,
	x86@kernel.org, Andrey Ryabinin <aryabinin@virtuozzo.com>,
	Alexander Potapenko <glider@google.com>,
	Dmitry Vyukov <dvyukov@google.com>,
	kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org,
	Andrey Konovalov <andreyknvl@google.com>,
	Andy Lutomirski <luto@kernel.org>,
	Sean Christopherson <sean.j.christopherson@intel.com>,
	Andi Kleen <ak@linux.intel.com>
Subject: Re: [PATCH v3 2/4] x86/traps: Print non-canonical address on #GP
Date: Wed, 20 Nov 2019 12:18:59 +0100	[thread overview]
Message-ID: <20191120111859.GA115930@gmail.com> (raw)
In-Reply-To: <20191120103613.63563-2-jannh@google.com>


* Jann Horn <jannh@google.com> wrote:

> A frequent cause of #GP exceptions are memory accesses to non-canonical
> addresses. Unlike #PF, #GP doesn't come with a fault address in CR2, so
> the kernel doesn't currently print the fault address for #GP.
> Luckily, we already have the necessary infrastructure for decoding X86
> instructions and computing the memory address that is being accessed;
> hook it up to the #GP handler so that we can figure out whether the #GP
> looks like it was caused by a non-canonical address, and if so, print
> that address.
> 
> While it is already possible to compute the faulting address manually by
> disassembling the opcode dump and evaluating the instruction against the
> register dump, this should make it slightly easier to identify crashes
> at a glance.
> 
> Signed-off-by: Jann Horn <jannh@google.com>
> ---
> 
> Notes:
>     v2:
>      - print different message for segment-related GP (Borislav)
>      - rewrite check for non-canonical address (Sean)
>      - make it clear we don't know for sure why the GP happened (Andy)
>     v3:
>      - change message format to one line (Borislav)
>     
>     I have already sent a patch to syzkaller that relaxes their parsing of GPF
>     messages (https://github.com/google/syzkaller/commit/432c7650) such that
>     changes like the one in this patch don't break it.
>     That patch has already made its way into syzbot's syzkaller instances
>     according to <https://syzkaller.appspot.com/upstream>.
> 
>  arch/x86/kernel/traps.c | 56 ++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 53 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> index c90312146da0..19afedcd6f4e 100644
> --- a/arch/x86/kernel/traps.c
> +++ b/arch/x86/kernel/traps.c
> @@ -56,6 +56,8 @@
>  #include <asm/mpx.h>
>  #include <asm/vm86.h>
>  #include <asm/umip.h>
> +#include <asm/insn.h>
> +#include <asm/insn-eval.h>
>  
>  #ifdef CONFIG_X86_64
>  #include <asm/x86_init.h>
> @@ -509,11 +511,45 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code)
>  	do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, error_code, 0, NULL);
>  }
>  
> +/*
> + * On 64-bit, if an uncaught #GP occurs while dereferencing a non-canonical
> + * address, return that address.
> + */
> +static unsigned long get_kernel_gp_address(struct pt_regs *regs)
> +{
> +#ifdef CONFIG_X86_64
> +	u8 insn_bytes[MAX_INSN_SIZE];
> +	struct insn insn;
> +	unsigned long addr_ref;
> +
> +	if (probe_kernel_read(insn_bytes, (void *)regs->ip, MAX_INSN_SIZE))
> +		return 0;
> +
> +	kernel_insn_init(&insn, insn_bytes, MAX_INSN_SIZE);
> +	insn_get_modrm(&insn);
> +	insn_get_sib(&insn);
> +	addr_ref = (unsigned long)insn_get_addr_ref(&insn, regs);

I had to look twice to realize that the 'insn_bytes' isn't an integer 
that shows the number of bytes in the instruction, but the instruction 
buffer itself.

Could we please do s/insn_bytes/insn_buf or such?

> +
> +	/* Bail out if insn_get_addr_ref() failed or we got a kernel address. */
> +	if (addr_ref >= ~__VIRTUAL_MASK)
> +		return 0;
> +
> +	/* Bail out if the entire operand is in the canonical user half. */
> +	if (addr_ref + insn.opnd_bytes - 1 <= __VIRTUAL_MASK)
> +		return 0;

BTW., it would be nice to split this logic in two: return the faulting 
address to do_general_protection(), and print it out both for 
non-canonical and canonical addresses as well -and use the canonical 
check to *additionally* print out a short note when the operand is 
non-canonical?

> +#define GPFSTR "general protection fault"
>  dotraplinkage void

Please separate macro and function definitions by an additional newline.

>  do_general_protection(struct pt_regs *regs, long error_code)
>  {
> -	const char *desc = "general protection fault";
>  	struct task_struct *tsk;
> +	char desc[90] = GPFSTR;


How was this maximum string length of '90' derived? In what way will that 
have to change if someone changes the message?

Thanks,

	Ingo

  reply	other threads:[~2019-11-20 11:19 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-20 10:36 [PATCH v3 1/4] x86/insn-eval: Add support for 64-bit kernel mode Jann Horn
2019-11-20 10:36 ` [PATCH v3 2/4] x86/traps: Print non-canonical address on #GP Jann Horn
2019-11-20 11:18   ` Ingo Molnar [this message]
2019-11-20 11:24     ` Borislav Petkov
2019-11-20 12:25       ` Jann Horn
2019-11-20 12:41         ` Borislav Petkov
2019-11-20 13:16         ` Ingo Molnar
2019-11-20 13:23           ` Jann Horn
2019-11-20 14:05             ` Ingo Molnar
2019-11-20 12:14     ` Jann Horn
2019-11-20 12:30       ` Ingo Molnar
2019-11-20 12:39         ` Borislav Petkov
2019-11-20 12:42           ` Jann Horn
2019-11-20 13:28           ` Ingo Molnar
2019-11-20 13:39             ` Borislav Petkov
2019-11-20 16:21               ` Sean Christopherson
2019-11-20 17:37                 ` Borislav Petkov
2019-11-20 10:36 ` [PATCH v3 3/4] x86/dumpstack: Split out header line printing from __die() Jann Horn
2019-11-20 10:36 ` [PATCH v3 4/4] x86/kasan: Print original address on #GP Jann Horn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191120111859.GA115930@gmail.com \
    --to=mingo@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=andreyknvl@google.com \
    --cc=aryabinin@virtuozzo.com \
    --cc=bp@alien8.de \
    --cc=dvyukov@google.com \
    --cc=glider@google.com \
    --cc=hpa@zytor.com \
    --cc=jannh@google.com \
    --cc=kasan-dev@googlegroups.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mingo@redhat.com \
    --cc=sean.j.christopherson@intel.com \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.