On Thu, Feb 02, 2023 at 12:11:47PM -0800, Sami Tolvanen wrote: > On Thu, Feb 2, 2023 at 11:53 AM Kees Cook <keescook@xxxxxxxxxxxx> wrote: > > > > On Thu, Feb 02, 2023 at 11:49:42AM -0800, Sami Tolvanen wrote: > > > A quick look at Clang's source code suggests that Intrinsic::ubsantrap > > > already accepts the handler ID (from the SanitizerHandler enum) as an > > > argument and the arm64 LLVM back-end appears to encode the value as an > > > immediate for the brk instruction. I didn't confirm that this actually > > > works, but perhaps we just need to teach the kernel about the possible > > > values? > > > > Oh excellent. Yeah, if that's all that's needed here that would be > > great. What are the values? > > The arm64 brk immediate encoding seems to be "ubsantrap arg | 'U' << 8": > > https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/AArch64/AArch64InstrInfo.td#L7571 > > The argument values come from the SanitizerHandler enum, which is > populated from this list: > > https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/CodeGenFunction.h#L113 > > Therefore, according to the tests, for ubsantrap(12) we'll get brk > #0x550c, for example: > > https://github.com/llvm/llvm-project/blob/main/llvm/test/CodeGen/AArch64/ubsantrap.ll So the absolute minimal handler would look like this: diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h index 6e000113e508..3f0f0d03268b 100644 --- a/arch/arm64/include/asm/brk-imm.h +++ b/arch/arm64/include/asm/brk-imm.h @@ -28,6 +28,8 @@ #define BUG_BRK_IMM 0x800 #define KASAN_BRK_IMM 0x900 #define KASAN_BRK_MASK 0x0ff +#define UBSAN_BRK_IMM 0x5500 +#define UBSAN_BRK_MASK 0x00ff #define CFI_BRK_IMM_TARGET GENMASK(4, 0) #define CFI_BRK_IMM_TYPE GENMASK(9, 5) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 4c0caa589e12..36b917d8fa5f 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -1074,6 +1074,18 @@ static struct break_hook kasan_break_hook = { }; #endif +#ifdef CONFIG_UBSAN_TRAP +static int ubsan_handler(struct pt_regs *regs, unsigned long esr) +{ + die("Oops - UBSAN", regs, esr); +} + +static struct break_hook ubsan_break_hook = { + .fn = ubsan_handler, + .imm = UBSAN_BRK_IMM, + .mask = UBSAN_BRK_MASK, +}; +#endif #define esr_comment(esr) ((esr) & ESR_ELx_BRK64_ISS_COMMENT_MASK) @@ -1091,6 +1103,10 @@ int __init early_brk64(unsigned long addr, unsigned long esr, #ifdef CONFIG_KASAN_SW_TAGS if ((esr_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM) return kasan_handler(regs, esr) != DBG_HOOK_HANDLED; +#endif +#ifdef CONFIG_UBSAN_TRAP + if ((esr_comment(esr) & ~UBSAN_BRK_MASK) == UBSAN_BRK_IMM) + return ubsan_handler(regs, esr) != DBG_HOOK_HANDLED; #endif return bug_handler(regs, esr) != DBG_HOOK_HANDLED; } @@ -1104,6 +1120,9 @@ void __init trap_init(void) register_kernel_break_hook(&fault_break_hook); #ifdef CONFIG_KASAN_SW_TAGS register_kernel_break_hook(&kasan_break_hook); +#endif +#ifdef CONFIG_UBSAN_TRAP + register_kernel_break_hook(&ubsan_break_hook); #endif debug_traps_init(); } But we could expand ubsan_handler() to extract the SanitizerHandler enum value and report which UBSAN check was hit... -- Kees Cook