1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _ASM_X86_CFI_H
3#define _ASM_X86_CFI_H
4
5/*
6 * Clang Control Flow Integrity (CFI) support.
7 *
8 * Copyright (C) 2022 Google LLC
9 */
10#include <linux/bug.h>
11#include <asm/ibt.h>
12
13/*
14 * An overview of the various calling conventions...
15 *
16 * Traditional:
17 *
18 * foo:
19 * ... code here ...
20 * ret
21 *
22 * direct caller:
23 * call foo
24 *
25 * indirect caller:
26 * lea foo(%rip), %r11
27 * ...
28 * call *%r11
29 *
30 *
31 * IBT:
32 *
33 * foo:
34 * endbr64
35 * ... code here ...
36 * ret
37 *
38 * direct caller:
39 * call foo / call foo+4
40 *
41 * indirect caller:
42 * lea foo(%rip), %r11
43 * ...
44 * call *%r11
45 *
46 *
47 * kCFI:
48 *
49 * __cfi_foo:
50 * movl $0x12345678, %eax
51 * # 11 nops when CONFIG_CALL_PADDING
52 * foo:
53 * endbr64 # when IBT
54 * ... code here ...
55 * ret
56 *
57 * direct call:
58 * call foo # / call foo+4 when IBT
59 *
60 * indirect call:
61 * lea foo(%rip), %r11
62 * ...
63 * movl $(-0x12345678), %r10d
64 * addl -4(%r11), %r10d # -15 when CONFIG_CALL_PADDING
65 * jz 1f
66 * ud2
67 * 1:call *%r11
68 *
69 *
70 * FineIBT (builds as kCFI + CALL_PADDING + IBT + RETPOLINE and runtime patches into):
71 *
72 * __cfi_foo:
73 * endbr64
74 * subl 0x12345678, %r10d
75 * jz foo
76 * ud2
77 * nop
78 * foo:
79 * osp nop3 # was endbr64
80 * ... code here ...
81 * ret
82 *
83 * direct caller:
84 * call foo / call foo+4
85 *
86 * indirect caller:
87 * lea foo(%rip), %r11
88 * ...
89 * movl $0x12345678, %r10d
90 * subl $16, %r11
91 * nop4
92 * call *%r11
93 *
94 */
95enum cfi_mode {
96 CFI_DEFAULT, /* FineIBT if hardware has IBT, otherwise kCFI */
97 CFI_OFF, /* Taditional / IBT depending on .config */
98 CFI_KCFI, /* Optionally CALL_PADDING, IBT, RETPOLINE */
99 CFI_FINEIBT, /* see arch/x86/kernel/alternative.c */
100};
101
102extern enum cfi_mode cfi_mode;
103
104struct pt_regs;
105
106#ifdef CONFIG_CFI_CLANG
107enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);
108#define __bpfcall
109extern u32 cfi_bpf_hash;
110extern u32 cfi_bpf_subprog_hash;
111
112static inline int cfi_get_offset(void)
113{
114 switch (cfi_mode) {
115 case CFI_FINEIBT:
116 return 16;
117 case CFI_KCFI:
118 if (IS_ENABLED(CONFIG_CALL_PADDING))
119 return 16;
120 return 5;
121 default:
122 return 0;
123 }
124}
125#define cfi_get_offset cfi_get_offset
126
127extern u32 cfi_get_func_hash(void *func);
128
129#else
130static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)
131{
132 return BUG_TRAP_TYPE_NONE;
133}
134#define cfi_bpf_hash 0U
135#define cfi_bpf_subprog_hash 0U
136static inline u32 cfi_get_func_hash(void *func)
137{
138 return 0;
139}
140#endif /* CONFIG_CFI_CLANG */
141
142#if HAS_KERNEL_IBT == 1
143#define CFI_NOSEAL(x) asm(IBT_NOSEAL(__stringify(x)))
144#endif
145
146#endif /* _ASM_X86_CFI_H */
147

source code of linux/arch/x86/include/asm/cfi.h