1 // SPDX-License-Identifier: GPL-2.0
3 * Clang Control Flow Integrity (CFI) support.
5 * Copyright (C) 2023 Google LLC
11 * Returns the target address and the expected type when regs->epc points
12 * to a compiler-generated CFI trap.
14 static bool decode_cfi_insn(struct pt_regs
*regs
, unsigned long *target
,
17 unsigned long *regs_ptr
= (unsigned long *)regs
;
24 * The compiler generates the following instruction sequence
25 * for indirect call checks:
29 * addiw t2, t2, <lo12>
31 * ebreak ; <- regs->epc
35 * We can read the expected type and the target address from the
36 * registers passed to the beq/jalr instructions.
38 if (get_kernel_nofault(insn
, (void *)regs
->epc
- 4))
40 if (!riscv_insn_is_beq(insn
))
43 *type
= (u32
)regs_ptr
[RV_EXTRACT_RS1_REG(insn
)];
45 if (get_kernel_nofault(insn
, (void *)regs
->epc
) ||
46 get_kernel_nofault(insn
, (void *)regs
->epc
+ GET_INSN_LENGTH(insn
)))
49 if (riscv_insn_is_jalr(insn
))
50 rs1_num
= RV_EXTRACT_RS1_REG(insn
);
51 else if (riscv_insn_is_c_jalr(insn
))
52 rs1_num
= RVC_EXTRACT_C2_RS1_REG(insn
);
56 *target
= regs_ptr
[rs1_num
];
62 * Checks if the ebreak trap is because of a CFI failure, and handles the trap
63 * if needed. Returns a bug_trap_type value similarly to report_bug.
65 enum bug_trap_type
handle_cfi_failure(struct pt_regs
*regs
)
70 if (!is_cfi_trap(regs
->epc
))
71 return BUG_TRAP_TYPE_NONE
;
73 if (!decode_cfi_insn(regs
, &target
, &type
))
74 return report_cfi_failure_noaddr(regs
, regs
->epc
);
76 return report_cfi_failure(regs
, regs
->epc
, &target
, type
);
79 #ifdef CONFIG_CFI_CLANG
82 /* Must match bpf_func_t / DEFINE_BPF_PROG_RUN() */
83 extern unsigned int __bpf_prog_runX(const void *ctx
,
84 const struct bpf_insn
*insn
);
87 * Force a reference to the external symbol so the compiler generates
90 __ADDRESSABLE(__bpf_prog_runX
);
92 /* u32 __ro_after_init cfi_bpf_hash = __kcfi_typeid___bpf_prog_runX; */
94 " .pushsection .data..ro_after_init,\"aw\",@progbits \n"
95 " .type cfi_bpf_hash,@object \n"
96 " .globl cfi_bpf_hash \n"
99 " .word __kcfi_typeid___bpf_prog_runX \n"
100 " .size cfi_bpf_hash, 4 \n"
104 /* Must match bpf_callback_t */
105 extern u64
__bpf_callback_fn(u64
, u64
, u64
, u64
, u64
);
107 __ADDRESSABLE(__bpf_callback_fn
);
109 /* u32 __ro_after_init cfi_bpf_subprog_hash = __kcfi_typeid___bpf_callback_fn; */
111 " .pushsection .data..ro_after_init,\"aw\",@progbits \n"
112 " .type cfi_bpf_subprog_hash,@object \n"
113 " .globl cfi_bpf_subprog_hash \n"
114 " .p2align 2, 0x0 \n"
115 "cfi_bpf_subprog_hash: \n"
116 " .word __kcfi_typeid___bpf_callback_fn \n"
117 " .size cfi_bpf_subprog_hash, 4 \n"
121 u32
cfi_get_func_hash(void *func
)
125 if (get_kernel_nofault(hash
, func
- cfi_get_offset()))