Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/bpf: Fix unwinding past the trampoline

When functions called by the trampoline panic, the backtrace that is
printed stops at the trampoline, because the trampoline does not store
its caller's frame address (backchain) on stack; it also stores the
return address at a wrong location.

Store both the same way as is already done for the regular eBPF programs.

Fixes: 528eb2cb87bc ("s390/bpf: Implement arch_prepare_bpf_trampoline()")
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20231010203512.385819-3-iii@linux.ibm.com

authored by

Ilya Leoshkevich and committed by
Daniel Borkmann
5356ba1f ce10fc06

+14 -3
+14 -3
arch/s390/net/bpf_jit_comp.c
··· 2066 2066 * func_addr's original caller 2067 2067 */ 2068 2068 int stack_size; /* Trampoline stack size */ 2069 + int backchain_off; /* Offset of backchain */ 2069 2070 int stack_args_off; /* Offset of stack arguments for calling 2070 2071 * func_addr, has to be at the top 2071 2072 */ ··· 2087 2086 * for __bpf_prog_enter() return value and 2088 2087 * func_addr respectively 2089 2088 */ 2090 - int r14_off; /* Offset of saved %r14 */ 2091 2089 int run_ctx_off; /* Offset of struct bpf_tramp_run_ctx */ 2092 2090 int tccnt_off; /* Offset of saved tailcall counter */ 2091 + int r14_off; /* Offset of saved %r14, has to be at the 2092 + * bottom */ 2093 2093 int do_fexit; /* do_fexit: label */ 2094 2094 }; 2095 2095 ··· 2249 2247 * Calculate the stack layout. 2250 2248 */ 2251 2249 2252 - /* Reserve STACK_FRAME_OVERHEAD bytes for the callees. */ 2250 + /* 2251 + * Allocate STACK_FRAME_OVERHEAD bytes for the callees. As the s390x 2252 + * ABI requires, put our backchain at the end of the allocated memory. 2253 + */ 2253 2254 tjit->stack_size = STACK_FRAME_OVERHEAD; 2255 + tjit->backchain_off = tjit->stack_size - sizeof(u64); 2254 2256 tjit->stack_args_off = alloc_stack(tjit, nr_stack_args * sizeof(u64)); 2255 2257 tjit->reg_args_off = alloc_stack(tjit, nr_reg_args * sizeof(u64)); 2256 2258 tjit->ip_off = alloc_stack(tjit, sizeof(u64)); ··· 2262 2256 tjit->bpf_args_off = alloc_stack(tjit, nr_bpf_args * sizeof(u64)); 2263 2257 tjit->retval_off = alloc_stack(tjit, sizeof(u64)); 2264 2258 tjit->r7_r8_off = alloc_stack(tjit, 2 * sizeof(u64)); 2265 - tjit->r14_off = alloc_stack(tjit, sizeof(u64)); 2266 2259 tjit->run_ctx_off = alloc_stack(tjit, 2267 2260 sizeof(struct bpf_tramp_run_ctx)); 2268 2261 tjit->tccnt_off = alloc_stack(tjit, sizeof(u64)); 2262 + tjit->r14_off = alloc_stack(tjit, sizeof(u64) * 2); 2269 2263 /* 2270 2264 * In accordance with the s390x ABI, the caller has allocated 2271 2265 * STACK_FRAME_OVERHEAD bytes for us. 8 of them contain the caller's ··· 2274 2268 tjit->stack_size -= STACK_FRAME_OVERHEAD - sizeof(u64); 2275 2269 tjit->orig_stack_args_off = tjit->stack_size + STACK_FRAME_OVERHEAD; 2276 2270 2271 + /* lgr %r1,%r15 */ 2272 + EMIT4(0xb9040000, REG_1, REG_15); 2277 2273 /* aghi %r15,-stack_size */ 2278 2274 EMIT4_IMM(0xa70b0000, REG_15, -tjit->stack_size); 2275 + /* stg %r1,backchain_off(%r15) */ 2276 + EMIT6_DISP_LH(0xe3000000, 0x0024, REG_1, REG_0, REG_15, 2277 + tjit->backchain_off); 2279 2278 /* mvc tccnt_off(4,%r15),stack_size+STK_OFF_TCCNT(%r15) */ 2280 2279 _EMIT6(0xd203f000 | tjit->tccnt_off, 2281 2280 0xf000 | (tjit->stack_size + STK_OFF_TCCNT));