live-patching.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: live-patching@vger.kernel.org, linux-kernel@vger.kernel.org,
	x86@kernel.org, Miroslav Benes <mbenes@suse.cz>,
	Petr Mladek <pmladek@suse.com>,
	Joe Lawrence <joe.lawrence@redhat.com>,
	Jiri Kosina <jikos@kernel.org>,
	Marcos Paulo de Souza <mpdesouza@suse.com>,
	Song Liu <song@kernel.org>
Subject: Re: [RFC 20/31] objtool: Add UD1 detection
Date: Tue, 3 Sep 2024 10:17:48 +0200	[thread overview]
Message-ID: <20240903081748.GN4723@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <20e0e2662239a042a10196e8f240ce596b250ae8.1725334260.git.jpoimboe@kernel.org>

On Mon, Sep 02, 2024 at 09:00:03PM -0700, Josh Poimboeuf wrote:
> A UD1 isn't a BUG and shouldn't be treated like one.
> 
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
> ---
>  tools/objtool/arch/x86/decode.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
> index 6b34b058a821..72d55dcd3d7f 100644
> --- a/tools/objtool/arch/x86/decode.c
> +++ b/tools/objtool/arch/x86/decode.c
> @@ -528,11 +528,19 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
>  			/* sysenter, sysret */
>  			insn->type = INSN_CONTEXT_SWITCH;
>  
> -		} else if (op2 == 0x0b || op2 == 0xb9) {
> +		} else if (op2 == 0x0b) {
>  
>  			/* ud2 */
>  			insn->type = INSN_BUG;
>  
> +		} else if (op2 == 0xb9) {
> +
> +			/*
> +			 * ud1 - only used for the static call trampoline to
> +			 * stop speculation.  Basically used like an int3.
> +			 */
> +			insn->type = INSN_TRAP;
> +
>  		} else if (op2 == 0x0d || op2 == 0x1f) {
>  
>  			/* nopl/nopw */

We recently grew more UD1 usage...

---
commit 7424fc6b86c8980a87169e005f5cd4438d18efe6
Author: Gatlin Newhouse <gatlin.newhouse@gmail.com>
Date:   Wed Jul 24 00:01:55 2024 +0000

    x86/traps: Enable UBSAN traps on x86
    
    Currently ARM64 extracts which specific sanitizer has caused a trap via
    encoded data in the trap instruction. Clang on x86 currently encodes the
    same data in the UD1 instruction but x86 handle_bug() and
    is_valid_bugaddr() currently only look at UD2.
    
    Bring x86 to parity with ARM64, similar to commit 25b84002afb9 ("arm64:
    Support Clang UBSAN trap codes for better reporting"). See the llvm
    links for information about the code generation.
    
    Enable the reporting of UBSAN sanitizer details on x86 compiled with clang
    when CONFIG_UBSAN_TRAP=y by analysing UD1 and retrieving the type immediate
    which is encoded by the compiler after the UD1.
    
    [ tglx: Simplified it by moving the printk() into handle_bug() ]
    
    Signed-off-by: Gatlin Newhouse <gatlin.newhouse@gmail.com>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Cc: Kees Cook <keescook@chromium.org>
    Link: https://lore.kernel.org/all/20240724000206.451425-1-gatlin.newhouse@gmail.com
    Link: https://github.com/llvm/llvm-project/commit/c5978f42ec8e9#diff-bb68d7cd885f41cfc35843998b0f9f534adb60b415f647109e597ce448e92d9f
    Link: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/X86/X86InstrSystem.td#L27

diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
index a3ec87d198ac..806649c7f23d 100644
--- a/arch/x86/include/asm/bug.h
+++ b/arch/x86/include/asm/bug.h
@@ -13,6 +13,18 @@
 #define INSN_UD2	0x0b0f
 #define LEN_UD2		2
 
+/*
+ * In clang we have UD1s reporting UBSAN failures on X86, 64 and 32bit.
+ */
+#define INSN_ASOP		0x67
+#define OPCODE_ESCAPE		0x0f
+#define SECOND_BYTE_OPCODE_UD1	0xb9
+#define SECOND_BYTE_OPCODE_UD2	0x0b
+
+#define BUG_NONE		0xffff
+#define BUG_UD1			0xfffe
+#define BUG_UD2			0xfffd
+
 #ifdef CONFIG_GENERIC_BUG
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 4fa0b17e5043..415881607c5d 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -42,6 +42,7 @@
 #include <linux/hardirq.h>
 #include <linux/atomic.h>
 #include <linux/iommu.h>
+#include <linux/ubsan.h>
 
 #include <asm/stacktrace.h>
 #include <asm/processor.h>
@@ -91,6 +92,47 @@ __always_inline int is_valid_bugaddr(unsigned long addr)
 	return *(unsigned short *)addr == INSN_UD2;
 }
 
+/*
+ * Check for UD1 or UD2, accounting for Address Size Override Prefixes.
+ * If it's a UD1, get the ModRM byte to pass along to UBSan.
+ */
+__always_inline int decode_bug(unsigned long addr, u32 *imm)
+{
+	u8 v;
+
+	if (addr < TASK_SIZE_MAX)
+		return BUG_NONE;
+
+	v = *(u8 *)(addr++);
+	if (v == INSN_ASOP)
+		v = *(u8 *)(addr++);
+	if (v != OPCODE_ESCAPE)
+		return BUG_NONE;
+
+	v = *(u8 *)(addr++);
+	if (v == SECOND_BYTE_OPCODE_UD2)
+		return BUG_UD2;
+
+	if (!IS_ENABLED(CONFIG_UBSAN_TRAP) || v != SECOND_BYTE_OPCODE_UD1)
+		return BUG_NONE;
+
+	/* Retrieve the immediate (type value) for the UBSAN UD1 */
+	v = *(u8 *)(addr++);
+	if (X86_MODRM_RM(v) == 4)
+		addr++;
+
+	*imm = 0;
+	if (X86_MODRM_MOD(v) == 1)
+		*imm = *(u8 *)addr;
+	else if (X86_MODRM_MOD(v) == 2)
+		*imm = *(u32 *)addr;
+	else
+		WARN_ONCE(1, "Unexpected MODRM_MOD: %u\n", X86_MODRM_MOD(v));
+
+	return BUG_UD1;
+}
+
+
 static nokprobe_inline int
 do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str,
 		  struct pt_regs *regs,	long error_code)
@@ -216,6 +258,8 @@ static inline void handle_invalid_op(struct pt_regs *regs)
 static noinstr bool handle_bug(struct pt_regs *regs)
 {
 	bool handled = false;
+	int ud_type;
+	u32 imm;
 
 	/*
 	 * Normally @regs are unpoisoned by irqentry_enter(), but handle_bug()
@@ -223,7 +267,8 @@ static noinstr bool handle_bug(struct pt_regs *regs)
 	 * irqentry_enter().
 	 */
 	kmsan_unpoison_entry_regs(regs);
-	if (!is_valid_bugaddr(regs->ip))
+	ud_type = decode_bug(regs->ip, &imm);
+	if (ud_type == BUG_NONE)
 		return handled;
 
 	/*
@@ -236,10 +281,14 @@ static noinstr bool handle_bug(struct pt_regs *regs)
 	 */
 	if (regs->flags & X86_EFLAGS_IF)
 		raw_local_irq_enable();
-	if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN ||
-	    handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) {
-		regs->ip += LEN_UD2;
-		handled = true;
+	if (ud_type == BUG_UD2) {
+		if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN ||
+		    handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) {
+			regs->ip += LEN_UD2;
+			handled = true;
+		}
+	} else if (IS_ENABLED(CONFIG_UBSAN_TRAP)) {
+		pr_crit("%s at %pS\n", report_ubsan_failure(regs, imm), (void *)regs->ip);
 	}
 	if (regs->flags & X86_EFLAGS_IF)
 		raw_local_irq_disable();
diff --git a/include/linux/ubsan.h b/include/linux/ubsan.h
index bff7445498de..d8219cbe09ff 100644
--- a/include/linux/ubsan.h
+++ b/include/linux/ubsan.h
@@ -4,6 +4,11 @@
 
 #ifdef CONFIG_UBSAN_TRAP
 const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type);
+#else
+static inline const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type)
+{
+	return NULL;
+}
 #endif
 
 #endif
diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan
index bdda600f8dfb..1d4aa7a83b3a 100644
--- a/lib/Kconfig.ubsan
+++ b/lib/Kconfig.ubsan
@@ -29,8 +29,8 @@ config UBSAN_TRAP
 
 	  Also note that selecting Y will cause your kernel to Oops
 	  with an "illegal instruction" error with no further details
-	  when a UBSAN violation occurs. (Except on arm64, which will
-	  report which Sanitizer failed.) This may make it hard to
+	  when a UBSAN violation occurs. (Except on arm64 and x86, which
+	  will report which Sanitizer failed.) This may make it hard to
 	  determine whether an Oops was caused by UBSAN or to figure
 	  out the details of a UBSAN violation. It makes the kernel log
 	  output less useful for bug reports.

  reply	other threads:[~2024-09-03  8:17 UTC|newest]

Thread overview: 94+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-03  3:59 [RFC 00/31] objtool, livepatch: Livepatch module generation Josh Poimboeuf
2024-09-03  3:59 ` [RFC 01/31] x86/alternative: Refactor INT3 call emulation selftest Josh Poimboeuf
2024-09-03  3:59 ` [RFC 02/31] x86/module: Improve relocation error messages Josh Poimboeuf
2024-09-03  3:59 ` [RFC 03/31] x86/kprobes: Remove STACK_FRAME_NON_STANDARD annotation Josh Poimboeuf
2024-09-03  3:59 ` [RFC 04/31] kernel/sys: Don't reference UTS_RELEASE directly Josh Poimboeuf
2024-09-03  3:59 ` [RFC 05/31] x86/compiler: Tweak __UNIQUE_ID naming Josh Poimboeuf
2024-09-03  7:56   ` Peter Zijlstra
2024-09-04  2:01     ` Josh Poimboeuf
2024-09-08 19:43     ` David Laight
2024-09-03  3:59 ` [RFC 06/31] elfnote: Use __UNIQUE_ID() for note symbols Josh Poimboeuf
2024-09-03  3:59 ` [RFC 07/31] kbuild: Remove "kmod" prefix from __KBUILD_MODNAME Josh Poimboeuf
2024-09-03  7:58   ` Peter Zijlstra
2024-09-04  2:11     ` Josh Poimboeuf
2024-09-04  7:53       ` Peter Zijlstra
2024-09-03  3:59 ` [RFC 08/31] objtool: Remove .parainstructions reference Josh Poimboeuf
2024-09-03  3:59 ` [RFC 09/31] objtool: Const string cleanup Josh Poimboeuf
2024-09-03  3:59 ` [RFC 10/31] objtool: Use 'struct elf' in elf macros Josh Poimboeuf
2024-09-03  3:59 ` [RFC 11/31] objtool: Add section/symbol type helpers Josh Poimboeuf
2024-09-03  3:59 ` [RFC 12/31] objtool: 'objname' refactoring Josh Poimboeuf
2024-09-03  3:59 ` [RFC 13/31] objtool: Support references to all symbol types in special sections Josh Poimboeuf
2024-09-03  3:59 ` [RFC 14/31] objtool: Refactor add_jump_destinations() Josh Poimboeuf
2024-09-03  3:59 ` [RFC 15/31] objtool: Interval tree cleanups Josh Poimboeuf
2024-09-03  3:59 ` [RFC 16/31] objtool: Simplify fatal error handling Josh Poimboeuf
2024-09-03  4:00 ` [RFC 17/31] objtool: Open up the elf API Josh Poimboeuf
2024-09-03  4:00 ` [RFC 18/31] objtool: Disallow duplicate prefix symbols Josh Poimboeuf
2024-09-03  4:00 ` [RFC 19/31] objtool: Add elf_create_file() Josh Poimboeuf
2024-09-03  4:00 ` [RFC 20/31] objtool: Add UD1 detection Josh Poimboeuf
2024-09-03  8:17   ` Peter Zijlstra [this message]
2024-09-04  2:25     ` Josh Poimboeuf
2024-09-03  4:00 ` [RFC 21/31] objtool: Fix x86 addend calcuation Josh Poimboeuf
2024-09-04  9:24   ` laokz
2024-09-04 16:15     ` Josh Poimboeuf
2024-09-03  4:00 ` [RFC 22/31] objtool: Make find_symbol_containing() less arbitrary Josh Poimboeuf
2024-09-03  4:00 ` [RFC 23/31] objtool: Handle __pa_symbol() relocations Josh Poimboeuf
2024-09-03  4:00 ` [RFC 24/31] objtool: Make STACK_FRAME_NON_STANDARD consistent Josh Poimboeuf
2024-09-03  4:00 ` [RFC 25/31] objtool: Fix interval tree insertion for zero-length symbols Josh Poimboeuf
2024-09-03  4:00 ` [RFC 26/31] objtool: Make interval tree functions "static inline" Josh Poimboeuf
2024-09-03  4:00 ` [RFC 27/31] objtool: Fix weak symbol detection Josh Poimboeuf
2024-09-03  8:26   ` Peter Zijlstra
2024-09-04  3:55     ` Josh Poimboeuf
2024-09-04  7:42       ` Peter Zijlstra
2024-09-04 16:03         ` Josh Poimboeuf
2024-09-03  4:00 ` [RFC 28/31] x86/alternative: Create symbols for special section entries Josh Poimboeuf
2024-09-03  8:29   ` Peter Zijlstra
2024-09-04  4:28     ` Josh Poimboeuf
2024-09-04  8:08       ` Peter Zijlstra
2024-09-04 16:13         ` Josh Poimboeuf
2024-09-04 12:39       ` Borislav Petkov
2024-09-04 16:44         ` Josh Poimboeuf
2024-09-06 10:19           ` Borislav Petkov
2024-09-06 16:53             ` Josh Poimboeuf
2024-09-06  6:51   ` [RFC 28/31] x86/alternative: Create symbols for special section entrie Weinan Liu
2024-09-07  6:28     ` Josh Poimboeuf
2024-09-03  4:00 ` [RFC 29/31] objtool: Calculate function checksums Josh Poimboeuf
2024-09-04  7:54   ` Peter Zijlstra
2024-09-04 16:11     ` Josh Poimboeuf
2024-09-03  4:00 ` [RFC 30/31] livepatch: Enable -ffunction-sections -fdata-sections Josh Poimboeuf
2024-09-03  4:00 ` [RFC 31/31] objtool, livepatch: Livepatch module generation Josh Poimboeuf
2024-09-04 21:38   ` Jeff Johnson
2024-09-05  4:15     ` Josh Poimboeuf
2024-09-12  2:39   ` laokz
2024-09-03 17:32 ` [RFC 00/31] " Song Liu
2024-09-04  4:30   ` Josh Poimboeuf
2024-09-04  5:26     ` Song Liu
2024-09-04  6:37       ` Josh Poimboeuf
2024-09-04  7:09         ` Josh Poimboeuf
2024-09-04 20:23           ` Song Liu
2024-09-04 20:59             ` Josh Poimboeuf
2024-09-04 21:32               ` Song Liu
2024-09-05  4:13               ` Josh Poimboeuf
2024-09-05  7:13                 ` Josh Poimboeuf
2024-09-05 21:34                   ` Song Liu
2024-09-07  6:46   ` Josh Poimboeuf
2024-09-07 17:43     ` Song Liu
2024-09-07 20:14       ` Josh Poimboeuf
2024-09-08  5:04         ` Song Liu
2024-09-09 21:19           ` Josh Poimboeuf
2024-09-09 21:43             ` Song Liu
2024-09-06 13:56 ` Joe Lawrence
2024-09-06 17:00   ` Josh Poimboeuf
2024-09-06 21:01     ` Joe Lawrence
2024-09-06 22:45       ` Josh Poimboeuf
2024-09-07  1:47   ` Josh Poimboeuf
2024-09-07 14:17     ` Joe Lawrence
2024-09-11  7:39 ` Josh Poimboeuf
2024-09-12 13:44   ` Joe Lawrence
2024-09-13 14:39     ` Joe Lawrence
2024-09-13 23:09       ` Josh Poimboeuf
2024-09-11 13:27 ` Petr Mladek
2024-09-11 16:20   ` Josh Poimboeuf
2024-09-12 16:05     ` Song Liu
2024-09-13 18:16       ` [External] " A K M Fazla Mehrab .
2024-09-17  7:12     ` Petr Mladek
2024-09-23  2:29     ` Chen Zhongjin

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=20240903081748.GN4723@noisy.programming.kicks-ass.net \
    --to=peterz@infradead.org \
    --cc=jikos@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=mpdesouza@suse.com \
    --cc=pmladek@suse.com \
    --cc=song@kernel.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).