Skip to content

Commit 9113333

Browse files
Mark Rutlandgregkh
Mark Rutland
authored andcommittedOct 25, 2023
arm64: rework FPAC exception handling
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 [khadas#1] PREEMPT SMP | Modules linked in: | CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.19.0-rc3-00130-g9c8a180a1cdf-dirty khadas#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 [khadas#1] PREEMPT SMP | Modules linked in: | CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.19.0-rc3-00132-g78846e1c4757-dirty khadas#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]>
1 parent a8d7c84 commit 9113333

File tree

3 files changed

+14
-9
lines changed

3 files changed

+14
-9
lines changed
 

‎arch/arm64/include/asm/exception.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,6 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr);
4747
void do_cp15instr(unsigned int esr, struct pt_regs *regs);
4848
void do_el0_svc(struct pt_regs *regs);
4949
void do_el0_svc_compat(struct pt_regs *regs);
50-
void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr);
50+
void do_el0_fpac(struct pt_regs *regs, unsigned long esr);
51+
void do_el1_fpac(struct pt_regs *regs, unsigned long esr);
5152
#endif /* __ASM_EXCEPTION_H */

‎arch/arm64/kernel/entry-common.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ static void noinstr el1_fpac(struct pt_regs *regs, unsigned long esr)
187187
{
188188
enter_from_kernel_mode(regs);
189189
local_daif_inherit(regs);
190-
do_ptrauth_fault(regs, esr);
190+
do_el1_fpac(regs, esr);
191191
local_daif_mask();
192192
exit_to_kernel_mode(regs);
193193
}
@@ -357,7 +357,7 @@ static void noinstr el0_fpac(struct pt_regs *regs, unsigned long esr)
357357
{
358358
enter_from_user_mode();
359359
local_daif_restore(DAIF_PROCCTX);
360-
do_ptrauth_fault(regs, esr);
360+
do_el0_fpac(regs, esr);
361361
}
362362

363363
asmlinkage void noinstr el0_sync_handler(struct pt_regs *regs)

‎arch/arm64/kernel/traps.c

+10-6
Original file line numberDiff line numberDiff line change
@@ -418,16 +418,20 @@ void do_bti(struct pt_regs *regs)
418418
}
419419
NOKPROBE_SYMBOL(do_bti);
420420

421-
void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr)
421+
void do_el0_fpac(struct pt_regs *regs, unsigned long esr)
422+
{
423+
force_signal_inject(SIGILL, ILL_ILLOPN, regs->pc, esr);
424+
}
425+
426+
void do_el1_fpac(struct pt_regs *regs, unsigned long esr)
422427
{
423428
/*
424-
* Unexpected FPAC exception or pointer authentication failure in
425-
* the kernel: kill the task before it does any more harm.
429+
* Unexpected FPAC exception in the kernel: kill the task before it
430+
* does any more harm.
426431
*/
427-
BUG_ON(!user_mode(regs));
428-
force_signal_inject(SIGILL, ILL_ILLOPN, regs->pc, esr);
432+
die("Oops - FPAC", regs, esr);
429433
}
430-
NOKPROBE_SYMBOL(do_ptrauth_fault);
434+
NOKPROBE_SYMBOL(do_el1_fpac);
431435

432436
#define __user_cache_maint(insn, address, res) \
433437
if (address >= user_addr_max()) { \

0 commit comments

Comments
 (0)
Please sign in to comment.