Skip to content

Commit d712669

Browse files
mrutland-armroxanan1996
authored andcommitted
arm64: rework FPAC exception handling
BugLink: https://bugs.launchpad.net/bugs/2046008 commit a1fafa3 upstream. If an FPAC exception is taken from EL1, the entry code will call do_ptrauth_fault(), where due to: BUG_ON(!user_mode(regs)) ... the kernel will report a problem within do_ptrauth_fault() rather than reporting the original context the FPAC exception was taken from. The pt_regs and ESR value reported will be from within do_ptrauth_fault() and the code dump will be for the BRK in BUG_ON(), which isn't sufficient to debug the cause of the original exception. This patch makes the reporting better by having separate EL0 and EL1 FPAC exception handlers, with the latter calling die() directly to report the original context the FPAC exception was taken from. Note that we only need to prevent kprobes of the EL1 FPAC handler, since the EL0 FPAC handler cannot be called recursively. For consistency with do_el0_svc*(), I've named the split functions do_el{0,1}_fpac() rather than do_el{0,1}_ptrauth_fault(). I've also clarified the comment to not imply there are casues other than FPAC exceptions. Prior to this patch FPAC exceptions are reported as: | kernel BUG at arch/arm64/kernel/traps.c:517! | Internal error: Oops - BUG: 00000000f2000800 [#1] PREEMPT SMP | Modules linked in: | CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.19.0-rc3-00130-g9c8a180a1cdf-dirty #12 | Hardware name: FVP Base RevC (DT) | pstate: 00400009 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) | pc : do_ptrauth_fault+0x3c/0x40 | lr : el1_fpac+0x34/0x54 | sp : ffff80000a3bbc80 | x29: ffff80000a3bbc80 x28: ffff0008001d8000 x27: 0000000000000000 | x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000 | x23: 0000000020400009 x22: ffff800008f70fa4 x21: ffff80000a3bbe00 | x20: 0000000072000000 x19: ffff80000a3bbcb0 x18: fffffbfffda37000 | x17: 3120676e696d7573 x16: 7361202c6e6f6974 x15: 0000000081a90000 | x14: 0040000000000041 x13: 0040000000000001 x12: ffff000001a90000 | x11: fffffbfffda37480 x10: 0068000000000703 x9 : 0001000080000000 | x8 : 0000000000090000 x7 : 0068000000000f03 x6 : 0060000000000783 | x5 : ffff80000a3bbcb0 x4 : ffff0008001d8000 x3 : 0000000072000000 | x2 : 0000000000000000 x1 : 0000000020400009 x0 : ffff80000a3bbcb0 | Call trace: | do_ptrauth_fault+0x3c/0x40 | el1h_64_sync_handler+0xc4/0xd0 | el1h_64_sync+0x64/0x68 | test_pac+0x8/0x10 | smp_init+0x7c/0x8c | kernel_init_freeable+0x128/0x28c | kernel_init+0x28/0x13c | ret_from_fork+0x10/0x20 | Code: 97fffe5e a8c17bfd d50323bf d65f03c0 (d4210000) With this patch applied FPAC exceptions are reported as: | Internal error: Oops - FPAC: 0000000072000000 [#1] PREEMPT SMP | Modules linked in: | CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.19.0-rc3-00132-g78846e1c4757-dirty #11 | Hardware name: FVP Base RevC (DT) | pstate: 20400009 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) | pc : test_pac+0x8/0x10 | lr : 0x0 | sp : ffff80000a3bbe00 | x29: ffff80000a3bbe00 x28: 0000000000000000 x27: 0000000000000000 | x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000 | x23: ffff80000a2c8000 x22: 0000000000000000 x21: 0000000000000000 | x20: ffff8000099fa5b0 x19: ffff80000a007000 x18: fffffbfffda37000 | x17: 3120676e696d7573 x16: 7361202c6e6f6974 x15: 0000000081a90000 | x14: 0040000000000041 x13: 0040000000000001 x12: ffff000001a90000 | x11: fffffbfffda37480 x10: 0068000000000703 x9 : 0001000080000000 | x8 : 0000000000090000 x7 : 0068000000000f03 x6 : 0060000000000783 | x5 : ffff80000a2c6000 x4 : ffff0008001d8000 x3 : ffff800009f88378 | x2 : 0000000000000000 x1 : 0000000080210000 x0 : ffff000001a90000 | Call trace: | test_pac+0x8/0x10 | smp_init+0x7c/0x8c | kernel_init_freeable+0x128/0x28c | kernel_init+0x28/0x13c | ret_from_fork+0x10/0x20 | Code: d50323bf d65f03c0 d503233f aa1f03fe (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 611d2d3 commit d712669

File tree

3 files changed

+14
-9
lines changed

3 files changed

+14
-9
lines changed

arch/arm64/include/asm/exception.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned long esr);
7171
void do_cp15instr(unsigned long esr, struct pt_regs *regs);
7272
void do_el0_svc(struct pt_regs *regs);
7373
void do_el0_svc_compat(struct pt_regs *regs);
74-
void do_ptrauth_fault(struct pt_regs *regs, unsigned long esr);
74+
void do_el0_fpac(struct pt_regs *regs, unsigned long esr);
75+
void do_el1_fpac(struct pt_regs *regs, unsigned long esr);
7576
void do_serror(struct pt_regs *regs, unsigned long esr);
7677
void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags);
7778

arch/arm64/kernel/entry-common.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ static void noinstr el1_fpac(struct pt_regs *regs, unsigned long esr)
394394
{
395395
enter_from_kernel_mode(regs);
396396
local_daif_inherit(regs);
397-
do_ptrauth_fault(regs, esr);
397+
do_el1_fpac(regs, esr);
398398
local_daif_mask();
399399
exit_to_kernel_mode(regs);
400400
}
@@ -601,7 +601,7 @@ static void noinstr el0_fpac(struct pt_regs *regs, unsigned long esr)
601601
{
602602
enter_from_user_mode(regs);
603603
local_daif_restore(DAIF_PROCCTX);
604-
do_ptrauth_fault(regs, esr);
604+
do_el0_fpac(regs, esr);
605605
exit_to_user_mode(regs);
606606
}
607607

arch/arm64/kernel/traps.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -509,16 +509,20 @@ void do_bti(struct pt_regs *regs)
509509
}
510510
NOKPROBE_SYMBOL(do_bti);
511511

512-
void do_ptrauth_fault(struct pt_regs *regs, unsigned long esr)
512+
void do_el0_fpac(struct pt_regs *regs, unsigned long esr)
513+
{
514+
force_signal_inject(SIGILL, ILL_ILLOPN, regs->pc, esr);
515+
}
516+
517+
void do_el1_fpac(struct pt_regs *regs, unsigned long esr)
513518
{
514519
/*
515-
* Unexpected FPAC exception or pointer authentication failure in
516-
* the kernel: kill the task before it does any more harm.
520+
* Unexpected FPAC exception in the kernel: kill the task before it
521+
* does any more harm.
517522
*/
518-
BUG_ON(!user_mode(regs));
519-
force_signal_inject(SIGILL, ILL_ILLOPN, regs->pc, esr);
523+
die("Oops - FPAC", regs, esr);
520524
}
521-
NOKPROBE_SYMBOL(do_ptrauth_fault);
525+
NOKPROBE_SYMBOL(do_el1_fpac);
522526

523527
#define __user_cache_maint(insn, address, res) \
524528
if (address >= user_addr_max()) { \

0 commit comments

Comments
 (0)