diff options
author | Alexei Starovoitov <ast@kernel.org> | 2019-06-14 18:43:28 -0400 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2019-06-14 21:02:25 -0400 |
commit | fe8d9571dc50232b569242fac7ea6332a654f186 (patch) | |
tree | 5278d30db2ccb8b0b61d787ab9c867482b1de0a7 | |
parent | 86723c8640633bee4b4588d3c7784ee7a0032f65 (diff) |
bpf, x64: fix stack layout of JITed bpf code
Since commit 177366bf7ceb the %rbp stopped pointing to %rbp of the
previous stack frame. That broke frame pointer based stack unwinding.
This commit is a partial revert of it.
Note that the location of tail_call_cnt is fixed, since the verifier
enforces MAX_BPF_STACK stack size for programs with tail calls.
Fixes: 177366bf7ceb ("bpf: change x86 JITed program stack layout")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r-- | arch/x86/net/bpf_jit_comp.c | 74 |
1 files changed, 21 insertions, 53 deletions
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index afabf597c855..d88bc0935886 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c | |||
@@ -190,9 +190,7 @@ struct jit_context { | |||
190 | #define BPF_MAX_INSN_SIZE 128 | 190 | #define BPF_MAX_INSN_SIZE 128 |
191 | #define BPF_INSN_SAFETY 64 | 191 | #define BPF_INSN_SAFETY 64 |
192 | 192 | ||
193 | #define AUX_STACK_SPACE 40 /* Space for RBX, R13, R14, R15, tailcnt */ | 193 | #define PROLOGUE_SIZE 20 |
194 | |||
195 | #define PROLOGUE_SIZE 37 | ||
196 | 194 | ||
197 | /* | 195 | /* |
198 | * Emit x86-64 prologue code for BPF program and check its size. | 196 | * Emit x86-64 prologue code for BPF program and check its size. |
@@ -203,44 +201,19 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf) | |||
203 | u8 *prog = *pprog; | 201 | u8 *prog = *pprog; |
204 | int cnt = 0; | 202 | int cnt = 0; |
205 | 203 | ||
206 | /* push rbp */ | 204 | EMIT1(0x55); /* push rbp */ |
207 | EMIT1(0x55); | 205 | EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ |
208 | 206 | /* sub rsp, rounded_stack_depth */ | |
209 | /* mov rbp,rsp */ | 207 | EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8)); |
210 | EMIT3(0x48, 0x89, 0xE5); | 208 | EMIT1(0x53); /* push rbx */ |
211 | 209 | EMIT2(0x41, 0x55); /* push r13 */ | |
212 | /* sub rsp, rounded_stack_depth + AUX_STACK_SPACE */ | 210 | EMIT2(0x41, 0x56); /* push r14 */ |
213 | EMIT3_off32(0x48, 0x81, 0xEC, | 211 | EMIT2(0x41, 0x57); /* push r15 */ |
214 | round_up(stack_depth, 8) + AUX_STACK_SPACE); | ||
215 | |||
216 | /* sub rbp, AUX_STACK_SPACE */ | ||
217 | EMIT4(0x48, 0x83, 0xED, AUX_STACK_SPACE); | ||
218 | |||
219 | /* mov qword ptr [rbp+0],rbx */ | ||
220 | EMIT4(0x48, 0x89, 0x5D, 0); | ||
221 | /* mov qword ptr [rbp+8],r13 */ | ||
222 | EMIT4(0x4C, 0x89, 0x6D, 8); | ||
223 | /* mov qword ptr [rbp+16],r14 */ | ||
224 | EMIT4(0x4C, 0x89, 0x75, 16); | ||
225 | /* mov qword ptr [rbp+24],r15 */ | ||
226 | EMIT4(0x4C, 0x89, 0x7D, 24); | ||
227 | |||
228 | if (!ebpf_from_cbpf) { | 212 | if (!ebpf_from_cbpf) { |
229 | /* | 213 | /* zero init tail_call_cnt */ |
230 | * Clear the tail call counter (tail_call_cnt): for eBPF tail | 214 | EMIT2(0x6a, 0x00); |
231 | * calls we need to reset the counter to 0. It's done in two | ||
232 | * instructions, resetting RAX register to 0, and moving it | ||
233 | * to the counter location. | ||
234 | */ | ||
235 | |||
236 | /* xor eax, eax */ | ||
237 | EMIT2(0x31, 0xc0); | ||
238 | /* mov qword ptr [rbp+32], rax */ | ||
239 | EMIT4(0x48, 0x89, 0x45, 32); | ||
240 | |||
241 | BUILD_BUG_ON(cnt != PROLOGUE_SIZE); | 215 | BUILD_BUG_ON(cnt != PROLOGUE_SIZE); |
242 | } | 216 | } |
243 | |||
244 | *pprog = prog; | 217 | *pprog = prog; |
245 | } | 218 | } |
246 | 219 | ||
@@ -285,13 +258,13 @@ static void emit_bpf_tail_call(u8 **pprog) | |||
285 | * if (tail_call_cnt > MAX_TAIL_CALL_CNT) | 258 | * if (tail_call_cnt > MAX_TAIL_CALL_CNT) |
286 | * goto out; | 259 | * goto out; |
287 | */ | 260 | */ |
288 | EMIT2_off32(0x8B, 0x85, 36); /* mov eax, dword ptr [rbp + 36] */ | 261 | EMIT2_off32(0x8B, 0x85, -36 - MAX_BPF_STACK); /* mov eax, dword ptr [rbp - 548] */ |
289 | EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ | 262 | EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ |
290 | #define OFFSET2 (30 + RETPOLINE_RAX_BPF_JIT_SIZE) | 263 | #define OFFSET2 (30 + RETPOLINE_RAX_BPF_JIT_SIZE) |
291 | EMIT2(X86_JA, OFFSET2); /* ja out */ | 264 | EMIT2(X86_JA, OFFSET2); /* ja out */ |
292 | label2 = cnt; | 265 | label2 = cnt; |
293 | EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ | 266 | EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ |
294 | EMIT2_off32(0x89, 0x85, 36); /* mov dword ptr [rbp + 36], eax */ | 267 | EMIT2_off32(0x89, 0x85, -36 - MAX_BPF_STACK); /* mov dword ptr [rbp -548], eax */ |
295 | 268 | ||
296 | /* prog = array->ptrs[index]; */ | 269 | /* prog = array->ptrs[index]; */ |
297 | EMIT4_off32(0x48, 0x8B, 0x84, 0xD6, /* mov rax, [rsi + rdx * 8 + offsetof(...)] */ | 270 | EMIT4_off32(0x48, 0x8B, 0x84, 0xD6, /* mov rax, [rsi + rdx * 8 + offsetof(...)] */ |
@@ -1040,19 +1013,14 @@ emit_jmp: | |||
1040 | seen_exit = true; | 1013 | seen_exit = true; |
1041 | /* Update cleanup_addr */ | 1014 | /* Update cleanup_addr */ |
1042 | ctx->cleanup_addr = proglen; | 1015 | ctx->cleanup_addr = proglen; |
1043 | /* mov rbx, qword ptr [rbp+0] */ | 1016 | if (!bpf_prog_was_classic(bpf_prog)) |
1044 | EMIT4(0x48, 0x8B, 0x5D, 0); | 1017 | EMIT1(0x5B); /* get rid of tail_call_cnt */ |
1045 | /* mov r13, qword ptr [rbp+8] */ | 1018 | EMIT2(0x41, 0x5F); /* pop r15 */ |
1046 | EMIT4(0x4C, 0x8B, 0x6D, 8); | 1019 | EMIT2(0x41, 0x5E); /* pop r14 */ |
1047 | /* mov r14, qword ptr [rbp+16] */ | 1020 | EMIT2(0x41, 0x5D); /* pop r13 */ |
1048 | EMIT4(0x4C, 0x8B, 0x75, 16); | 1021 | EMIT1(0x5B); /* pop rbx */ |
1049 | /* mov r15, qword ptr [rbp+24] */ | 1022 | EMIT1(0xC9); /* leave */ |
1050 | EMIT4(0x4C, 0x8B, 0x7D, 24); | 1023 | EMIT1(0xC3); /* ret */ |
1051 | |||
1052 | /* add rbp, AUX_STACK_SPACE */ | ||
1053 | EMIT4(0x48, 0x83, 0xC5, AUX_STACK_SPACE); | ||
1054 | EMIT1(0xC9); /* leave */ | ||
1055 | EMIT1(0xC3); /* ret */ | ||
1056 | break; | 1024 | break; |
1057 | 1025 | ||
1058 | default: | 1026 | default: |