summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2019-06-14 18:43:28 -0400
committerAlexei Starovoitov <ast@kernel.org>2019-06-14 21:02:25 -0400
commitfe8d9571dc50232b569242fac7ea6332a654f186 (patch)
tree5278d30db2ccb8b0b61d787ab9c867482b1de0a7
parent86723c8640633bee4b4588d3c7784ee7a0032f65 (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.c74
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: