From: sashiko-bot@kernel.org
To: "George Guo" <dongtai.guo@linux.dev>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH 3/5] LoongArch: BPF: Add exceptions (bpf_throw) support
Date: Thu, 18 Jun 2026 03:55:17 +0000 [thread overview]
Message-ID: <20260618035517.CE3601F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260618033809.98253-4-dongtai.guo@linux.dev>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Critical] `arch_bpf_stack_walk()` uses inline assembly to capture the live `$r22` register, incorrectly assuming it holds the unmodified BPF frame pointer.
Pre-existing issues:
- [High] Tail calls within exception programs (or arena programs) cause a kernel panic (NULL pointer dereference) due to a hardcoded stack offset macro.
--
commit 7327176c407071584a340964ddba1f924e66533a
Author: George Guo <guodongtai@kylinos.cn>
LoongArch: BPF: Add exceptions (bpf_throw) support
Implement BPF exception support, advertised via
bpf_jit_supports_exceptions(). bpf_throw() unwinds the stack to find the
exception boundary program's frame and then invokes its exception
callback with that frame's stack and frame pointers.
> diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c
> index 387dc4d3c4868..718c98b3f1fc4 100644
> --- a/arch/loongarch/kernel/stacktrace.c
> +++ b/arch/loongarch/kernel/stacktrace.c
[ ... ]
> @@ -40,6 +41,57 @@ void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
> }
> }
>
> +#ifdef CONFIG_UNWINDER_ORC
[ ... ]
> +void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp),
> + void *cookie)
> +{
> + unsigned long fp;
> +
> + /*
> + * Capture the live frame pointer ($r22/$fp) here, before handing off to
> + * the worker. The kernel is built with -fomit-frame-pointer, so $fp is
> + * an ordinary callee-saved register that is preserved across the call
> + * from the JITed BPF program into bpf_throw() down to here, and thus
> + * still points at the innermost BPF frame. The ORC frame-pointer
> + * fallback walks the BPF frames up to the exception boundary from it.
> + *
> + * This must be a thin wrapper with no large stack locals: the worker
> + * uses $r22 to address its frame, which would clobber the live $fp
> + * before it could be read. __builtin_frame_address() cannot be used
> + * either, as it is $sp-derived and would yield a kernel-stack frame.
> + */
> + asm volatile("move %0, $r22" : "=r"(fp));
[Severity: Critical]
Could the compiler clobber the live $r22 register before we capture it
here?
Since the kernel is built with -fomit-frame-pointer, bpf_throw() is
compiled as a standard C function and the compiler might use $r22 as a
general-purpose callee-saved register for local variables (such as the
cookie argument).
If $r22 is clobbered during bpf_throw(), this inline assembly will capture
the clobbered value instead of the unmodified BPF frame pointer. The
exception callback then blindly trusts this propagated value (passed via
$a2) to anchor its stack frame:
arch/loongarch/net/bpf_jit.c:build_prologue() {
...
move_reg(ctx, LOONGARCH_GPR_FP, LOONGARCH_GPR_A2);
emit_insn(ctx, addid, LOONGARCH_GPR_SP, LOONGARCH_GPR_FP, -stack_adjust);
...
}
Could this allow a forged chain of frame pointers to dictate the callback's
return address, leading to a severe regression where arbitrary kernel code
execution is possible?
> + walk_stackframe_bpf(consume_fn, cookie, fp);
> +}
> +#endif /* CONFIG_UNWINDER_ORC */
> +
> int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
> void *cookie, struct task_struct *task)
> {
> diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
> index c410b02e64bef..22527428f0b34 100644
> --- a/arch/loongarch/net/bpf_jit.c
> +++ b/arch/loongarch/net/bpf_jit.c
[ ... ]
> @@ -203,7 +223,7 @@ static void build_prologue(struct jit_ctx *ctx)
> store_offset -= sizeof(long);
> emit_insn(ctx, std, LOONGARCH_GPR_S5, LOONGARCH_GPR_SP, store_offset);
>
> - if (ctx->arena_vm_start) {
> + if (ctx->arena_vm_start || is_exception_prog) {
> store_offset -= sizeof(long);
> emit_insn(ctx, std, REG_ARENA, LOONGARCH_GPR_SP, store_offset);
> }
[Severity: High]
This isn't a bug introduced by this patch, but does forcing REG_ARENA to be
pushed for exception programs expose an issue with the tail call layout?
When is_exception_prog is true, this adds an extra 8 bytes to the stack.
However, emit_bpf_tail_call() relies on a hardcoded stack offset macro:
arch/loongarch/net/bpf_jit.c:emit_bpf_tail_call() {
...
int tcc_ptr_off = BPF_TAIL_CALL_CNT_PTR_STACK_OFF(ctx->stack_size);
...
emit_insn(ctx, ldd, t3, REG_TCC, 0);
...
}
Since BPF_TAIL_CALL_CNT_PTR_STACK_OFF(ctx->stack_size) evaluates to a fixed
offset (stack_size - 80) regardless of whether REG_ARENA was pushed, does
this cause emit_bpf_tail_call() to incorrectly fetch the TCC integer
instead of TCC_PTR?
If it fetches the integer (often 0) and immediately dereferences it, would
tail calls within exception programs or arena programs cause a NULL pointer
dereference?
> @@ -212,6 +232,7 @@ static void build_prologue(struct jit_ctx *ctx)
>
> emit_insn(ctx, addid, LOONGARCH_GPR_FP, LOONGARCH_GPR_SP, stack_adjust);
>
> +setup_bpf_fp:
> if (ctx->priv_sp_used) {
> /* Set up the private stack pointer and the BPF frame pointer */
> void __percpu *priv_stack_ptr;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260618033809.98253-1-dongtai.guo@linux.dev?part=3
next prev parent reply other threads:[~2026-06-18 3:55 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-18 3:38 [PATCH 0/5] LoongArch: BPF: arena instruction gating, private stack and exceptions George Guo
2026-06-18 3:38 ` [PATCH 1/5] LoongArch: BPF: Gate unsupported arena instructions via bpf_jit_supports_insn() George Guo
2026-06-18 3:53 ` sashiko-bot
2026-06-18 4:19 ` bot+bpf-ci
2026-06-18 3:38 ` [PATCH 2/5] LoongArch: BPF: Add private stack support George Guo
2026-06-18 3:55 ` sashiko-bot
2026-06-18 3:38 ` [PATCH 3/5] LoongArch: BPF: Add exceptions (bpf_throw) support George Guo
2026-06-18 3:55 ` sashiko-bot [this message]
2026-06-18 3:38 ` [PATCH 4/5] selftests/bpf: Add LoongArch deny list George Guo
2026-06-18 3:52 ` sashiko-bot
2026-06-18 3:38 ` [PATCH 5/5] selftests/bpf: Enable struct_ops private stack test for LoongArch George Guo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260618035517.CE3601F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dongtai.guo@linux.dev \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox