* Re: [PATCHv2 bpf-next 2/2] bpf: Disable private stacks for untagged kprobe programs
2026-11-06 16:40 ` [PATCHv2 bpf-next 2/2] bpf: Disable private stacks for untagged kprobe programs Jiri Olsa
@ 2026-11-06 17:02 ` sashiko-bot
2026-11-06 17:17 ` bot+bpf-ci
2026-11-13 14:53 ` Jiri Olsa
2 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-11-06 17:02 UTC (permalink / raw)
To: Jiri Olsa; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] bpf: bpf_enable_priv_stack() allows private stack on uprobe
via IOC_SET_BPF
- [Low] bpf: missing Fixes trailer for commit a76ab5731e32 in commit
message
--
commit f0768285bc0b64d913853bd20bc1d61e4c54eed4
Author: Jiri Olsa <jolsa@kernel.org>
> bpf: Disable private stacks for untagged kprobe programs
>
> Uprobe programs can be preempted and re-entered on the same CPU. Since
> the private stack is shared per program and CPU, another invocation can
> overwrite the preempted invocation's stack.
>
> Programs without a multi or session attach type may be standard kprobes
> or uprobes. Disable private stacks for them, and retain private stacks
> only for kprobe multi and session programs, which have attach types that
> identify them as kprobes.
>
> Update verifier tests that rely on private stacks to use kprobe.multi,
> and add coverage that untagged kprobe and uprobe programs do not use
> private stacks.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
[Severity: Low]
Should this commit include a Fixes tag for a76ab5731e32 ("bpf: Find
eligible subprogs for private stack support")?
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index b7329d164771c..1b58a1796a2e4 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -5749,6 +5749,15 @@ static enum priv_stack_mode bpf_enable_priv_stack(struct bpf_prog *prog)
> */
> switch (prog->type) {
> case BPF_PROG_TYPE_KPROBE:
> + /*
> + * Uprobes are preemptible and lack recursion protection. Classic
> + * kprobe and uprobe progs have no expected attach type, so enable
> + * private stacks only for kprobe.multi and kprobe.session progs.
> + */
> + if (prog->expected_attach_type != BPF_TRACE_KPROBE_MULTI &&
> + prog->expected_attach_type != BPF_TRACE_KPROBE_SESSION)
> + return NO_PRIV_STACK;
[Severity: Medium]
Can a BPF_PROG_TYPE_KPROBE program with a private stack still be attached
to a classic uprobe through PERF_EVENT_IOC_SET_BPF?
At load time, bpf_prog_load_check_attach() accepts BPF_TRACE_KPROBE_MULTI
or BPF_TRACE_KPROBE_SESSION on any BPF_PROG_TYPE_KPROBE program (including
sleepable ones, since can_be_sleepable() only checks prog->type ==
BPF_PROG_TYPE_KPROBE). While BPF_LINK_CREATE checks expected_attach_type
via bpf_prog_attach_check_attach_type(), attaching via
ioctl(perf_event_fd, PERF_EVENT_IOC_SET_BPF, prog_fd) ->
__perf_event_set_bpf_prog() only checks prog->type:
kernel/events/core.c:__perf_event_set_bpf_prog() {
...
if (((is_kprobe || is_uprobe) && prog->type != BPF_PROG_TYPE_KPROBE) ||
(is_tracepoint && prog->type != BPF_PROG_TYPE_TRACEPOINT) ||
(is_syscall_tp && prog->type != BPF_PROG_TYPE_TRACEPOINT))
return -EINVAL;
...
}
A BPF_PROG_TYPE_KPROBE program loaded with BPF_TRACE_KPROBE_MULTI or
BPF_TRACE_KPROBE_SESSION therefore still gets a per-CPU private stack and
can be attached to a uprobe perf_event, where __uprobe_perf_func() ->
bpf_prog_run_array_uprobe() runs it in preemptible (and optionally
sleepable) context without recursion protection, allowing preemption and
re-entry on the same CPU to overwrite the active invocation's private
stack.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261106164043.546879-3-jolsa@kernel.org?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCHv2 bpf-next 2/2] bpf: Disable private stacks for untagged kprobe programs
2026-11-06 16:40 ` [PATCHv2 bpf-next 2/2] bpf: Disable private stacks for untagged kprobe programs Jiri Olsa
2026-11-06 17:02 ` sashiko-bot
@ 2026-11-06 17:17 ` bot+bpf-ci
2026-11-13 14:53 ` Jiri Olsa
2 siblings, 0 replies; 7+ messages in thread
From: bot+bpf-ci @ 2026-11-06 17:17 UTC (permalink / raw)
To: jolsa, ast, daniel, andrii
Cc: bpf, martin.lau, eddyz87, song, yonghong.song, sammiee5311, simon,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, mason,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 3195 bytes --]
> bpf: Disable private stacks for untagged kprobe programs
TL;DR: Disabling private stacks for classic kprobe programs may make
previously loadable programs fail verification (-EACCES) once frames count
combined against the stack limit, e.g. on powerpc64; the commit message
doesn't mention it.
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
[ ... ]
> @@ -5749,6 +5749,15 @@ static enum priv_stack_mode bpf_enable_priv_stack(struct bpf_prog *prog)
> */
> switch (prog->type) {
> case BPF_PROG_TYPE_KPROBE:
> + /*
> + * Uprobes are preemptible and lack recursion protection. Classic
> + * kprobe and uprobe progs have no expected attach type, so enable
> + * private stacks only for kprobe.multi and kprobe.session progs.
> + */
> + if (prog->expected_attach_type != BPF_TRACE_KPROBE_MULTI &&
> + prog->expected_attach_type != BPF_TRACE_KPROBE_SESSION)
> + return NO_PRIV_STACK;
> + fallthrough;
Classic SEC("kprobe"), kretprobe and ksyscall programs run through
trace_call_bpf(), which has cant_sleep() and the per-CPU bpf_prog_active
guard, so they never had the re-entry problem. They lose private stacks
only because they cannot be told apart from uprobes.
Does this change which classic kprobe programs the verifier accepts?
check_call_depth() treats a frame separately when private stacks are on:
if (si[s].priv_stack_mode == PRIV_STACK_ADAPTIVE) {
depth = round_up_stack_depth(env, si[s].stack_depth);
...
continue;
}
depth = dinfo[s].depth + subprog_stack_size(env, s);
...
if (depth > env->stack_limit) {
verbose(env, "combined stack size of %d calls is %d. Too large\n", ...
subprog_stack_size() returns 0 for an ADAPTIVE frame, so before this patch
the frames of a kprobe program were not added together. Now they are, and
a program that loaded before can fail with -EACCES.
For example, on powerpc64 bpf_jit_supports_private_stack() returns
IS_ENABLED(CONFIG_PPC64) and there is no bpf_jit_supports_large_stack(), so
bpf_prog_stack_limit() returns MAX_BPF_STACK (512). A SEC("kprobe")
program with a 512-byte main frame calling a subprog with a 32-byte frame
used to load, and would now fail with "combined stack size of 2 calls is
544. Too large". This is the shape of the "Private stack, subtree >
MAX_BPF_STACK" selftest that this patch moves to kprobe.multi.
On x86-64 and arm64 the limit becomes MAX_BPF_STACK_JIT (2048) combined,
where it used to be 2048 per frame. If this is backported to a tree
without MAX_BPF_STACK_JIT, x86-64 and arm64 would fall back to 512
combined for these programs.
The commit message does not mention that existing classic kprobe programs
can now fail verification, or that users need to move to kprobe.multi or
kprobe.session to keep the larger stack budget. Is this rejection
intended? If so, could the changelog say so?
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/42256932632
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCHv2 bpf-next 2/2] bpf: Disable private stacks for untagged kprobe programs
2026-11-06 16:40 ` [PATCHv2 bpf-next 2/2] bpf: Disable private stacks for untagged kprobe programs Jiri Olsa
2026-11-06 17:02 ` sashiko-bot
2026-11-06 17:17 ` bot+bpf-ci
@ 2026-11-13 14:53 ` Jiri Olsa
2 siblings, 0 replies; 7+ messages in thread
From: Jiri Olsa @ 2026-11-13 14:53 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
Cc: bpf, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
HyeongJun An, Christian Simon, stable
On Fri, Nov 06, 2026 at 05:40:43PM +0100, Jiri Olsa wrote:
> Uprobe programs can be preempted and re-entered on the same CPU. Since
> the private stack is shared per program and CPU, another invocation can
> overwrite the preempted invocation's stack.
>
> Programs without a multi or session attach type may be standard kprobes
> or uprobes. Disable private stacks for them, and retain private stacks
> only for kprobe multi and session programs, which have attach types that
> identify them as kprobes.
>
> Update verifier tests that rely on private stacks to use kprobe.multi,
> and add coverage that untagged kprobe and uprobe programs do not use
> private stacks.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
hi,
I did not realize before, but I think this should be added to stable
Fixes: a76ab5731e32 ("bpf: Find eligible subprogs for private stack support")
Cc: stable@vger.kernel.org
jirka
> ---
> kernel/bpf/verifier.c | 9 +++++
> .../bpf/progs/verifier_large_stack.c | 2 +-
> .../bpf/progs/verifier_private_stack.c | 38 ++++++++++++++++++-
> 3 files changed, 46 insertions(+), 3 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index b7329d164771..1b58a1796a2e 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -5749,6 +5749,15 @@ static enum priv_stack_mode bpf_enable_priv_stack(struct bpf_prog *prog)
> */
> switch (prog->type) {
> case BPF_PROG_TYPE_KPROBE:
> + /*
> + * Uprobes are preemptible and lack recursion protection. Classic
> + * kprobe and uprobe progs have no expected attach type, so enable
> + * private stacks only for kprobe.multi and kprobe.session progs.
> + */
> + if (prog->expected_attach_type != BPF_TRACE_KPROBE_MULTI &&
> + prog->expected_attach_type != BPF_TRACE_KPROBE_SESSION)
> + return NO_PRIV_STACK;
> + fallthrough;
> case BPF_PROG_TYPE_TRACEPOINT:
> case BPF_PROG_TYPE_PERF_EVENT:
> case BPF_PROG_TYPE_RAW_TRACEPOINT:
> diff --git a/tools/testing/selftests/bpf/progs/verifier_large_stack.c b/tools/testing/selftests/bpf/progs/verifier_large_stack.c
> index 7e4f5e3463a2..cbabb41d973c 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_large_stack.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_large_stack.c
> @@ -243,7 +243,7 @@ static void priv_stack_frame_2048(void)
> " ::: __clobber_all);
> }
>
> -SEC("kprobe")
> +SEC("kprobe.multi")
> __description("private stack: two frames of 2048 bytes")
> __load_if_large_stack()
> __arch_x86_64
> diff --git a/tools/testing/selftests/bpf/progs/verifier_private_stack.c b/tools/testing/selftests/bpf/progs/verifier_private_stack.c
> index aa15361bcca5..0ce07bf6b566 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_private_stack.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_private_stack.c
> @@ -22,7 +22,7 @@ struct {
> __type(value, struct elem);
> } array SEC(".maps");
>
> -SEC("kprobe")
> +SEC("kprobe.multi")
> __description("Private stack, single prog")
> __success
> __arch_x86_64
> @@ -110,6 +110,40 @@ int no_private_stack_stack_args(void)
> }
> #endif
>
> +SEC("kprobe")
> +__description("No private stack, untagged kprobe")
> +__success
> +__arch_x86_64
> +__jited(" subq $0x100, %rsp")
> +__arch_arm64
> +__jited(" sub sp, sp, #0x100")
> +__naked void no_private_stack_kprobe(void)
> +{
> + asm volatile (" \
> + r1 = 42; \
> + *(u64 *)(r10 - 256) = r1; \
> + r0 = 0; \
> + exit; \
> +" ::: __clobber_all);
> +}
> +
> +SEC("uprobe")
> +__description("No private stack, uprobe")
> +__success
> +__arch_x86_64
> +__jited(" subq $0x100, %rsp")
> +__arch_arm64
> +__jited(" sub sp, sp, #0x100")
> +__naked void no_private_stack_uprobe(void)
> +{
> + asm volatile (" \
> + r1 = 42; \
> + *(u64 *)(r10 - 256) = r1; \
> + r0 = 0; \
> + exit; \
> +" ::: __clobber_all);
> +}
> +
> __used
> __naked static void cumulative_stack_depth_subprog(void)
> {
> @@ -123,7 +157,7 @@ __naked static void cumulative_stack_depth_subprog(void)
> : __clobber_all);
> }
>
> -SEC("kprobe")
> +SEC("kprobe.multi")
> __description("Private stack, subtree > MAX_BPF_STACK")
> __success
> __log_level(4) __msg("stack depth max 512")
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 7+ messages in thread