* [PATCH bpf v1 00/10] Misc bug fixes - part 1
@ 2026-09-03 14:44 Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 01/10] bpf: Mark signal tracepoint siginfo arguments as scalar Kumar Kartikeya Dwivedi
` (10 more replies)
0 siblings, 11 replies; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team
A set of miscellaneous fixes for bugs reported by Nicholas. These are
easy ones and should not require any major discussion, hence batched
together. See commit logs and selftests for details.
Kumar Kartikeya Dwivedi (10):
bpf: Mark signal tracepoint siginfo arguments as scalar
selftests/bpf: Cover signal tracepoint siginfo sentinels
bpf: Reject tail calls directly from callback frames
selftests/bpf: Test direct tail calls from callbacks
bpf: Reject resilient lock operations in rbtree callbacks
selftests/bpf: Reject resilient unlock in rbtree callback
bpf: Mark sched_process_wait argument as nullable
selftests/bpf: Test sched_process_wait nullable argument
bpf: Mark syscall helpers as sleepable
selftests/bpf: Check syscall helpers in timer callbacks
kernel/bpf/btf.c | 7 ++
kernel/bpf/syscall.c | 2 +
kernel/bpf/verifier.c | 16 +++++
.../selftests/bpf/progs/raw_tp_null_fail.c | 53 +++++++++++++++
.../testing/selftests/bpf/progs/rbtree_fail.c | 29 +++++++++
.../selftests/bpf/progs/tailcall_callback.c | 16 +++++
.../bpf/progs/verifier_async_cb_context.c | 64 +++++++++++++++++++
7 files changed, 187 insertions(+)
base-commit: ac0aaef0aa997fcdcb2458bd584539ba8608d33e
--
2.53.0
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH bpf v1 01/10] bpf: Mark signal tracepoint siginfo arguments as scalar
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 14:44 ` [PATCH bpf v1 02/10] selftests/bpf: Cover signal tracepoint siginfo sentinels Kumar Kartikeya Dwivedi
` (9 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Nicholas Carlini, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd,
kernel-team
The signal_generate and signal_deliver tracepoints declare their info
argument as a struct kernel_siginfo pointer. btf_ctx_access() therefore
treats it as a trusted pointer for tp_btf programs.
Signal delivery also uses SEND_SIG_NOINFO and SEND_SIG_PRIV as special
values for this argument. Those values are zero and one respectively,
and are not pointers. A tp_btf program can currently dereference either
value and fault the kernel. In particular, signal_generate can run from
timer interrupt context, turning the fault into a kernel panic.
Record both tracepoints in raw_tp_null_args[] and mark argument one as
a non-pointer. This preserves scalar access to the cookie while rejecting
direct and helper-mediated pointer use. Merely marking it nullable would
not suffice because SEND_SIG_PRIV is nonzero.
Fixes: 838a10bd2ebf ("bpf: Augment raw_tp arguments with PTR_MAYBE_NULL")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
kernel/bpf/btf.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index da36d4b9d31a..d6d243c262ea 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -6717,6 +6717,9 @@ static const struct bpf_raw_tp_null_args raw_tp_null_args[] = {
{ "rxrpc_resend", 0x10 },
{ "rxrpc_tq", 0x10 },
{ "rxrpc_client", 0x1 },
+ /* signal */
+ { "signal_generate", 0x20 },
+ { "signal_deliver", 0x20 },
/* skb */
{"kfree_skb", 0x1000},
/* sunrpc */
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf v1 02/10] selftests/bpf: Cover signal tracepoint siginfo sentinels
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 01/10] bpf: Mark signal tracepoint siginfo arguments as scalar Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 14:44 ` [PATCH bpf v1 03/10] bpf: Reject tail calls directly from callback frames Kumar Kartikeya Dwivedi
` (8 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team
Add load-only verifier coverage for the signal_generate and
signal_deliver info arguments. The signal_generate case performs a NULL
check before dereferencing info, ensuring that merely making it nullable
cannot satisfy the test when the nonzero SEND_SIG_PRIV sentinel is used.
Both programs load successfully without the verifier fix, contrary to
their expected-failure annotations. With the fix, info is a scalar and
the attempted dereferences are rejected.
Also add success cases showing that plain raw tracepoint and tp_btf
programs can continue to read and compare the context word as a scalar.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
.../selftests/bpf/progs/raw_tp_null_fail.c | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c b/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c
index 0d58114a4955..7e8842bf9000 100644
--- a/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c
+++ b/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c
@@ -22,3 +22,39 @@ int test_raw_tp_null_sched_pi_setprio_arg_2(void *ctx) {
asm volatile("r1 = *(u64 *)(r1 +8); r1 = *(u64 *)(r1 +0);" ::: __clobber_all);
return 0;
}
+
+/* Plain raw tracepoint arguments remain scalar values. */
+SEC("raw_tp/signal_generate")
+__success
+int test_raw_tp_signal_generate_info_scalar(void *ctx)
+{
+ asm volatile("r1 = *(u64 *)(r1 +8); if r1 != 1 goto +0;" ::: __clobber_all);
+ return 0;
+}
+
+/* tp_btf programs may inspect the sentinel as a scalar value. */
+SEC("tp_btf/signal_generate")
+__success
+int test_tp_btf_signal_generate_info_scalar(void *ctx)
+{
+ asm volatile("r1 = *(u64 *)(r1 +8); if r1 != 1 goto +0;" ::: __clobber_all);
+ return 0;
+}
+
+/* SEND_SIG_PRIV is non-NULL, so a NULL check cannot make info safe. */
+SEC("tp_btf/signal_generate")
+__failure __msg("R1 invalid mem access 'scalar'")
+int test_tp_btf_signal_generate_info_no_deref(void *ctx)
+{
+ asm volatile("r1 = *(u64 *)(r1 +8); if r1 == 0 goto +1; "
+ "r1 = *(u32 *)(r1 +0);" ::: __clobber_all);
+ return 0;
+}
+
+SEC("tp_btf/signal_deliver")
+__failure __msg("R1 invalid mem access 'scalar'")
+int test_tp_btf_signal_deliver_info_no_deref(void *ctx)
+{
+ asm volatile("r1 = *(u64 *)(r1 +8); r1 = *(u32 *)(r1 +0);" ::: __clobber_all);
+ return 0;
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf v1 03/10] bpf: Reject tail calls directly from callback frames
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 01/10] bpf: Mark signal tracepoint siginfo arguments as scalar Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 02/10] selftests/bpf: Cover signal tracepoint siginfo sentinels Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 15:21 ` sashiko-bot
2026-09-03 14:44 ` [PATCH bpf v1 04/10] selftests/bpf: Test direct tail calls from callbacks Kumar Kartikeya Dwivedi
` (7 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Nicholas Carlini, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd,
kernel-team
A tail call from a non-zero frame is modeled as a return from that frame.
The verifier makes R0 unknown and calls prepare_func_exit() for the taken
branch.
When the current frame is a synchronous callback, prepare_func_exit()
enforces the callback return-value contract and marks R0 precise. Since the
tail-call path synthesized R0 rather than deriving it from an instruction,
precision backtracking reaches the callback-calling instruction with R0
still requested and triggers the "callback unexpected regs" verifier bug.
A CAP_BPF task can therefore cause a WARN and an -EFAULT BPF_PROG_LOAD.
Tail calls reachable from callbacks are already rejected later by
check_max_stack_depth(). Reject a tail call made directly by a callback
before constructing the inconsistent return state, using the existing
diagnostic. Tail calls from ordinary subprograms keep their current
behavior.
Fixes: e3245f899043 ("bpf: properly verify tail call behavior")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
kernel/bpf/verifier.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 7d8ddb1bee00..f540279ff4ab 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -11228,6 +11228,17 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
if (env->cur_state->curframe) {
struct bpf_verifier_state *branch;
+ /*
+ * A taken tail call is modeled as a return from the current
+ * frame. A callback frame cannot be left that way because
+ * prepare_func_exit() would apply its return contract to the
+ * unknown R0 synthesized below. Stack-depth validation rejects
+ * this construct anyway.
+ */
+ if (cur_func(env)->in_callback_fn) {
+ verbose(env, "cannot tail call within callback\n");
+ return -EINVAL;
+ }
mark_reg_scratched(env, BPF_REG_0);
branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
if (IS_ERR(branch))
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf v1 04/10] selftests/bpf: Test direct tail calls from callbacks
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
` (2 preceding siblings ...)
2026-09-03 14:44 ` [PATCH bpf v1 03/10] bpf: Reject tail calls directly from callback frames Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 05/10] bpf: Reject resilient lock operations in rbtree callbacks Kumar Kartikeya Dwivedi
` (6 subsequent siblings)
10 siblings, 0 replies; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team
tailcall_callback tests a tail call one static subprogram below a callback.
That reaches the later stack-depth rejection, but it does not exercise the
tail-call helper while the current frame is itself a callback.
Add a callback that calls bpf_tail_call directly and expect the existing
"cannot tail call within callback" diagnostic. On an affected kernel, the
load instead reaches the "callback unexpected regs" verifier bug, so the
expected message is absent and the test fails. The existing ordinary
subprogram case remains a success control for legitimate tail calls.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
.../selftests/bpf/progs/tailcall_callback.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/tailcall_callback.c b/tools/testing/selftests/bpf/progs/tailcall_callback.c
index c41632cf423b..14fa7a87028e 100644
--- a/tools/testing/selftests/bpf/progs/tailcall_callback.c
+++ b/tools/testing/selftests/bpf/progs/tailcall_callback.c
@@ -44,6 +44,13 @@ int callback_loop(int index, void **cb_ctx)
return ret ? 1 : 0;
}
+static __noinline
+int callback_tail(int index, void **cb_ctx)
+{
+ bpf_tail_call_static(*cb_ctx, &jmp_table, 0);
+ return 0;
+}
+
static __noinline
int callback_empty(int index, void *data)
{
@@ -78,4 +85,13 @@ int tailcall_callback_2(struct __sk_buff *skb)
return 0;
}
+/* callback with a direct tail call is rejected without a verifier bug */
+SEC("tc")
+__failure __msg("cannot tail call within callback")
+int tailcall_callback_3(struct __sk_buff *skb)
+{
+ bpf_loop(1, callback_tail, &skb, 0);
+ return 0;
+}
+
char __license[] SEC("license") = "GPL";
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf v1 05/10] bpf: Reject resilient lock operations in rbtree callbacks
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
` (3 preceding siblings ...)
2026-09-03 14:44 ` [PATCH bpf v1 04/10] selftests/bpf: Test direct tail calls from callbacks Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 15:31 ` sashiko-bot
2026-09-03 14:44 ` [PATCH bpf v1 06/10] selftests/bpf: Reject resilient unlock in rbtree callback Kumar Kartikeya Dwivedi
` (5 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Nicholas Carlini, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd,
kernel-team
__bpf_rbtree_add() keeps parent and link pointers live across calls to the
program-supplied comparison callback. The verifier therefore requires the
root's lock to remain held throughout the callback.
The helper path enforces this rule for bpf_spin_lock() and
bpf_spin_unlock(), but the resilient lock kfunc argument path does not.
Since resilient locks may protect BPF rbtree roots, a callback can release
the root lock and let another CPU remove and free the node referenced by
the in-progress tree walk. The walk then resumes using freed pointers.
Reject resilient lock kfuncs in an rbtree comparison callback, matching
the existing policy for the spin lock helpers. Resilient-lock-protected
trees remain valid when their comparison callbacks leave lock state alone.
Fixes: 0de2046137f9 ("bpf: Implement verifier support for rqspinlock")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
kernel/bpf/verifier.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index f540279ff4ab..32d31fa67036 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -13241,6 +13241,11 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me
{
int flags = PROCESS_RES_LOCK;
+ if (in_rbtree_lock_required_cb(env)) {
+ verbose(env, "can't res_spin_{lock,unlock} in rbtree cb\n");
+ return -EACCES;
+ }
+
if (reg->type != PTR_TO_MAP_VALUE && reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
verbose(env, "%s doesn't point to map value or allocated object\n",
reg_arg_name(env, argno));
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf v1 06/10] selftests/bpf: Reject resilient unlock in rbtree callback
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
` (4 preceding siblings ...)
2026-09-03 14:44 ` [PATCH bpf v1 05/10] bpf: Reject resilient lock operations in rbtree callbacks Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 14:44 ` [PATCH bpf v1 07/10] bpf: Mark sched_process_wait argument as nullable Kumar Kartikeya Dwivedi
` (4 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team
Add a load-only verifier regression for a resilient lock operation in an
rbtree comparison callback. The program holds the rbtree's regular spin
lock and a separate resilient lock, then releases the resilient lock from
the callback. This isolates the missing kfunc policy check without running
a concurrent tree mutation.
Release the resilient lock before the regular lock on the outer
fall-through. The broken verifier therefore accepts the balanced program,
while the fixed verifier rejects the resilient unlock specifically while
verifying the callback.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
.../testing/selftests/bpf/progs/rbtree_fail.c | 29 +++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/rbtree_fail.c b/tools/testing/selftests/bpf/progs/rbtree_fail.c
index 555379952dcc..803419a47c62 100644
--- a/tools/testing/selftests/bpf/progs/rbtree_fail.c
+++ b/tools/testing/selftests/bpf/progs/rbtree_fail.c
@@ -16,6 +16,7 @@ struct node_data {
private(A) struct bpf_spin_lock glock;
private(A) struct bpf_rb_root groot __contains(node_data, node);
private(A) struct bpf_rb_root groot2 __contains(node_data, node);
+private(B) struct bpf_res_spin_lock res_glock;
static bool less(struct bpf_rb_node *a, const struct bpf_rb_node *b)
{
@@ -265,6 +266,12 @@ static bool less__bad_fn_call_first_unlock_after(struct bpf_rb_node *a, const st
return node_a->key < node_b->key;
}
+static bool less__bad_res_spin_unlock(struct bpf_rb_node *a, const struct bpf_rb_node *b)
+{
+ bpf_res_spin_unlock(&res_glock);
+ return false;
+}
+
static __always_inline
long add_with_cb(bool (cb)(struct bpf_rb_node *a, const struct bpf_rb_node *b))
{
@@ -301,4 +308,26 @@ long rbtree_api_add_bad_cb_bad_fn_call_first_unlock_after(void *ctx)
return add_with_cb(less__bad_fn_call_first_unlock_after);
}
+SEC("?tc")
+__failure __msg("can't res_spin_{lock,unlock} in rbtree cb")
+long rbtree_api_add_bad_cb_res_spin_unlock(void *ctx)
+{
+ struct node_data *n;
+
+ n = bpf_obj_new(typeof(*n));
+ if (!n)
+ return 1;
+
+ bpf_spin_lock(&glock);
+ if (bpf_res_spin_lock(&res_glock)) {
+ bpf_spin_unlock(&glock);
+ bpf_obj_drop(n);
+ return 1;
+ }
+ bpf_rbtree_add(&groot, &n->node, less__bad_res_spin_unlock);
+ bpf_res_spin_unlock(&res_glock);
+ bpf_spin_unlock(&glock);
+ return 0;
+}
+
char _license[] SEC("license") = "GPL";
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf v1 07/10] bpf: Mark sched_process_wait argument as nullable
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
` (5 preceding siblings ...)
2026-09-03 14:44 ` [PATCH bpf v1 06/10] selftests/bpf: Reject resilient unlock in rbtree callback Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 14:44 ` [PATCH bpf v1 08/10] selftests/bpf: Test sched_process_wait nullable argument Kumar Kartikeya Dwivedi
` (3 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Nicholas Carlini, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd,
kernel-team
do_wait() passes wo->wo_pid to the sched_process_wait tracepoint.
kernel_wait4() leaves wo_pid NULL for wait4(-1), and
kernel_waitid_prepare() does likewise for waitid(P_ALL).
btf_ctx_access() currently types argument 0 as PTR_TO_BTF_ID |
PTR_TRUSTED. Without PTR_MAYBE_NULL, the verifier accepts an unchecked
dereference. Trusted pointer loads have no fault protection, so a wait for
any child can then cause a NULL pointer dereference in JITed BPF code.
Add sched_process_wait to raw_tp_null_args[] with argument 0 marked
nullable. The verifier rejects an unchecked dereference while preserving
access after the program checks the pointer for NULL.
Fixes: 838a10bd2ebf ("bpf: Augment raw_tp arguments with PTR_MAYBE_NULL")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
kernel/bpf/btf.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index d6d243c262ea..41764356d2d3 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -6657,6 +6657,10 @@ struct bpf_raw_tp_null_args {
static const struct bpf_raw_tp_null_args raw_tp_null_args[] = {
/* sched */
{ "sched_pi_setprio", 0x10 },
+ /*
+ * do_wait() passes NULL for wait4(-1) and waitid(P_ALL).
+ */
+ { "sched_process_wait", 0x1 },
/* ... from sched_numa_pair_template event class */
{ "sched_stick_numa", 0x100 },
{ "sched_swap_numa", 0x100 },
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf v1 08/10] selftests/bpf: Test sched_process_wait nullable argument
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
` (6 preceding siblings ...)
2026-09-03 14:44 ` [PATCH bpf v1 07/10] bpf: Mark sched_process_wait argument as nullable Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 09/10] bpf: Mark syscall helpers as sleepable Kumar Kartikeya Dwivedi
` (2 subsequent siblings)
10 siblings, 0 replies; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team
Add a load-time verifier test that dereferences argument 0 of the
sched_process_wait tp_btf program without checking it. The test expects the
nullable-pointer diagnostic, so it is accepted unexpectedly before the fix
and rejected as expected after it.
Add a successful control that checks the argument for NULL before the
dereference. This ensures the nullable marking preserves legitimate access
to the pid when the tracepoint supplies one.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
.../selftests/bpf/progs/raw_tp_null_fail.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c b/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c
index 7e8842bf9000..725d73c9ffe1 100644
--- a/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c
+++ b/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c
@@ -58,3 +58,20 @@ int test_tp_btf_signal_deliver_info_no_deref(void *ctx)
asm volatile("r1 = *(u64 *)(r1 +8); r1 = *(u32 *)(r1 +0);" ::: __clobber_all);
return 0;
}
+
+SEC("tp_btf/sched_process_wait")
+__failure __msg("R1 invalid mem access 'trusted_ptr_or_null_'")
+int test_raw_tp_null_sched_process_wait_arg_1(void *ctx)
+{
+ asm volatile("r1 = *(u64 *)(r1 +0); r1 = *(u32 *)(r1 +0);" ::: __clobber_all);
+ return 0;
+}
+
+SEC("tp_btf/sched_process_wait")
+__success
+int test_raw_tp_null_sched_process_wait_arg_1_checked(void *ctx)
+{
+ asm volatile("r1 = *(u64 *)(r1 +0); if r1 == 0 goto +1; "
+ "r1 = *(u32 *)(r1 +0);" ::: __clobber_all);
+ return 0;
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf v1 09/10] bpf: Mark syscall helpers as sleepable
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
` (7 preceding siblings ...)
2026-09-03 14:44 ` [PATCH bpf v1 08/10] selftests/bpf: Test sched_process_wait nullable argument Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 15:51 ` sashiko-bot
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 14:44 ` [PATCH bpf v1 10/10] selftests/bpf: Check syscall helpers in timer callbacks Kumar Kartikeya Dwivedi
2026-09-03 16:50 ` [PATCH bpf v1 00/10] Misc bug fixes - part 1 patchwork-bot+netdevbpf
10 siblings, 2 replies; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Nicholas Carlini, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd,
kernel-team
bpf_sys_bpf() executes the bpf(2) syscall body, which can take mutexes,
allocate with GFP_KERNEL, and wait for an RCU grace period.
bpf_sys_close() reaches close_fd() and filp_close(), which can sleep as
well.
Both helpers are limited to BPF_PROG_TYPE_SYSCALL, whose main program is
sleepable. That does not make every callback sleepable: a syscall program
can register a bpf_timer callback, and the verifier checks that callback
in a non-sleepable context while retaining the syscall helper set.
Without .might_sleep on the prototypes, such a callback can invoke
bpf_sys_bpf() from hrtimer softirq context and trigger a
scheduling-while-atomic failure. bpf_sys_close() is exposed through the
same missing context check.
Set .might_sleep on both prototypes so the existing helper-context check
rejects them from timer callbacks and other atomic regions. Calls from the
sleepable main body remain valid.
Fixes: 79a7f8bdb159 ("bpf: Introduce bpf_sys_bpf() helper and program type.")
Fixes: 3abea089246f ("bpf: Add bpf_sys_close() helper.")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
kernel/bpf/syscall.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 6874ba1424af..c7bc9ba9b331 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -6568,6 +6568,7 @@ EXPORT_SYMBOL_NS(kern_sys_bpf, "BPF_INTERNAL");
static const struct bpf_func_proto bpf_sys_bpf_proto = {
.func = bpf_sys_bpf,
.gpl_only = false,
+ .might_sleep = true,
.ret_type = RET_INTEGER,
.arg1_type = ARG_ANYTHING,
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
@@ -6593,6 +6594,7 @@ BPF_CALL_1(bpf_sys_close, u32, fd)
static const struct bpf_func_proto bpf_sys_close_proto = {
.func = bpf_sys_close,
.gpl_only = false,
+ .might_sleep = true,
.ret_type = RET_INTEGER,
.arg1_type = ARG_ANYTHING,
};
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf v1 10/10] selftests/bpf: Check syscall helpers in timer callbacks
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
` (8 preceding siblings ...)
2026-09-03 14:44 ` [PATCH bpf v1 09/10] bpf: Mark syscall helpers as sleepable Kumar Kartikeya Dwivedi
@ 2026-09-03 14:44 ` Kumar Kartikeya Dwivedi
2026-09-03 16:50 ` [PATCH bpf v1 00/10] Misc bug fixes - part 1 patchwork-bot+netdevbpf
10 siblings, 0 replies; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 14:44 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team
A BPF_PROG_TYPE_SYSCALL program is sleepable, but its bpf_timer callbacks
run in a non-sleepable hrtimer softirq context.
Add verifier cases that call bpf_sys_bpf() and bpf_sys_close() from timer
callbacks. Without the syscall helper prototype annotations these programs
load, so their failure expectations expose the bug.
Also add successful controls that call each helper from the syscall program
main body, ensuring that the intended sleepable use remains accepted.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
.../bpf/progs/verifier_async_cb_context.c | 64 +++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c b/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
index 6bf95550a024..a7c84d3fa4c7 100644
--- a/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
+++ b/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
@@ -62,6 +62,70 @@ int timer_sleepable_prog(void *ctx)
return 0;
}
+static int timer_sys_bpf_cb(void *map, int *key, struct bpf_timer *timer)
+{
+ __u64 attr = 0;
+
+ bpf_sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr));
+ return 0;
+}
+
+SEC("syscall")
+__failure __msg("sleepable helper bpf_sys_bpf#{{[0-9]+}} in non-sleepable prog")
+int timer_sys_bpf_prog(void *ctx)
+{
+ struct timer_elem *val;
+ int key = 0;
+
+ val = bpf_map_lookup_elem(&timer_map, &key);
+ if (!val)
+ return 0;
+
+ bpf_timer_init(&val->t, &timer_map, 0);
+ bpf_timer_set_callback(&val->t, timer_sys_bpf_cb);
+ return 0;
+}
+
+static int timer_sys_close_cb(void *map, int *key, struct bpf_timer *timer)
+{
+ bpf_sys_close(0);
+ return 0;
+}
+
+SEC("syscall")
+__failure __msg("sleepable helper bpf_sys_close#{{[0-9]+}} in non-sleepable prog")
+int timer_sys_close_prog(void *ctx)
+{
+ struct timer_elem *val;
+ int key = 0;
+
+ val = bpf_map_lookup_elem(&timer_map, &key);
+ if (!val)
+ return 0;
+
+ bpf_timer_init(&val->t, &timer_map, 0);
+ bpf_timer_set_callback(&val->t, timer_sys_close_cb);
+ return 0;
+}
+
+SEC("syscall")
+__success
+int syscall_sys_bpf_prog(void *ctx)
+{
+ __u64 attr = 0;
+
+ bpf_sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr));
+ return 0;
+}
+
+SEC("syscall")
+__success
+int syscall_sys_close_prog(void *ctx)
+{
+ bpf_sys_close(0);
+ return 0;
+}
+
/* Workqueue tests */
struct wq_elem {
--
2.53.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 03/10] bpf: Reject tail calls directly from callback frames
2026-09-03 14:44 ` [PATCH bpf v1 03/10] bpf: Reject tail calls directly from callback frames Kumar Kartikeya Dwivedi
@ 2026-09-03 15:21 ` sashiko-bot
2026-09-03 15:36 ` Kumar Kartikeya Dwivedi
0 siblings, 1 reply; 24+ messages in thread
From: sashiko-bot @ 2026-09-03 15:21 UTC (permalink / raw)
To: Kumar Kartikeya Dwivedi; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The patch prevents bpf_tail_call within a callback to fix the 'callback unexpected regs' verifier bug, but misses that BPF_LD_ABS and BPF_LD_IND trigger the exact same bug via the same prepare_func_exit() path.
--
commit a25ccc5cdb72d9330414949c17ecac5156595510
Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>
bpf: Reject tail calls directly from callback frames
A tail call from a non-zero frame is modeled as a return from that frame,
synthesizing R0 and calling prepare_func_exit() for the taken branch.
When the current frame is a synchronous callback, prepare_func_exit()
enforces the callback return-value contract and marks R0 precise, triggering
the "callback unexpected regs" verifier warning during precision backtracking.
This patch rejects a tail call made directly by a callback before
constructing the inconsistent return state.
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 7d8ddb1bee00c..f540279ff4abb 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -11228,6 +11228,17 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
> if (env->cur_state->curframe) {
> struct bpf_verifier_state *branch;
>
> + /*
> + * A taken tail call is modeled as a return from the current
> + * frame. A callback frame cannot be left that way because
> + * prepare_func_exit() would apply its return contract to the
> + * unknown R0 synthesized below. Stack-depth validation rejects
> + * this construct anyway.
> + */
> + if (cur_func(env)->in_callback_fn) {
> + verbose(env, "cannot tail call within callback\n");
> + return -EINVAL;
> + }
[Severity: High]
This isn't a bug introduced by this patch, but doesn't BPF_LD_ABS inside a
subprog trigger the exact same bug via the same prepare_func_exit() path?
Looking at check_ld_abs() in kernel/bpf/verifier.c:
if (env->cur_state->curframe) {
struct bpf_verifier_state *branch;
mark_reg_scratched(env, BPF_REG_0);
branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
if (IS_ERR(branch))
return PTR_ERR(branch);
mark_reg_known_zero(env, regs, BPF_REG_0);
err = prepare_func_exit(env, &env->insn_idx);
if (err)
return err;
env->insn_idx--;
}
If a CAP_BPF user loads a SCHED_CLS program (where BPF_LD_ABS is allowed),
invokes bpf_loop(), passes PTR_TO_CTX through the stack to the callback_ctx
argument, loads the context into R6 inside the callback, and executes
BPF_LD_ABS, it appears check_ld_abs() will synthesize R0 and call
prepare_func_exit().
Since the callback frame lacks instruction history for R0, won't precision
backtracking fail and hit the exact same "callback unexpected regs" verifier
warning? Does check_ld_abs() need a similar rejection for callbacks?
> mark_reg_scratched(env, BPF_REG_0);
> branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
> if (IS_ERR(branch))
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260903144433.1716731-1-memxor@gmail.com?part=3
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 05/10] bpf: Reject resilient lock operations in rbtree callbacks
2026-09-03 14:44 ` [PATCH bpf v1 05/10] bpf: Reject resilient lock operations in rbtree callbacks Kumar Kartikeya Dwivedi
@ 2026-09-03 15:31 ` sashiko-bot
2026-09-03 15:36 ` Kumar Kartikeya Dwivedi
0 siblings, 1 reply; 24+ messages in thread
From: sashiko-bot @ 2026-09-03 15:31 UTC (permalink / raw)
To: Kumar Kartikeya Dwivedi; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The restriction against calling lock operations inside rbtree callbacks can be bypassed by nesting callbacks or calling subprograms, because in_rbtree_lock_required_cb() only checks the immediate top frame.
--
commit c5914f67e15078bc12af13429620d2a2a4de2b11
Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>
bpf: Reject resilient lock operations in rbtree callbacks
This patch attempts to enforce the root's lock requirement for resilient
locks in rbtree callbacks. It aims to prevent use-after-free conditions
when nodes are removed and freed by other CPUs during the in-progress tree
walk.
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index f540279ff4abb..32d31fa67036b 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -13241,6 +13241,11 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me
> {
> int flags = PROCESS_RES_LOCK;
>
> + if (in_rbtree_lock_required_cb(env)) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Severity: High]
This isn't a bug introduced by this patch, but does
in_rbtree_lock_required_cb() fully protect against this bypass?
Looking at in_rbtree_lock_required_cb(), it only checks the immediate top
frame:
kernel/bpf/verifier.c:in_rbtree_lock_required_cb() {
...
callee = state->frame[state->curframe];
if (!callee->in_callback_fn)
return false;
kfunc_btf_id = insn[callee->callsite].imm;
return is_rbtree_lock_required_kfunc(kfunc_btf_id);
}
If a BPF program calls a custom rbtree comparison callback, and inside that
callback it calls a static subprogram (or a nested callback like bpf_loop()),
would state->curframe's in_callback_fn be false (or its kfunc_btf_id not
match the rbtree add kfunc)?
Could a program use this nested frame to successfully unlock the resilient
lock via a global map value (BPF_PSEUDO_MAP_VALUE), temporarily dropping the
lock and allowing another CPU to concurrently remove and free the nodes being
traversed by bpf_rbtree_add(), leading to a Use-After-Free?
> + verbose(env, "can't res_spin_{lock,unlock} in rbtree cb\n");
> + return -EACCES;
> + }
> +
> if (reg->type != PTR_TO_MAP_VALUE && reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
> verbose(env, "%s doesn't point to map value or allocated object\n",
> reg_arg_name(env, argno));
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260903144433.1716731-1-memxor@gmail.com?part=5
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 05/10] bpf: Reject resilient lock operations in rbtree callbacks
2026-09-03 15:31 ` sashiko-bot
@ 2026-09-03 15:36 ` Kumar Kartikeya Dwivedi
0 siblings, 0 replies; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 15:36 UTC (permalink / raw)
To: sashiko-reviews; +Cc: bpf
On Thu Sep 3, 2026 at 5:31 PM CEST, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] The restriction against calling lock operations inside rbtree callbacks can be bypassed by nesting callbacks or calling subprograms, because in_rbtree_lock_required_cb() only checks the immediate top frame.
> --
>
> commit c5914f67e15078bc12af13429620d2a2a4de2b11
> Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>
> bpf: Reject resilient lock operations in rbtree callbacks
>
> This patch attempts to enforce the root's lock requirement for resilient
> locks in rbtree callbacks. It aims to prevent use-after-free conditions
> when nodes are removed and freed by other CPUs during the in-progress tree
> walk.
>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index f540279ff4abb..32d31fa67036b 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -13241,6 +13241,11 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me
>> {
>> int flags = PROCESS_RES_LOCK;
>>
>> + if (in_rbtree_lock_required_cb(env)) {
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> [Severity: High]
> This isn't a bug introduced by this patch, but does
> in_rbtree_lock_required_cb() fully protect against this bypass?
>
> Looking at in_rbtree_lock_required_cb(), it only checks the immediate top
> frame:
>
> kernel/bpf/verifier.c:in_rbtree_lock_required_cb() {
> ...
> callee = state->frame[state->curframe];
>
> if (!callee->in_callback_fn)
> return false;
>
> kfunc_btf_id = insn[callee->callsite].imm;
> return is_rbtree_lock_required_kfunc(kfunc_btf_id);
> }
>
> If a BPF program calls a custom rbtree comparison callback, and inside that
> callback it calls a static subprogram (or a nested callback like bpf_loop()),
> would state->curframe's in_callback_fn be false (or its kfunc_btf_id not
> match the rbtree add kfunc)?
>
> Could a program use this nested frame to successfully unlock the resilient
> lock via a global map value (BPF_PSEUDO_MAP_VALUE), temporarily dropping the
> lock and allowing another CPU to concurrently remove and free the nodes being
> traversed by bpf_rbtree_add(), leading to a Use-After-Free?
>
Separate bug, will be separate fix. Let's still add this one.
>> + verbose(env, "can't res_spin_{lock,unlock} in rbtree cb\n");
>> + return -EACCES;
>> + }
>> +
>> if (reg->type != PTR_TO_MAP_VALUE && reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
>> verbose(env, "%s doesn't point to map value or allocated object\n",
>> reg_arg_name(env, argno));
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 03/10] bpf: Reject tail calls directly from callback frames
2026-09-03 15:21 ` sashiko-bot
@ 2026-09-03 15:36 ` Kumar Kartikeya Dwivedi
0 siblings, 0 replies; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 15:36 UTC (permalink / raw)
To: sashiko-reviews; +Cc: bpf
On Thu Sep 3, 2026 at 5:21 PM CEST, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] The patch prevents bpf_tail_call within a callback to fix the 'callback unexpected regs' verifier bug, but misses that BPF_LD_ABS and BPF_LD_IND trigger the exact same bug via the same prepare_func_exit() path.
> --
>
> commit a25ccc5cdb72d9330414949c17ecac5156595510
> Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>
> bpf: Reject tail calls directly from callback frames
>
> A tail call from a non-zero frame is modeled as a return from that frame,
> synthesizing R0 and calling prepare_func_exit() for the taken branch.
> When the current frame is a synchronous callback, prepare_func_exit()
> enforces the callback return-value contract and marks R0 precise, triggering
> the "callback unexpected regs" verifier warning during precision backtracking.
> This patch rejects a tail call made directly by a callback before
> constructing the inconsistent return state.
>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index 7d8ddb1bee00c..f540279ff4abb 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -11228,6 +11228,17 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
>> if (env->cur_state->curframe) {
>> struct bpf_verifier_state *branch;
>>
>> + /*
>> + * A taken tail call is modeled as a return from the current
>> + * frame. A callback frame cannot be left that way because
>> + * prepare_func_exit() would apply its return contract to the
>> + * unknown R0 synthesized below. Stack-depth validation rejects
>> + * this construct anyway.
>> + */
>> + if (cur_func(env)->in_callback_fn) {
>> + verbose(env, "cannot tail call within callback\n");
>> + return -EINVAL;
>> + }
>
> [Severity: High]
> This isn't a bug introduced by this patch, but doesn't BPF_LD_ABS inside a
> subprog trigger the exact same bug via the same prepare_func_exit() path?
>
> Looking at check_ld_abs() in kernel/bpf/verifier.c:
>
> if (env->cur_state->curframe) {
> struct bpf_verifier_state *branch;
>
> mark_reg_scratched(env, BPF_REG_0);
> branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
> if (IS_ERR(branch))
> return PTR_ERR(branch);
> mark_reg_known_zero(env, regs, BPF_REG_0);
> err = prepare_func_exit(env, &env->insn_idx);
> if (err)
> return err;
> env->insn_idx--;
> }
>
> If a CAP_BPF user loads a SCHED_CLS program (where BPF_LD_ABS is allowed),
> invokes bpf_loop(), passes PTR_TO_CTX through the stack to the callback_ctx
> argument, loads the context into R6 inside the callback, and executes
> BPF_LD_ABS, it appears check_ld_abs() will synthesize R0 and call
> prepare_func_exit().
>
> Since the callback frame lacks instruction history for R0, won't precision
> backtracking fail and hit the exact same "callback unexpected regs" verifier
> warning? Does check_ld_abs() need a similar rejection for callbacks?
>
Has to be fixed separately.
>> mark_reg_scratched(env, BPF_REG_0);
>> branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
>> if (IS_ERR(branch))
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 09/10] bpf: Mark syscall helpers as sleepable
2026-09-03 14:44 ` [PATCH bpf v1 09/10] bpf: Mark syscall helpers as sleepable Kumar Kartikeya Dwivedi
@ 2026-09-03 15:51 ` sashiko-bot
2026-09-03 15:54 ` Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
1 sibling, 1 reply; 24+ messages in thread
From: sashiko-bot @ 2026-09-03 15:51 UTC (permalink / raw)
To: Kumar Kartikeya Dwivedi; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] bpf_btf_find_by_name_kind_proto lacks .might_sleep = true, allowing arbitrary FD injection via softirq.
--
commit 1d16e876066d61c09bcc6698ca694cdf8336d52c
Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>
bpf: Mark syscall helpers as sleepable
This commit adds the .might_sleep = true constraint to the bpf_sys_bpf and
bpf_sys_close helper prototypes. This ensures the verifier rejects them from
non-sleepable contexts, such as bpf_timer callbacks registered within a
BPF_PROG_TYPE_SYSCALL program.
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 6874ba1424af0..c7bc9ba9b331f 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -6568,6 +6568,7 @@ EXPORT_SYMBOL_NS(kern_sys_bpf, "BPF_INTERNAL");
> static const struct bpf_func_proto bpf_sys_bpf_proto = {
> .func = bpf_sys_bpf,
> .gpl_only = false,
> + .might_sleep = true,
> .ret_type = RET_INTEGER,
> .arg1_type = ARG_ANYTHING,
> .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
> .arg3_type = ARG_MEM_SIZE,
> };
> @@ -6593,6 +6594,7 @@ BPF_CALL_1(bpf_sys_close, u32, fd)
> static const struct bpf_func_proto bpf_sys_close_proto = {
> .func = bpf_sys_close,
> .gpl_only = false,
> + .might_sleep = true,
> .ret_type = RET_INTEGER,
> .arg1_type = ARG_ANYTHING,
> };
[Severity: High]
This isn't a bug introduced by this patch, but does
bpf_btf_find_by_name_kind_proto also need to be marked as sleepable?
Looking at syscall_prog_func_proto() in kernel/bpf/syscall.c,
bpf_btf_find_by_name_kind is also exposed to syscall programs:
case BPF_FUNC_btf_find_by_name_kind:
return &bpf_btf_find_by_name_kind_proto;
Because bpf_btf_find_by_name_kind_proto in kernel/bpf/btf.c lacks the
.might_sleep = true constraint, the verifier will permit its use inside a
non-sleepable bpf_timer callback registered by a syscall program.
When the timer fires in softirq context, bpf_btf_find_by_name_kind() calls
__btf_new_fd(). This attempts to allocate a file descriptor with GFP_KERNEL
and injects the new file descriptor into the current->files struct of
whatever arbitrary process was interrupted by the timer.
Should bpf_btf_find_by_name_kind_proto be updated as well to prevent this
cross-process file descriptor injection and scheduling-while-atomic issue?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260903144433.1716731-1-memxor@gmail.com?part=9
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 07/10] bpf: Mark sched_process_wait argument as nullable
2026-09-03 14:44 ` [PATCH bpf v1 07/10] bpf: Mark sched_process_wait argument as nullable Kumar Kartikeya Dwivedi
@ 2026-09-03 15:52 ` bot+bpf-ci
0 siblings, 0 replies; 24+ messages in thread
From: bot+bpf-ci @ 2026-09-03 15:52 UTC (permalink / raw)
To: memxor, bpf
Cc: npc, ast, andrii, daniel, eddyz87, emil, kkd, kernel-team, ast,
andrii, daniel, martin.lau, eddyz87, yonghong.song, mason,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 900 bytes --]
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index d6d243c262ea5..41764356d2d30 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -6657,6 +6657,10 @@ struct bpf_raw_tp_null_args {
> static const struct bpf_raw_tp_null_args raw_tp_null_args[] = {
> /* sched */
> { "sched_pi_setprio", 0x10 },
> + /*
> + * do_wait() passes NULL for wait4(-1) and waitid(P_ALL).
> + */
> + { "sched_process_wait", 0x1 },
> /* ... from sched_numa_pair_template event class */
This isn't a bug, but would the comment read better as a single-line
/* do_wait() passes NULL for wait4(-1) and waitid(P_ALL). */ to match
the other comments in this table?
---
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/33770534313
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 02/10] selftests/bpf: Cover signal tracepoint siginfo sentinels
2026-09-03 14:44 ` [PATCH bpf v1 02/10] selftests/bpf: Cover signal tracepoint siginfo sentinels Kumar Kartikeya Dwivedi
@ 2026-09-03 15:52 ` bot+bpf-ci
0 siblings, 0 replies; 24+ messages in thread
From: bot+bpf-ci @ 2026-09-03 15:52 UTC (permalink / raw)
To: memxor, bpf
Cc: ast, andrii, daniel, eddyz87, emil, kkd, kernel-team, ast, andrii,
daniel, martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1494 bytes --]
> selftests/bpf: Cover signal tracepoint siginfo sentinels
>
> Add load-only verifier coverage for the signal_generate and
> signal_deliver info arguments. The signal_generate case performs a NULL
> check before dereferencing info, ensuring that merely making it nullable
> cannot satisfy the test when the nonzero SEND_SIG_PRIV sentinel is used.
>
> Both programs load successfully without the verifier fix, contrary to
> their expected-failure annotations. With the fix, info is a scalar and
> the attempted dereferences are rejected.
>
> Also add success cases showing that plain raw tracepoint and tp_btf
> programs can continue to read and compare the context word as a scalar.
>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This isn't a bug, but would it read more clearly to name the two
expected-failure programs explicitly in the "Both programs load
successfully" sentence?
The patch adds four programs total (two __success controls and two
__failure cases), so "Both" has to be inferred as referring to the two
__failure programs. Something like "without the verifier fix the two
__failure programs load, so the tests fail; with the fix info is a
scalar and both dereferences are rejected" would make the antecedent
explicit.
---
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/33770534313
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 09/10] bpf: Mark syscall helpers as sleepable
2026-09-03 14:44 ` [PATCH bpf v1 09/10] bpf: Mark syscall helpers as sleepable Kumar Kartikeya Dwivedi
2026-09-03 15:51 ` sashiko-bot
@ 2026-09-03 15:52 ` bot+bpf-ci
1 sibling, 0 replies; 24+ messages in thread
From: bot+bpf-ci @ 2026-09-03 15:52 UTC (permalink / raw)
To: memxor, bpf
Cc: npc, ast, andrii, daniel, eddyz87, emil, kkd, kernel-team, ast,
andrii, daniel, martin.lau, eddyz87, yonghong.song, mason,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 3914 bytes --]
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 6874ba1424af0..c7bc9ba9b331f 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -6568,6 +6568,7 @@ EXPORT_SYMBOL_NS(kern_sys_bpf, "BPF_INTERNAL");
> static const struct bpf_func_proto bpf_sys_bpf_proto = {
> .func = bpf_sys_bpf,
> .gpl_only = false,
> + .might_sleep = true,
> .ret_type = RET_INTEGER,
> .arg1_type = ARG_ANYTHING,
> .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
Does bpf_btf_find_by_name_kind() need the same treatment?
syscall_prog_func_proto() hands out four helpers to BPF_PROG_TYPE_SYSCALL.
This patch marks two of them. bpf_btf_find_by_name_kind_proto is used by
nothing else in the tree, so marking it has no collateral effect on other
program types.
It can sleep on the module-BTF path:
bpf_btf_find_by_name_kind()
-> bpf_find_btf_id() /* module BTF hit */
-> __btf_new_fd()
-> anon_inode_getfd()
-> alloc_file_pseudo() /* kmem_cache_zalloc(filp_cachep, GFP_KERNEL) */
-> get_unused_fd_flags()
-> alloc_fd()
-> expand_files() /* kvmalloc(GFP_KERNEL_ACCOUNT) */
bpf_get_btf_vmlinux() additionally takes mutex_lock(&btf_vmlinux_lock)
(that branch is unreachable at run time because bpf_check() already
populated btf_vmlinux, so the fd-allocation path is the load-bearing one).
Reachability is identical to the case the changelog describes for
bpf_sys_bpf(): a SEC("syscall") program can call bpf_timer_set_callback(),
and the verifier checks that callback in a non-sleepable context while
retaining the syscall helper set. Without .might_sleep on the prototype,
the callback can invoke bpf_btf_find_by_name_kind() from hrtimer softirq
context and trigger the same scheduling-while-atomic failure.
The same issue applies to bpf_rcu_read_lock(), bpf_preempt_disable(),
bpf_spin_lock(), and irq-disabled regions, which in_sleepable_context()
also excludes.
The fourth helper, bpf_kallsyms_lookup_name(), is genuinely non-sleeping
(kallsyms_lookup_name() operates under RCU), so leaving that one unmarked
is correct.
> @@ -6593,6 +6594,7 @@ BPF_CALL_1(bpf_sys_close, u32, fd)
> static const struct bpf_func_proto bpf_sys_close_proto = {
> .func = bpf_sys_close,
> .gpl_only = false,
> + .might_sleep = true,
> .ret_type = RET_INTEGER,
> .arg1_type = ARG_ANYTHING,
> };
A subsystem pattern flags this as potentially concerning: freplace
(BPF_PROG_TYPE_EXT) programs that replace a global subprog of a syscall
program can no longer call bpf_sys_bpf() or bpf_sys_close(), where they
could before.
An EXT program is never sleepable: can_be_sleepable() does not list
BPF_PROG_TYPE_EXT, and check_attach_btf_id() rejects 'prog->sleepable &&
!can_be_sleepable(prog)' with 'Program of this type cannot be sleepable'.
Consequently do_check_common() sets state->in_sleepable = false for every
EXT program.
At the same time check_attach_btf_id() sets env->ops =
bpf_verifier_ops[tgt_prog->type] for EXT and resolve_prog_type() returns
the saved SYSCALL type, so such an EXT program does get
syscall_prog_func_proto() and previously loaded fine with a bpf_sys_bpf()
call in it.
After this patch that same program is rejected with 'sleepable helper
bpf_sys_bpf#166 in non-sleepable prog', even though the replaced subprog
only ever runs from the sleepable BPF_PROG_TEST_RUN body.
Mitigating context: this limitation already exists for every other
might_sleep helper (e.g. bpf_copy_from_user), no in-tree selftest does
freplace on a SEC("syscall") program, and rejecting is the conservative
direction. Worth a sentence in the changelog since it is a user-visible
loadability change?
---
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/33770534313
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 01/10] bpf: Mark signal tracepoint siginfo arguments as scalar
2026-09-03 14:44 ` [PATCH bpf v1 01/10] bpf: Mark signal tracepoint siginfo arguments as scalar Kumar Kartikeya Dwivedi
@ 2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 16:47 ` Alexei Starovoitov
0 siblings, 1 reply; 24+ messages in thread
From: bot+bpf-ci @ 2026-09-03 15:52 UTC (permalink / raw)
To: memxor, bpf
Cc: npc, ast, andrii, daniel, eddyz87, emil, kkd, kernel-team, ast,
andrii, daniel, martin.lau, eddyz87, yonghong.song, mason,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 4390 bytes --]
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index da36d4b9d31ab..d6d243c262ea5 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -6717,6 +6717,9 @@ static const struct bpf_raw_tp_null_args raw_tp_null_args[] = {
> { "rxrpc_resend", 0x10 },
> { "rxrpc_tq", 0x10 },
> { "rxrpc_client", 0x1 },
> + /* signal */
> + { "signal_generate", 0x20 },
> + { "signal_deliver", 0x20 },
^^^^
Is signal_deliver's 0x20 mask too strict for its actual call sites?
Looking at the two call sites for trace_signal_deliver():
kernel/signal.c (do_coredump):
trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO,
&sighand->action[SIGKILL-1]);
kernel/signal.c (get_signal):
trace_signal_deliver(signr, &ksig->info, ka);
SEND_SIG_PRIV is never passed to this tracepoint. SEND_SIG_NOINFO is
zero (NULL), and &ksig->info is always a real pointer filled by
dequeue_synchronous_signal() or dequeue_signal() just above the call.
SEND_SIG_PRIV == 1 only reaches trace_signal_generate() from
kernel/signal.c:__send_signal_locked().
If that's the case, would 0x10 (PTR_MAYBE_NULL) be both sufficient and
less restrictive for signal_deliver? With 0x10 the verifier would still
force a NULL check to catch SEND_SIG_NOINFO, but after the check a
tp_btf program could read info->si_code and other fields. With 0x20 the
register becomes SCALAR_VALUE immediately and check_mem_access() rejects
all dereferencing with "R1 invalid mem access 'scalar'".
This table supports per-argument distinctions. The existing entry:
{ "cachefiles_lookup", 0x1 | 0x200 }
marks arg 0 nullable and arg 2 ERR_PTR rather than applying the same
mask to both. The signal_generate justification holds (SEND_SIG_PRIV is
nonzero so PTR_MAYBE_NULL alone doesn't work), but does the same
reasoning apply to signal_deliver given that it never sees that
sentinel?
> commit a481db8aa51a8682ee36d019234a31b254b3ecd5
> Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> Date: Thu Sep 3 16:44:19 2026 +0200
>
> bpf: Mark signal tracepoint siginfo arguments as scalar
>
> The signal_generate and signal_deliver tracepoints declare their info
> argument as a struct kernel_siginfo pointer. btf_ctx_access() therefore
> treats it as a trusted pointer for tp_btf programs.
>
> Signal delivery also uses SEND_SIG_NOINFO and SEND_SIG_PRIV as special
> values for this argument. Those values are zero and one respectively,
> and are not pointers. A tp_btf program can currently dereference either
> value and fault the kernel. In particular, signal_generate can run from
> timer interrupt context, turning the fault into a kernel panic.
>
> Record both tracepoints in raw_tp_null_args[] and mark argument one as
> a non-pointer. This preserves scalar access to the cookie while rejecting
> direct and helper-mediated pointer use. Merely marking it nullable would
> not suffice because SEND_SIG_PRIV is nonzero.
^^^^^^
Could this paragraph's wording be more precise about which parts are
being preserved and which argument is being marked?
"This preserves scalar access to the cookie" - there doesn't appear to
be a cookie anywhere in this change. Neither signal_generate nor
signal_deliver has a cookie argument, and this isn't related to
bpf_get_attach_cookie(). What's actually preserved is scalar access to
the siginfo sentinel value itself (0 for SEND_SIG_NOINFO, 1 for
SEND_SIG_PRIV), which is what a program can still read back. The term
"cookie" has a specific meaning in BPF context, so this might mislead
a reader trying to understand what the patch keeps working.
"mark argument one as a non-pointer" - 838a10bd2ebf documents the mask
as "1st arg: 0x1 / 2nd arg: 0x10 / 3rd arg: 0x100", where the nibble
position is the zero-indexed argument number. The mask 0x20 is nibble 1,
meaning the second argument (info). Against the referenced commit's own
wording, "argument one" could point at sig rather than info. Would
"argument 1 (info)" or "the second argument" remove the off-by-one
ambiguity?
---
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/33770534313
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 06/10] selftests/bpf: Reject resilient unlock in rbtree callback
2026-09-03 14:44 ` [PATCH bpf v1 06/10] selftests/bpf: Reject resilient unlock in rbtree callback Kumar Kartikeya Dwivedi
@ 2026-09-03 15:52 ` bot+bpf-ci
0 siblings, 0 replies; 24+ messages in thread
From: bot+bpf-ci @ 2026-09-03 15:52 UTC (permalink / raw)
To: memxor, bpf
Cc: ast, andrii, daniel, eddyz87, emil, kkd, kernel-team, ast, andrii,
daniel, martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 3414 bytes --]
> Add a load-only verifier regression for a resilient lock operation in an
> rbtree comparison callback. The program holds the rbtree's regular spin
> lock and a separate resilient lock, then releases the resilient lock from
> the callback. This isolates the missing kfunc policy check without running
> a concurrent tree mutation.
>
> Release the resilient lock before the regular lock on the outer
> fall-through. The broken verifier therefore accepts the balanced program,
> while the fixed verifier rejects the resilient unlock specifically while
> verifying the callback.
>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
The commit message states "The broken verifier therefore accepts the
balanced program." Does the pre-fix verifier actually accept this program?
Tracing through the verifier's behavior before the parent commit's fix: the
added program structure is
bpf_spin_lock(&glock);
if (bpf_res_spin_lock(&res_glock)) { ... }
bpf_rbtree_add(&groot, &n->node, less__bad_res_spin_unlock);
bpf_res_spin_unlock(&res_glock);
bpf_spin_unlock(&glock);
with the callback doing only bpf_res_spin_unlock(&res_glock).
Without the parent commit's check, the callback's unlock succeeds and the
release is recorded in the verifier state, not in the callee frame. Locks
live in struct bpf_verifier_state (state->refs, state->active_locks,
acquire_lock_state() and release_lock_state() in verifier.c, and
process_spin_lock()).
Nothing catches the imbalance at the callback boundary either:
process_bpf_exit_full() passes check_lock = exception_exit ||
!env->cur_state->curframe, which is false for a callback frame.
check_reference_leak() returns 0 immediately when cur_func(env)->frameno is
non-zero.
prepare_func_exit() then does, for in_callback_fn:
if (in_callback_fn)
*insn_idx = callee->callsite;
so the frame is popped and verification resumes at the bpf_rbtree_add
callsite carrying the callback's state, in which res_glock is no longer
held. is_state_visited() cannot prune that state against the pre-call state
at the callsite, because refsafe() bails on old->active_locks !=
cur->active_locks (2 vs 1).
Verification therefore falls through past the callsite and reaches the outer
bpf_res_spin_unlock(&res_glock), where process_spin_lock()'s
find_lock_state(cur, REF_TYPE_RES_LOCK, reg->id, ptr) finds nothing and
emits "bpf_res_spin_unlock of different lock" with -EINVAL.
The result is: pre-fix the load fails with "bpf_res_spin_unlock of different
lock," while post-fix it fails with "can't res_spin_{lock,unlock} in rbtree
cb."
The __failure __msg("can't res_spin_{lock,unlock} in rbtree cb") assertion
does still discriminate a fixed kernel from a broken one, so the test itself
is functional. However, should the changelog say the pre-fix verifier accepts
this program when it actually rejects it with a different message?
A case that the pre-fix verifier would actually accept is one where the
callback leaves the lock state balanced at exit (for example, unlock then
re-lock the same resilient lock inside the callback), which is also closer
to the use-after-free window the parent commit describes.
---
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/33770534313
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 09/10] bpf: Mark syscall helpers as sleepable
2026-09-03 15:51 ` sashiko-bot
@ 2026-09-03 15:54 ` Kumar Kartikeya Dwivedi
0 siblings, 0 replies; 24+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-09-03 15:54 UTC (permalink / raw)
To: sashiko-reviews; +Cc: bpf
On Thu Sep 3, 2026 at 5:51 PM CEST, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] bpf_btf_find_by_name_kind_proto lacks .might_sleep = true, allowing arbitrary FD injection via softirq.
> --
>
> commit 1d16e876066d61c09bcc6698ca694cdf8336d52c
> Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>
> bpf: Mark syscall helpers as sleepable
>
> This commit adds the .might_sleep = true constraint to the bpf_sys_bpf and
> bpf_sys_close helper prototypes. This ensures the verifier rejects them from
> non-sleepable contexts, such as bpf_timer callbacks registered within a
> BPF_PROG_TYPE_SYSCALL program.
>
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index 6874ba1424af0..c7bc9ba9b331f 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
>> @@ -6568,6 +6568,7 @@ EXPORT_SYMBOL_NS(kern_sys_bpf, "BPF_INTERNAL");
>> static const struct bpf_func_proto bpf_sys_bpf_proto = {
>> .func = bpf_sys_bpf,
>> .gpl_only = false,
>> + .might_sleep = true,
>> .ret_type = RET_INTEGER,
>> .arg1_type = ARG_ANYTHING,
>> .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
>> .arg3_type = ARG_MEM_SIZE,
>> };
>> @@ -6593,6 +6594,7 @@ BPF_CALL_1(bpf_sys_close, u32, fd)
>> static const struct bpf_func_proto bpf_sys_close_proto = {
>> .func = bpf_sys_close,
>> .gpl_only = false,
>> + .might_sleep = true,
>> .ret_type = RET_INTEGER,
>> .arg1_type = ARG_ANYTHING,
>> };
>
> [Severity: High]
> This isn't a bug introduced by this patch, but does
> bpf_btf_find_by_name_kind_proto also need to be marked as sleepable?
>
> Looking at syscall_prog_func_proto() in kernel/bpf/syscall.c,
> bpf_btf_find_by_name_kind is also exposed to syscall programs:
>
> case BPF_FUNC_btf_find_by_name_kind:
> return &bpf_btf_find_by_name_kind_proto;
>
> Because bpf_btf_find_by_name_kind_proto in kernel/bpf/btf.c lacks the
> .might_sleep = true constraint, the verifier will permit its use inside a
> non-sleepable bpf_timer callback registered by a syscall program.
>
> When the timer fires in softirq context, bpf_btf_find_by_name_kind() calls
> __btf_new_fd(). This attempts to allocate a file descriptor with GFP_KERNEL
> and injects the new file descriptor into the current->files struct of
> whatever arbitrary process was interrupted by the timer.
>
> Should bpf_btf_find_by_name_kind_proto be updated as well to prevent this
> cross-process file descriptor injection and scheduling-while-atomic issue?
Yes, this also looks broken. Will fix after this set lands.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 01/10] bpf: Mark signal tracepoint siginfo arguments as scalar
2026-09-03 15:52 ` bot+bpf-ci
@ 2026-09-03 16:47 ` Alexei Starovoitov
0 siblings, 0 replies; 24+ messages in thread
From: Alexei Starovoitov @ 2026-09-03 16:47 UTC (permalink / raw)
To: bot+bpf-ci, memxor, bpf
Cc: npc, ast, andrii, daniel, eddyz87, emil, kkd, kernel-team,
martin.lau, yonghong.song, mason, ihor.solodrai
On Thu Sep 3, 2026 at 8:52 AM PDT, bot+bpf-ci wrote:
>> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
>> index da36d4b9d31ab..d6d243c262ea5 100644
>> --- a/kernel/bpf/btf.c
>> +++ b/kernel/bpf/btf.c
>> @@ -6717,6 +6717,9 @@ static const struct bpf_raw_tp_null_args raw_tp_null_args[] = {
>> { "rxrpc_resend", 0x10 },
>> { "rxrpc_tq", 0x10 },
>> { "rxrpc_client", 0x1 },
>> + /* signal */
>> + { "signal_generate", 0x20 },
>> + { "signal_deliver", 0x20 },
> ^^^^
>
> Is signal_deliver's 0x20 mask too strict for its actual call sites?
>
> Looking at the two call sites for trace_signal_deliver():
>
> kernel/signal.c (do_coredump):
> trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO,
> &sighand->action[SIGKILL-1]);
>
> kernel/signal.c (get_signal):
> trace_signal_deliver(signr, &ksig->info, ka);
>
> SEND_SIG_PRIV is never passed to this tracepoint. SEND_SIG_NOINFO is
> zero (NULL), and &ksig->info is always a real pointer filled by
> dequeue_synchronous_signal() or dequeue_signal() just above the call.
>
> SEND_SIG_PRIV == 1 only reaches trace_signal_generate() from
> kernel/signal.c:__send_signal_locked().
>
> If that's the case, would 0x10 (PTR_MAYBE_NULL) be both sufficient and
> less restrictive for signal_deliver? With 0x10 the verifier would still
> force a NULL check to catch SEND_SIG_NOINFO, but after the check a
> tp_btf program could read info->si_code and other fields. With 0x20 the
> register becomes SCALAR_VALUE immediately and check_mem_access() rejects
> all dereferencing with "R1 invalid mem access 'scalar'".
Though AI is correct today the callers of trace_signal_deliver() may change
in the future without cc-ing bpf mailing list and raw_tp_null_args[]
won't be correct anymore. It's better to be strict by default.
Hence, I applied the series as-is.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf v1 00/10] Misc bug fixes - part 1
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
` (9 preceding siblings ...)
2026-09-03 14:44 ` [PATCH bpf v1 10/10] selftests/bpf: Check syscall helpers in timer callbacks Kumar Kartikeya Dwivedi
@ 2026-09-03 16:50 ` patchwork-bot+netdevbpf
10 siblings, 0 replies; 24+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-03 16:50 UTC (permalink / raw)
To: Kumar Kartikeya Dwivedi
Cc: bpf, ast, andrii, daniel, eddyz87, emil, kkd, kernel-team
Hello:
This series was applied to bpf/bpf.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Thu, 3 Sep 2026 16:44:18 +0200 you wrote:
> A set of miscellaneous fixes for bugs reported by Nicholas. These are
> easy ones and should not require any major discussion, hence batched
> together. See commit logs and selftests for details.
>
> Kumar Kartikeya Dwivedi (10):
> bpf: Mark signal tracepoint siginfo arguments as scalar
> selftests/bpf: Cover signal tracepoint siginfo sentinels
> bpf: Reject tail calls directly from callback frames
> selftests/bpf: Test direct tail calls from callbacks
> bpf: Reject resilient lock operations in rbtree callbacks
> selftests/bpf: Reject resilient unlock in rbtree callback
> bpf: Mark sched_process_wait argument as nullable
> selftests/bpf: Test sched_process_wait nullable argument
> bpf: Mark syscall helpers as sleepable
> selftests/bpf: Check syscall helpers in timer callbacks
>
> [...]
Here is the summary with links:
- [bpf,v1,01/10] bpf: Mark signal tracepoint siginfo arguments as scalar
https://git.kernel.org/bpf/bpf/c/77515ab12e49
- [bpf,v1,02/10] selftests/bpf: Cover signal tracepoint siginfo sentinels
https://git.kernel.org/bpf/bpf/c/d7719a1736e6
- [bpf,v1,03/10] bpf: Reject tail calls directly from callback frames
https://git.kernel.org/bpf/bpf/c/266aa4ad0b2e
- [bpf,v1,04/10] selftests/bpf: Test direct tail calls from callbacks
https://git.kernel.org/bpf/bpf/c/d9ae3e4c7fb5
- [bpf,v1,05/10] bpf: Reject resilient lock operations in rbtree callbacks
https://git.kernel.org/bpf/bpf/c/7b7b8b596010
- [bpf,v1,06/10] selftests/bpf: Reject resilient unlock in rbtree callback
https://git.kernel.org/bpf/bpf/c/08b4dc83d981
- [bpf,v1,07/10] bpf: Mark sched_process_wait argument as nullable
https://git.kernel.org/bpf/bpf/c/a453d6e3b8e8
- [bpf,v1,08/10] selftests/bpf: Test sched_process_wait nullable argument
https://git.kernel.org/bpf/bpf/c/c1992ba73b03
- [bpf,v1,09/10] bpf: Mark syscall helpers as sleepable
https://git.kernel.org/bpf/bpf/c/d05524794240
- [bpf,v1,10/10] selftests/bpf: Check syscall helpers in timer callbacks
https://git.kernel.org/bpf/bpf/c/26a3a510cd34
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2026-09-03 16:51 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 14:44 [PATCH bpf v1 00/10] Misc bug fixes - part 1 Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 01/10] bpf: Mark signal tracepoint siginfo arguments as scalar Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 16:47 ` Alexei Starovoitov
2026-09-03 14:44 ` [PATCH bpf v1 02/10] selftests/bpf: Cover signal tracepoint siginfo sentinels Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 14:44 ` [PATCH bpf v1 03/10] bpf: Reject tail calls directly from callback frames Kumar Kartikeya Dwivedi
2026-09-03 15:21 ` sashiko-bot
2026-09-03 15:36 ` Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 04/10] selftests/bpf: Test direct tail calls from callbacks Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 05/10] bpf: Reject resilient lock operations in rbtree callbacks Kumar Kartikeya Dwivedi
2026-09-03 15:31 ` sashiko-bot
2026-09-03 15:36 ` Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 06/10] selftests/bpf: Reject resilient unlock in rbtree callback Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 14:44 ` [PATCH bpf v1 07/10] bpf: Mark sched_process_wait argument as nullable Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 14:44 ` [PATCH bpf v1 08/10] selftests/bpf: Test sched_process_wait nullable argument Kumar Kartikeya Dwivedi
2026-09-03 14:44 ` [PATCH bpf v1 09/10] bpf: Mark syscall helpers as sleepable Kumar Kartikeya Dwivedi
2026-09-03 15:51 ` sashiko-bot
2026-09-03 15:54 ` Kumar Kartikeya Dwivedi
2026-09-03 15:52 ` bot+bpf-ci
2026-09-03 14:44 ` [PATCH bpf v1 10/10] selftests/bpf: Check syscall helpers in timer callbacks Kumar Kartikeya Dwivedi
2026-09-03 16:50 ` [PATCH bpf v1 00/10] Misc bug fixes - part 1 patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox