Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'x86-core-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 core update from Thomas Gleixner:
"Enable UBSAN traps for x86, which provides better reporting through
metadata encodeded into UD1"

* tag 'x86-core-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/traps: Enable UBSAN traps on x86

+73 -7
+12
arch/x86/include/asm/bug.h
··· 13 13 #define INSN_UD2 0x0b0f 14 14 #define LEN_UD2 2 15 15 16 + /* 17 + * In clang we have UD1s reporting UBSAN failures on X86, 64 and 32bit. 18 + */ 19 + #define INSN_ASOP 0x67 20 + #define OPCODE_ESCAPE 0x0f 21 + #define SECOND_BYTE_OPCODE_UD1 0xb9 22 + #define SECOND_BYTE_OPCODE_UD2 0x0b 23 + 24 + #define BUG_NONE 0xffff 25 + #define BUG_UD1 0xfffe 26 + #define BUG_UD2 0xfffd 27 + 16 28 #ifdef CONFIG_GENERIC_BUG 17 29 18 30 #ifdef CONFIG_X86_32
+54 -5
arch/x86/kernel/traps.c
··· 42 42 #include <linux/hardirq.h> 43 43 #include <linux/atomic.h> 44 44 #include <linux/iommu.h> 45 + #include <linux/ubsan.h> 45 46 46 47 #include <asm/stacktrace.h> 47 48 #include <asm/processor.h> ··· 91 90 */ 92 91 return *(unsigned short *)addr == INSN_UD2; 93 92 } 93 + 94 + /* 95 + * Check for UD1 or UD2, accounting for Address Size Override Prefixes. 96 + * If it's a UD1, get the ModRM byte to pass along to UBSan. 97 + */ 98 + __always_inline int decode_bug(unsigned long addr, u32 *imm) 99 + { 100 + u8 v; 101 + 102 + if (addr < TASK_SIZE_MAX) 103 + return BUG_NONE; 104 + 105 + v = *(u8 *)(addr++); 106 + if (v == INSN_ASOP) 107 + v = *(u8 *)(addr++); 108 + if (v != OPCODE_ESCAPE) 109 + return BUG_NONE; 110 + 111 + v = *(u8 *)(addr++); 112 + if (v == SECOND_BYTE_OPCODE_UD2) 113 + return BUG_UD2; 114 + 115 + if (!IS_ENABLED(CONFIG_UBSAN_TRAP) || v != SECOND_BYTE_OPCODE_UD1) 116 + return BUG_NONE; 117 + 118 + /* Retrieve the immediate (type value) for the UBSAN UD1 */ 119 + v = *(u8 *)(addr++); 120 + if (X86_MODRM_RM(v) == 4) 121 + addr++; 122 + 123 + *imm = 0; 124 + if (X86_MODRM_MOD(v) == 1) 125 + *imm = *(u8 *)addr; 126 + else if (X86_MODRM_MOD(v) == 2) 127 + *imm = *(u32 *)addr; 128 + else 129 + WARN_ONCE(1, "Unexpected MODRM_MOD: %u\n", X86_MODRM_MOD(v)); 130 + 131 + return BUG_UD1; 132 + } 133 + 94 134 95 135 static nokprobe_inline int 96 136 do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str, ··· 258 216 static noinstr bool handle_bug(struct pt_regs *regs) 259 217 { 260 218 bool handled = false; 219 + int ud_type; 220 + u32 imm; 261 221 262 222 /* 263 223 * Normally @regs are unpoisoned by irqentry_enter(), but handle_bug() ··· 267 223 * irqentry_enter(). 268 224 */ 269 225 kmsan_unpoison_entry_regs(regs); 270 - if (!is_valid_bugaddr(regs->ip)) 226 + ud_type = decode_bug(regs->ip, &imm); 227 + if (ud_type == BUG_NONE) 271 228 return handled; 272 229 273 230 /* ··· 281 236 */ 282 237 if (regs->flags & X86_EFLAGS_IF) 283 238 raw_local_irq_enable(); 284 - if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN || 285 - handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) { 286 - regs->ip += LEN_UD2; 287 - handled = true; 239 + if (ud_type == BUG_UD2) { 240 + if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN || 241 + handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) { 242 + regs->ip += LEN_UD2; 243 + handled = true; 244 + } 245 + } else if (IS_ENABLED(CONFIG_UBSAN_TRAP)) { 246 + pr_crit("%s at %pS\n", report_ubsan_failure(regs, imm), (void *)regs->ip); 288 247 } 289 248 if (regs->flags & X86_EFLAGS_IF) 290 249 raw_local_irq_disable();
+5
include/linux/ubsan.h
··· 4 4 5 5 #ifdef CONFIG_UBSAN_TRAP 6 6 const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type); 7 + #else 8 + static inline const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type) 9 + { 10 + return NULL; 11 + } 7 12 #endif 8 13 9 14 #endif
+2 -2
lib/Kconfig.ubsan
··· 29 29 30 30 Also note that selecting Y will cause your kernel to Oops 31 31 with an "illegal instruction" error with no further details 32 - when a UBSAN violation occurs. (Except on arm64, which will 33 - report which Sanitizer failed.) This may make it hard to 32 + when a UBSAN violation occurs. (Except on arm64 and x86, which 33 + will report which Sanitizer failed.) This may make it hard to 34 34 determine whether an Oops was caused by UBSAN or to figure 35 35 out the details of a UBSAN violation. It makes the kernel log 36 36 output less useful for bug reports.