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