1cf68fffbSSami Tolvanen /* SPDX-License-Identifier: GPL-2.0 */
2cf68fffbSSami Tolvanen /*
3cf68fffbSSami Tolvanen * Clang Control Flow Integrity (CFI) support.
4cf68fffbSSami Tolvanen *
589245600SSami Tolvanen * Copyright (C) 2022 Google LLC
6cf68fffbSSami Tolvanen */
7cf68fffbSSami Tolvanen #ifndef _LINUX_CFI_H
8cf68fffbSSami Tolvanen #define _LINUX_CFI_H
9cf68fffbSSami Tolvanen
1089245600SSami Tolvanen #include <linux/bug.h>
1189245600SSami Tolvanen #include <linux/module.h>
1243821596SPeter Zijlstra #include <asm/cfi.h>
1389245600SSami Tolvanen
14*9a54fb31SPeter Zijlstra extern bool cfi_warn;
15*9a54fb31SPeter Zijlstra
164f9087f1SPeter Zijlstra #ifndef cfi_get_offset
cfi_get_offset(void)174f9087f1SPeter Zijlstra static inline int cfi_get_offset(void)
184f9087f1SPeter Zijlstra {
194f9087f1SPeter Zijlstra return 0;
204f9087f1SPeter Zijlstra }
214f9087f1SPeter Zijlstra #endif
224f9087f1SPeter Zijlstra
23cf68fffbSSami Tolvanen #ifdef CONFIG_CFI_CLANG
2489245600SSami Tolvanen enum bug_trap_type report_cfi_failure(struct pt_regs *regs, unsigned long addr,
2589245600SSami Tolvanen unsigned long *target, u32 type);
26cf68fffbSSami Tolvanen
report_cfi_failure_noaddr(struct pt_regs * regs,unsigned long addr)2789245600SSami Tolvanen static inline enum bug_trap_type report_cfi_failure_noaddr(struct pt_regs *regs,
2889245600SSami Tolvanen unsigned long addr)
2989245600SSami Tolvanen {
3089245600SSami Tolvanen return report_cfi_failure(regs, addr, NULL, 0);
3189245600SSami Tolvanen }
32b6541376SMasami Hiramatsu #endif /* CONFIG_CFI_CLANG */
33cf68fffbSSami Tolvanen
3489245600SSami Tolvanen #ifdef CONFIG_ARCH_USES_CFI_TRAPS
3589245600SSami Tolvanen bool is_cfi_trap(unsigned long addr);
36b6541376SMasami Hiramatsu #else
is_cfi_trap(unsigned long addr)37b6541376SMasami Hiramatsu static inline bool is_cfi_trap(unsigned long addr) { return false; }
3889245600SSami Tolvanen #endif
39cf68fffbSSami Tolvanen
4089245600SSami Tolvanen #ifdef CONFIG_MODULES
4189245600SSami Tolvanen #ifdef CONFIG_ARCH_USES_CFI_TRAPS
4289245600SSami Tolvanen void module_cfi_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
4389245600SSami Tolvanen struct module *mod);
4489245600SSami Tolvanen #else
module_cfi_finalize(const Elf_Ehdr * hdr,const Elf_Shdr * sechdrs,struct module * mod)4589245600SSami Tolvanen static inline void module_cfi_finalize(const Elf_Ehdr *hdr,
4689245600SSami Tolvanen const Elf_Shdr *sechdrs,
4789245600SSami Tolvanen struct module *mod) {}
4889245600SSami Tolvanen #endif /* CONFIG_ARCH_USES_CFI_TRAPS */
4989245600SSami Tolvanen #endif /* CONFIG_MODULES */
5089245600SSami Tolvanen
51e9d13b9dSPeter Zijlstra #ifndef CFI_NOSEAL
52e9d13b9dSPeter Zijlstra #define CFI_NOSEAL(x)
53e9d13b9dSPeter Zijlstra #endif
54e9d13b9dSPeter Zijlstra
55cf68fffbSSami Tolvanen #endif /* _LINUX_CFI_H */
56