Skip to content

Commit d154b2a

Browse files
mrutland-armroxanan1996
authored andcommitted
arm64: rework BTI exception handling
BugLink: https://bugs.launchpad.net/bugs/2046008 commit 830a2a4 upstream. If a BTI exception is taken from EL1, the entry code will treat this as an unhandled exception and will panic() the kernel. This is inconsistent with the way we handle FPAC exceptions, which have a dedicated handler and only necessarily kill the thread from which the exception was taken from, and we don't log all the information that could be relevant to debug the issue. The code in do_bti() has: BUG_ON(!user_mode(regs)); ... and it seems like the intent was to call this for EL1 BTI exceptions, as with FPAC, but this was omitted due to an oversight. This patch adds separate EL0 and EL1 BTI exception handlers, with the latter calling die() directly to report the original context the BTI exception was taken from. This matches our handling of FPAC exceptions. Prior to this patch, a BTI failure is reported as: | Unhandled 64-bit el1h sync exception on CPU0, ESR 0x0000000034000002 -- BTI | CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.19.0-rc3-00131-g7d937ff0221d-dirty #9 | Hardware name: linux,dummy-virt (DT) | pstate: 20400809 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=-c) | pc : test_bti_callee+0x4/0x10 | lr : test_bti_caller+0x1c/0x28 | sp : ffff80000800bdf0 | x29: ffff80000800bdf0 x28: 0000000000000000 x27: 0000000000000000 | x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000 | x23: ffff80000a2b8000 x22: 0000000000000000 x21: 0000000000000000 | x20: ffff8000099fa5b0 x19: ffff800009ff7000 x18: fffffbfffda37000 | x17: 3120676e696d7573 x16: 7361202c6e6f6974 x15: 0000000041a90000 | x14: 0040000000000041 x13: 0040000000000001 x12: ffff000001a90000 | x11: fffffbfffda37480 x10: 0068000000000703 x9 : 0001000040000000 | x8 : 0000000000090000 x7 : 0068000000000f03 x6 : 0060000000000f83 | x5 : ffff80000a2b6000 x4 : ffff0000028d0000 x3 : ffff800009f78378 | x2 : 0000000000000000 x1 : 0000000040210000 x0 : ffff8000080257e4 | Kernel panic - not syncing: Unhandled exception | CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.19.0-rc3-00131-g7d937ff0221d-dirty #9 | Hardware name: linux,dummy-virt (DT) | Call trace: | dump_backtrace.part.0+0xcc/0xe0 | show_stack+0x18/0x5c | dump_stack_lvl+0x64/0x80 | dump_stack+0x18/0x34 | panic+0x170/0x360 | arm64_exit_nmi.isra.0+0x0/0x80 | el1h_64_sync_handler+0x64/0xd0 | el1h_64_sync+0x64/0x68 | test_bti_callee+0x4/0x10 | smp_cpus_done+0xb0/0xbc | smp_init+0x7c/0x8c | kernel_init_freeable+0x128/0x28c | kernel_init+0x28/0x13c | ret_from_fork+0x10/0x20 With this patch applied, a BTI failure is reported as: | Internal error: Oops - BTI: 0000000034000002 [#1] PREEMPT SMP | Modules linked in: | CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.19.0-rc3-00132-g0ad98265d582-dirty #8 | Hardware name: linux,dummy-virt (DT) | pstate: 20400809 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=-c) | pc : test_bti_callee+0x4/0x10 | lr : test_bti_caller+0x1c/0x28 | sp : ffff80000800bdf0 | x29: ffff80000800bdf0 x28: 0000000000000000 x27: 0000000000000000 | x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000 | x23: ffff80000a2b8000 x22: 0000000000000000 x21: 0000000000000000 | x20: ffff8000099fa5b0 x19: ffff800009ff7000 x18: fffffbfffda37000 | x17: 3120676e696d7573 x16: 7361202c6e6f6974 x15: 0000000041a90000 | x14: 0040000000000041 x13: 0040000000000001 x12: ffff000001a90000 | x11: fffffbfffda37480 x10: 0068000000000703 x9 : 0001000040000000 | x8 : 0000000000090000 x7 : 0068000000000f03 x6 : 0060000000000f83 | x5 : ffff80000a2b6000 x4 : ffff0000028d0000 x3 : ffff800009f78378 | x2 : 0000000000000000 x1 : 0000000040210000 x0 : ffff800008025804 | Call trace: | test_bti_callee+0x4/0x10 | smp_cpus_done+0xb0/0xbc | smp_init+0x7c/0x8c | kernel_init_freeable+0x128/0x28c | kernel_init+0x28/0x13c | ret_from_fork+0x10/0x20 | Code: d50323bf d53cd040 d65f03c0 d503233f (d50323bf) Signed-off-by: Mark Rutland <[email protected]> Reviewed-by: Mark Brown <[email protected]> Reviewed-by: Anshuman Khandual <[email protected]> Cc: Alexandru Elisei <[email protected]> Cc: Amit Daniel Kachhap <[email protected]> Cc: James Morse <[email protected]> Cc: Will Deacon <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]> Signed-off-by: Jinjie Ruan <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Kamal Mostafa <[email protected]> Signed-off-by: Stefan Bader <[email protected]>
1 parent d712669 commit d154b2a

File tree

3 files changed

+22
-5
lines changed

3 files changed

+22
-5
lines changed

arch/arm64/include/asm/exception.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ asmlinkage void asm_exit_to_user_mode(struct pt_regs *regs);
5959

6060
void do_mem_abort(unsigned long far, unsigned long esr, struct pt_regs *regs);
6161
void do_undefinstr(struct pt_regs *regs, unsigned long esr);
62-
void do_bti(struct pt_regs *regs);
62+
void do_el0_bti(struct pt_regs *regs);
63+
void do_el1_bti(struct pt_regs *regs, unsigned long esr);
6364
void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr,
6465
struct pt_regs *regs);
6566
void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs);

arch/arm64/kernel/entry-common.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,15 @@ static void noinstr el1_undef(struct pt_regs *regs, unsigned long esr)
380380
exit_to_kernel_mode(regs);
381381
}
382382

383+
static void noinstr el1_bti(struct pt_regs *regs, unsigned long esr)
384+
{
385+
enter_from_kernel_mode(regs);
386+
local_daif_inherit(regs);
387+
do_el1_bti(regs, esr);
388+
local_daif_mask();
389+
exit_to_kernel_mode(regs);
390+
}
391+
383392
static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
384393
{
385394
unsigned long far = read_sysreg(far_el1);
@@ -419,6 +428,9 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
419428
case ESR_ELx_EC_UNKNOWN:
420429
el1_undef(regs, esr);
421430
break;
431+
case ESR_ELx_EC_BTI:
432+
el1_bti(regs, esr);
433+
break;
422434
case ESR_ELx_EC_BREAKPT_CUR:
423435
case ESR_ELx_EC_SOFTSTP_CUR:
424436
case ESR_ELx_EC_WATCHPT_CUR:
@@ -566,7 +578,7 @@ static void noinstr el0_bti(struct pt_regs *regs)
566578
{
567579
enter_from_user_mode(regs);
568580
local_daif_restore(DAIF_PROCCTX);
569-
do_bti(regs);
581+
do_el0_bti(regs);
570582
exit_to_user_mode(regs);
571583
}
572584

arch/arm64/kernel/traps.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,12 +502,16 @@ void do_undefinstr(struct pt_regs *regs, unsigned long esr)
502502
}
503503
NOKPROBE_SYMBOL(do_undefinstr);
504504

505-
void do_bti(struct pt_regs *regs)
505+
void do_el0_bti(struct pt_regs *regs)
506506
{
507-
BUG_ON(!user_mode(regs));
508507
force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0);
509508
}
510-
NOKPROBE_SYMBOL(do_bti);
509+
510+
void do_el1_bti(struct pt_regs *regs, unsigned long esr)
511+
{
512+
die("Oops - BTI", regs, esr);
513+
}
514+
NOKPROBE_SYMBOL(do_el1_bti);
511515

512516
void do_el0_fpac(struct pt_regs *regs, unsigned long esr)
513517
{

0 commit comments

Comments
 (0)