2626#include <linux/syscalls.h>
2727#include <linux/mm_types.h>
2828#include <linux/kasan.h>
29+ #include <linux/cfi.h>
2930
3031#include <asm/atomic.h>
3132#include <asm/bug.h>
@@ -991,6 +992,38 @@ static struct break_hook bug_break_hook = {
991992 .imm = BUG_BRK_IMM ,
992993};
993994
995+ #ifdef CONFIG_CFI_CLANG
996+ static int cfi_handler (struct pt_regs * regs , unsigned long esr )
997+ {
998+ unsigned long target ;
999+ u32 type ;
1000+
1001+ target = pt_regs_read_reg (regs , FIELD_GET (CFI_BRK_IMM_TARGET , esr ));
1002+ type = (u32 )pt_regs_read_reg (regs , FIELD_GET (CFI_BRK_IMM_TYPE , esr ));
1003+
1004+ switch (report_cfi_failure (regs , regs -> pc , & target , type )) {
1005+ case BUG_TRAP_TYPE_BUG :
1006+ die ("Oops - CFI" , regs , 0 );
1007+ break ;
1008+
1009+ case BUG_TRAP_TYPE_WARN :
1010+ break ;
1011+
1012+ default :
1013+ return DBG_HOOK_ERROR ;
1014+ }
1015+
1016+ arm64_skip_faulting_instruction (regs , AARCH64_INSN_SIZE );
1017+ return DBG_HOOK_HANDLED ;
1018+ }
1019+
1020+ static struct break_hook cfi_break_hook = {
1021+ .fn = cfi_handler ,
1022+ .imm = CFI_BRK_IMM_BASE ,
1023+ .mask = CFI_BRK_IMM_MASK ,
1024+ };
1025+ #endif /* CONFIG_CFI_CLANG */
1026+
9941027static int reserved_fault_handler (struct pt_regs * regs , unsigned long esr )
9951028{
9961029 pr_err ("%s generated an invalid instruction at %pS!\n" ,
@@ -1052,17 +1085,22 @@ static struct break_hook kasan_break_hook = {
10521085};
10531086#endif
10541087
1088+
1089+ #define esr_comment (esr ) ((esr) & ESR_ELx_BRK64_ISS_COMMENT_MASK)
1090+
10551091/*
10561092 * Initial handler for AArch64 BRK exceptions
10571093 * This handler only used until debug_traps_init().
10581094 */
10591095int __init early_brk64 (unsigned long addr , unsigned long esr ,
10601096 struct pt_regs * regs )
10611097{
1098+ #ifdef CONFIG_CFI_CLANG
1099+ if ((esr_comment (esr ) & ~CFI_BRK_IMM_MASK ) == CFI_BRK_IMM_BASE )
1100+ return cfi_handler (regs , esr ) != DBG_HOOK_HANDLED ;
1101+ #endif
10621102#ifdef CONFIG_KASAN_SW_TAGS
1063- unsigned long comment = esr & ESR_ELx_BRK64_ISS_COMMENT_MASK ;
1064-
1065- if ((comment & ~KASAN_BRK_MASK ) == KASAN_BRK_IMM )
1103+ if ((esr_comment (esr ) & ~KASAN_BRK_MASK ) == KASAN_BRK_IMM )
10661104 return kasan_handler (regs , esr ) != DBG_HOOK_HANDLED ;
10671105#endif
10681106 return bug_handler (regs , esr ) != DBG_HOOK_HANDLED ;
@@ -1071,6 +1109,9 @@ int __init early_brk64(unsigned long addr, unsigned long esr,
10711109void __init trap_init (void )
10721110{
10731111 register_kernel_break_hook (& bug_break_hook );
1112+ #ifdef CONFIG_CFI_CLANG
1113+ register_kernel_break_hook (& cfi_break_hook );
1114+ #endif
10741115 register_kernel_break_hook (& fault_break_hook );
10751116#ifdef CONFIG_KASAN_SW_TAGS
10761117 register_kernel_break_hook (& kasan_break_hook );
0 commit comments