s390/bpf: Fix unwinding past the trampoline
authorIlya Leoshkevich <iii@linux.ibm.com>
Tue, 10 Oct 2023 20:20:10 +0000 (22:20 +0200)
committerDaniel Borkmann <daniel@iogearbox.net>
Tue, 10 Oct 2023 22:08:46 +0000 (00:08 +0200)
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
arch/s390/net/bpf_jit_comp.c

index 9a9733e..e507692 100644 (file)
@@ -2066,6 +2066,7 @@ struct bpf_tramp_jit {
                                 * func_addr's original caller
                                 */
        int stack_size;         /* Trampoline stack size */
+       int backchain_off;      /* Offset of backchain */
        int stack_args_off;     /* Offset of stack arguments for calling
                                 * func_addr, has to be at the top
                                 */
@@ -2086,9 +2087,10 @@ struct bpf_tramp_jit {
                                 * for __bpf_prog_enter() return value and
                                 * func_addr respectively
                                 */
-       int r14_off;            /* Offset of saved %r14 */
        int run_ctx_off;        /* Offset of struct bpf_tramp_run_ctx */
        int tccnt_off;          /* Offset of saved tailcall counter */
+       int r14_off;            /* Offset of saved %r14, has to be at the
+                                * bottom */
        int do_fexit;           /* do_fexit: label */
 };
 
@@ -2247,8 +2249,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
         * Calculate the stack layout.
         */
 
-       /* Reserve STACK_FRAME_OVERHEAD bytes for the callees. */
+       /*
+        * Allocate STACK_FRAME_OVERHEAD bytes for the callees. As the s390x
+        * ABI requires, put our backchain at the end of the allocated memory.
+        */
        tjit->stack_size = STACK_FRAME_OVERHEAD;
+       tjit->backchain_off = tjit->stack_size - sizeof(u64);
        tjit->stack_args_off = alloc_stack(tjit, nr_stack_args * sizeof(u64));
        tjit->reg_args_off = alloc_stack(tjit, nr_reg_args * sizeof(u64));
        tjit->ip_off = alloc_stack(tjit, sizeof(u64));
@@ -2256,10 +2262,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
        tjit->bpf_args_off = alloc_stack(tjit, nr_bpf_args * sizeof(u64));
        tjit->retval_off = alloc_stack(tjit, sizeof(u64));
        tjit->r7_r8_off = alloc_stack(tjit, 2 * sizeof(u64));
-       tjit->r14_off = alloc_stack(tjit, sizeof(u64));
        tjit->run_ctx_off = alloc_stack(tjit,
                                        sizeof(struct bpf_tramp_run_ctx));
        tjit->tccnt_off = alloc_stack(tjit, sizeof(u64));
+       tjit->r14_off = alloc_stack(tjit, sizeof(u64) * 2);
        /*
         * In accordance with the s390x ABI, the caller has allocated
         * STACK_FRAME_OVERHEAD bytes for us. 8 of them contain the caller's
@@ -2268,8 +2274,13 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
        tjit->stack_size -= STACK_FRAME_OVERHEAD - sizeof(u64);
        tjit->orig_stack_args_off = tjit->stack_size + STACK_FRAME_OVERHEAD;
 
+       /* lgr %r1,%r15 */
+       EMIT4(0xb9040000, REG_1, REG_15);
        /* aghi %r15,-stack_size */
        EMIT4_IMM(0xa70b0000, REG_15, -tjit->stack_size);
+       /* stg %r1,backchain_off(%r15) */
+       EMIT6_DISP_LH(0xe3000000, 0x0024, REG_1, REG_0, REG_15,
+                     tjit->backchain_off);
        /* mvc tccnt_off(4,%r15),stack_size+STK_OFF_TCCNT(%r15) */
        _EMIT6(0xd203f000 | tjit->tccnt_off,
               0xf000 | (tjit->stack_size + STK_OFF_TCCNT));