mirror of
https://github.com/torvalds/linux.git
synced 2026-09-27 19:42:03 +02:00
Merge branch 'bpf-arm64-fix-the-exception-callback-s-frame-pointer'
Donggeun Yoo says:
====================
bpf, arm64: fix the exception callback's frame pointer
The arm64 JIT does not set BPF_REG_FP in the prologue of an exception
callback, so the callback runs with whatever x25 held when bpf_throw()
was called. A callback that materializes the register, for instance to
pass the address of a local variable to a helper, then works on the
frame of the subprogram that threw.
Patch 1 sets ctx->fp_used on that path, the same fix commit b114fcee76
("bpf, arm64: Fix fp initialization for exception boundary") made for
the exception boundary. Patch 2 adds a selftest that reaches the case.
Tested on aarch64 under QEMU with vmtest.sh, on the base below. Without
patch 1 the new test panics the kernel, because the address handed to
the helper lands on the helper's own saved return address:
pc : 0x1234
lr : 0x1234
Call trace:
0x1234 (P)
bpf_test_run+0x188/0x3e0
bpf_prog_test_run_skb+0x47c/0x998
__sys_bpf+0xbdc/0xdd8
Kernel panic - not syncing: Oops: Fatal exception in interrupt
0x1234 is the value the callback reads, so the helper wrote it over its
own return address. With patch 1 applied the whole group passes:
#117/11 exceptions/exception_throw_subprog_stack_cb:OK
#117 exceptions:OK
Summary: 1/118 PASSED, 0 SKIPPED, 0/0 FAILED
Not tested on other architectures.
v1: https://lore.kernel.org/bpf/20260904070210.4163193-1-donggeunyoo.kernel@gmail.com/
v2: https://lore.kernel.org/bpf/20260907054235.473103-1-donggeunyoo.kernel@gmail.com/
v2 -> v3:
- patch 2: use the standard multi-line comment style
- patch 1: no change, added the Acked-by
Nothing compiled changed, so the numbers above are still v2's.
v1 -> v2:
- rebase onto bpf/master; CI could not apply v1
- spell the three new declarations u64 rather than __u64, to match the
rest of progs/exceptions.c
- no change to patch 1
====================
Link: https://patch.msgid.link/20260907130624.611942-1-donggeunyoo.kernel@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
ee363e0558
|
|
@ -600,6 +600,8 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
|
|||
* 12 registers are on the stack
|
||||
*/
|
||||
emit(A64_SUB_I(1, A64_SP, A64_FP, 96), ctx);
|
||||
/* The callback may use its own BPF stack, set up fp for it. */
|
||||
ctx->fp_used = true;
|
||||
}
|
||||
|
||||
/* Stack must be multiples of 16B */
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ static void test_exceptions_success(void)
|
|||
RUN_SUCCESS(exception_ext, 0);
|
||||
RUN_SUCCESS(exception_ext_mod_cb_runtime, 35);
|
||||
RUN_SUCCESS(exception_throw_subprog, 1);
|
||||
RUN_SUCCESS(exception_throw_subprog_stack_cb, 0x1234);
|
||||
RUN_SUCCESS(exception_assert_nz_gfunc, 1);
|
||||
RUN_SUCCESS(exception_assert_zero_gfunc, 1);
|
||||
RUN_SUCCESS(exception_assert_neg_gfunc, 1);
|
||||
|
|
|
|||
|
|
@ -212,6 +212,36 @@ int exception_throw_subprog(struct __sk_buff *ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u64 exception_cb_stack_src = 0x1234;
|
||||
|
||||
/*
|
||||
* The address handed to the helper has to be this callback's own stack
|
||||
* slot, not one from a frame that is already gone.
|
||||
*/
|
||||
__noinline int exception_cb_stack(u64 cookie)
|
||||
{
|
||||
volatile u64 val = 0xdead;
|
||||
|
||||
bpf_probe_read_kernel((void *)&val, sizeof(val), &exception_cb_stack_src);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Throws from a subprogram that has a stack of its own. */
|
||||
__noinline static int throwing_subprog_stack(struct __sk_buff *ctx)
|
||||
{
|
||||
volatile u64 pad[4] = {};
|
||||
|
||||
bpf_throw(pad[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("tc")
|
||||
__exception_cb(exception_cb_stack)
|
||||
int exception_throw_subprog_stack_cb(struct __sk_buff *ctx)
|
||||
{
|
||||
return throwing_subprog_stack(ctx);
|
||||
}
|
||||
|
||||
__noinline int assert_nz_gfunc(u64 c)
|
||||
{
|
||||
volatile u64 cookie = c;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user