All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next v1 0/2] Open up res_spin_lock for tracing programs, fix is_tracing_prog_type()
@ 2026-07-19 11:35 Kumar Kartikeya Dwivedi
  2026-07-19 11:35 ` [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts Kumar Kartikeya Dwivedi
  2026-07-19 11:35 ` [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret Kumar Kartikeya Dwivedi
  0 siblings, 2 replies; 9+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-07-19 11:35 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team

Patches in the set first open up res_spin_lock in all program types. The
second patch goes back to addressing the technical debt highlighted in [0].
While for programs affected by the second patch don't need res_spin_lock
to be opened up (since it was already allowed in those program types due
to the oversight in is_tracing_prog_type()), it is timely to do so now.

  [0]: https://lore.kernel.org/bpf/DJ3W8IZ08WBT.VTRTP72FSWVO@gmail.com

See commits for details.

Kumar Kartikeya Dwivedi (2):
  bpf: Allow bpf_res_spin_lock() in all contexts
  bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret

 kernel/bpf/verifier.c                         | 48 +++++++++++--------
 .../selftests/bpf/prog_tests/linked_list.c    |  6 +--
 .../selftests/bpf/prog_tests/map_btf.c        | 19 ++++----
 .../selftests/bpf/progs/map_in_map_btf.c      |  2 +-
 .../selftests/bpf/progs/normal_map_btf.c      |  2 +-
 .../selftests/bpf/progs/refcounted_kptr.c     | 10 ++--
 .../bpf/progs/refcounted_kptr_fail.c          |  5 +-
 .../bpf/progs/verifier_helper_restricted.c    |  4 ++
 8 files changed, 51 insertions(+), 45 deletions(-)


base-commit: ecf11bc5f56abb3a2219a8c75e8a5b54467d1781
-- 
2.53.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts
  2026-07-19 11:35 [PATCH bpf-next v1 0/2] Open up res_spin_lock for tracing programs, fix is_tracing_prog_type() Kumar Kartikeya Dwivedi
@ 2026-07-19 11:35 ` Kumar Kartikeya Dwivedi
  2026-07-19 11:56   ` sashiko-bot
  2026-07-20 22:00   ` Emil Tsalapatis
  2026-07-19 11:35 ` [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret Kumar Kartikeya Dwivedi
  1 sibling, 2 replies; 9+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-07-19 11:35 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team

There is no particular reason to keep bpf_res_spin_lock() disabled in
tracing programs, since it is safe against reentrancy and deadlocks.
Remove the restriction for tracing programs covered by the predicate
is_tracing_prog_type().

This is a prerequisite before the definition of is_tracing_prog_type()
is updated to include raw_tp, fentry, fexit, and fmod_ret. Existing
tracing programs will be updated to use bpf_res_spin_lock() instead when
it is available.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
 kernel/bpf/verifier.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 4446f0bde88b..bb6e16668d0d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -17815,7 +17815,9 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
 			verbose(env, "socket filter progs cannot use bpf_spin_lock yet\n");
 			return -EINVAL;
 		}
+	}
 
+	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
 		if (is_tracing_prog_type(prog_type)) {
 			verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
 			return -EINVAL;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret
  2026-07-19 11:35 [PATCH bpf-next v1 0/2] Open up res_spin_lock for tracing programs, fix is_tracing_prog_type() Kumar Kartikeya Dwivedi
  2026-07-19 11:35 ` [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts Kumar Kartikeya Dwivedi
@ 2026-07-19 11:35 ` Kumar Kartikeya Dwivedi
  2026-07-19 14:09   ` sashiko-bot
  2026-07-20 22:40   ` Emil Tsalapatis
  1 sibling, 2 replies; 9+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-07-19 11:35 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team

The is_tracing_prog_type() predicate currently skips fentry, fexit,
fmod_ret, and also raw_tp attach type in BPF_PROG_TYPE_TRACING, due to
oversight.

Fix this by tightening the check, and moving predicates checking for the
restriction closer to the point of use. This change might affect
existing programs using them in unsafe contexts, but in such cases, it
is recommended for users to switch over to bpf_res_spin_lock instead.

Make appropriate changes to selftests to adjust to the change in error
messages and added restrictions.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
 kernel/bpf/verifier.c                         | 48 ++++++++++---------
 .../selftests/bpf/prog_tests/linked_list.c    |  6 +--
 .../selftests/bpf/prog_tests/map_btf.c        | 19 ++++----
 .../selftests/bpf/progs/map_in_map_btf.c      |  2 +-
 .../selftests/bpf/progs/normal_map_btf.c      |  2 +-
 .../selftests/bpf/progs/refcounted_kptr.c     | 10 ++--
 .../bpf/progs/refcounted_kptr_fail.c          |  5 +-
 .../bpf/progs/verifier_helper_restricted.c    |  4 ++
 8 files changed, 50 insertions(+), 46 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index bb6e16668d0d..3fe2410c7ce3 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -207,7 +207,7 @@ static int release_reference_nomark(struct bpf_verifier_state *state, int id);
 static int release_reference(struct bpf_verifier_env *env, int id);
 static void invalidate_non_owning_refs(struct bpf_verifier_env *env);
 static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env);
-static bool is_tracing_prog_type(enum bpf_prog_type type);
+static bool is_tracing_prog_type(struct bpf_prog *prog);
 static int ref_set_non_owning(struct bpf_verifier_env *env,
 			      struct bpf_reg_state *reg);
 static bool is_trusted_reg(struct bpf_verifier_env *env, const struct bpf_reg_state *reg);
@@ -7089,6 +7089,12 @@ static int process_spin_lock(struct bpf_verifier_env *env, struct bpf_reg_state
 			val, lock_str, spin_lock_off);
 		return -EINVAL;
 	}
+
+	if (is_tracing_prog_type(env->prog) && !is_res_lock) {
+		verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
+		return -EINVAL;
+	}
+
 	if (is_lock) {
 		void *ptr;
 		int type;
@@ -12317,6 +12323,10 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me
 				verbose(env, "allocated object must be referenced\n");
 				return -EINVAL;
 			}
+			if (is_tracing_prog_type(env->prog)) {
+				verbose(env, "tracing progs cannot use bpf_{list_head,rb_root} yet\n");
+				return -EINVAL;
+			}
 			ret = process_kf_arg_ptr_to_list_head(env, reg, argno, meta);
 			if (ret < 0)
 				return ret;
@@ -12333,6 +12343,10 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me
 				verbose(env, "allocated object must be referenced\n");
 				return -EINVAL;
 			}
+			if (is_tracing_prog_type(env->prog)) {
+				verbose(env, "tracing progs cannot use bpf_{list_head,rb_root} yet\n");
+				return -EINVAL;
+			}
 			ret = process_kf_arg_ptr_to_rbtree_root(env, reg, argno, meta);
 			if (ret < 0)
 				return ret;
@@ -12966,7 +12980,6 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
 			    int *insn_idx_p)
 {
 	bool sleepable, rcu_lock, rcu_unlock, preempt_disable, preempt_enable;
-	enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
 	struct bpf_reg_state *regs = cur_regs(env);
 	const char *func_name, *ptr_type_name;
 	const struct btf_type *t, *ptr_type;
@@ -13044,10 +13057,8 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
 		return err;
 
 	if ((is_bpf_obj_drop_kfunc(meta.func_id) ||
-	     is_bpf_percpu_obj_drop_kfunc(meta.func_id)) && (is_tracing_prog_type(prog_type) ||
-	     /* is_tracing_prog_type() for now doesn't cover non-iterator tracing progs. */
-	     (prog_type == BPF_PROG_TYPE_TRACING && env->prog->expected_attach_type != BPF_TRACE_ITER
-	      && !env->prog->sleepable))) {
+	     is_bpf_percpu_obj_drop_kfunc(meta.func_id)) && (is_tracing_prog_type(env->prog)
+	     && !env->prog->sleepable)) {
 		struct btf_struct_meta *struct_meta;
 
 		struct_meta = btf_find_struct_meta(meta.arg_btf, meta.arg_btf_id);
@@ -17769,9 +17780,11 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
 	return __add_used_btf(env, btf);
 }
 
-static bool is_tracing_prog_type(enum bpf_prog_type type)
+static bool is_tracing_prog_type(struct bpf_prog *prog)
 {
-	switch (type) {
+	switch (resolve_prog_type(prog)) {
+	case BPF_PROG_TYPE_TRACING:
+		return prog->expected_attach_type != BPF_TRACE_ITER;
 	case BPF_PROG_TYPE_KPROBE:
 	case BPF_PROG_TYPE_TRACEPOINT:
 	case BPF_PROG_TYPE_PERF_EVENT:
@@ -17802,14 +17815,6 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
 		return -EACCES;
 	}
 
-	if (btf_record_has_field(map->record, BPF_LIST_HEAD) ||
-	    btf_record_has_field(map->record, BPF_RB_ROOT)) {
-		if (is_tracing_prog_type(prog_type)) {
-			verbose(env, "tracing progs cannot use bpf_{list_head,rb_root} yet\n");
-			return -EINVAL;
-		}
-	}
-
 	if (btf_record_has_field(map->record, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK)) {
 		if (prog_type == BPF_PROG_TYPE_SOCKET_FILTER) {
 			verbose(env, "socket filter progs cannot use bpf_spin_lock yet\n");
@@ -17817,12 +17822,11 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
 		}
 	}
 
-	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
-		if (is_tracing_prog_type(prog_type)) {
-			verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
-			return -EINVAL;
-		}
-	}
+	/*
+	 * Restrictions on using BPF list,rbtree,spin_lock is checked later upon
+	 * use, since rejecting accesing map containing them in programs is too
+	 * conservative.
+	 */
 
 	if ((bpf_prog_is_offloaded(prog->aux) || bpf_map_is_offloaded(map)) &&
 	    !bpf_offload_prog_map_match(prog, map)) {
diff --git a/tools/testing/selftests/bpf/prog_tests/linked_list.c b/tools/testing/selftests/bpf/prog_tests/linked_list.c
index c3d133c6a00d..702268422673 100644
--- a/tools/testing/selftests/bpf/prog_tests/linked_list.c
+++ b/tools/testing/selftests/bpf/prog_tests/linked_list.c
@@ -59,12 +59,12 @@ static struct {
 	TEST(inner_map, pop_front)
 	TEST(inner_map, pop_back)
 #undef TEST
-	{ "map_compat_kprobe", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
-	{ "map_compat_kretprobe", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
+	{ "map_compat_kprobe", "calling kernel function bpf_list_push_front is not allowed" },
+	{ "map_compat_kretprobe", "calling kernel function bpf_list_push_front is not allowed" },
 	{ "map_compat_tp", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
 	{ "map_compat_perf", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
 	{ "map_compat_raw_tp", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
-	{ "map_compat_raw_tp_w", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
+	{ "map_compat_raw_tp_w", "calling kernel function bpf_list_push_front is not allowed" },
 	{ "obj_type_id_oor", "local type ID argument must be in range [0, U32_MAX]" },
 	{ "obj_new_no_composite", "bpf_obj_new/bpf_percpu_obj_new type ID argument must be of a struct" },
 	{ "obj_new_no_struct", "bpf_obj_new/bpf_percpu_obj_new type ID argument must be of a struct" },
diff --git a/tools/testing/selftests/bpf/prog_tests/map_btf.c b/tools/testing/selftests/bpf/prog_tests/map_btf.c
index 2c4ef6037573..1313f680fcda 100644
--- a/tools/testing/selftests/bpf/prog_tests/map_btf.c
+++ b/tools/testing/selftests/bpf/prog_tests/map_btf.c
@@ -7,6 +7,7 @@
 
 static void do_test_normal_map_btf(void)
 {
+	LIBBPF_OPTS(bpf_test_run_opts, opts);
 	struct normal_map_btf *skel;
 	int i, err, new_fd = -1;
 	int map_fd_arr[64];
@@ -15,12 +16,10 @@ static void do_test_normal_map_btf(void)
 	if (!ASSERT_OK_PTR(skel, "open_load"))
 		return;
 
-	err = normal_map_btf__attach(skel);
-	if (!ASSERT_OK(err, "attach"))
-		goto out;
-
 	skel->bss->pid = getpid();
-	usleep(1);
+	err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.add_to_list_in_array), &opts);
+	if (!ASSERT_OK(err, "test_run"))
+		goto out;
 	ASSERT_TRUE(skel->bss->done, "done");
 
 	/* Use percpu_array to slow bpf_map_free_deferred() down.
@@ -55,6 +54,7 @@ static void do_test_normal_map_btf(void)
 
 static void do_test_map_in_map_btf(void)
 {
+	LIBBPF_OPTS(bpf_test_run_opts, opts);
 	int err, zero = 0, new_fd = -1;
 	struct map_in_map_btf *skel;
 
@@ -62,12 +62,11 @@ static void do_test_map_in_map_btf(void)
 	if (!ASSERT_OK_PTR(skel, "open_load"))
 		return;
 
-	err = map_in_map_btf__attach(skel);
-	if (!ASSERT_OK(err, "attach"))
-		goto out;
-
 	skel->bss->pid = getpid();
-	usleep(1);
+	err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.add_to_list_in_inner_array),
+				     &opts);
+	if (!ASSERT_OK(err, "test_run"))
+		goto out;
 	ASSERT_TRUE(skel->bss->done, "done");
 
 	/* Close inner_array fd later */
diff --git a/tools/testing/selftests/bpf/progs/map_in_map_btf.c b/tools/testing/selftests/bpf/progs/map_in_map_btf.c
index 7a1336d7b16a..eb4d009b8a62 100644
--- a/tools/testing/selftests/bpf/progs/map_in_map_btf.c
+++ b/tools/testing/selftests/bpf/progs/map_in_map_btf.c
@@ -41,7 +41,7 @@ char _license[] SEC("license") = "GPL";
 int pid = 0;
 bool done = false;
 
-SEC("fentry/" SYS_PREFIX "sys_nanosleep")
+SEC("syscall")
 int add_to_list_in_inner_array(void *ctx)
 {
 	struct map_value *value;
diff --git a/tools/testing/selftests/bpf/progs/normal_map_btf.c b/tools/testing/selftests/bpf/progs/normal_map_btf.c
index a45c9299552c..90ac1ec365b9 100644
--- a/tools/testing/selftests/bpf/progs/normal_map_btf.c
+++ b/tools/testing/selftests/bpf/progs/normal_map_btf.c
@@ -29,7 +29,7 @@ char _license[] SEC("license") = "GPL";
 int pid = 0;
 bool done = false;
 
-SEC("fentry/" SYS_PREFIX "sys_nanosleep")
+SEC("syscall")
 int add_to_list_in_array(void *ctx)
 {
 	struct map_value *value;
diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr.c b/tools/testing/selftests/bpf/progs/refcounted_kptr.c
index 61906f48025c..9a783693ce08 100644
--- a/tools/testing/selftests/bpf/progs/refcounted_kptr.c
+++ b/tools/testing/selftests/bpf/progs/refcounted_kptr.c
@@ -921,11 +921,10 @@ long rbtree_wrong_owner_remove_fail_a2(void *ctx)
 	return 0;
 }
 
-SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
+SEC("?lsm.s/bpf")
 __success
 int BPF_PROG(rbtree_sleepable_rcu,
-	     struct file *file, struct kobject *kobj,
-	     struct bin_attribute *bin_attr, char *buf, loff_t off, size_t len)
+	     int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
 {
 	struct bpf_rb_node *rb;
 	struct node_data *n, *m = NULL;
@@ -955,11 +954,10 @@ int BPF_PROG(rbtree_sleepable_rcu,
 	return 0;
 }
 
-SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
+SEC("?lsm.s/bpf")
 __success
 int BPF_PROG(rbtree_sleepable_rcu_no_explicit_rcu_lock,
-	     struct file *file, struct kobject *kobj,
-	     struct bin_attribute *bin_attr, char *buf, loff_t off, size_t len)
+	     int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
 {
 	struct bpf_rb_node *rb;
 	struct node_data *n, *m = NULL;
diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c b/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c
index 024ef2aae200..c47fc9d8e27f 100644
--- a/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c
+++ b/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c
@@ -127,11 +127,10 @@ long refcount_acquire_list_node_offset(void *ctx)
 	return 0;
 }
 
-SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
+SEC("?lsm.s/bpf")
 __failure __msg("function calls are not allowed while holding a lock")
 int BPF_PROG(rbtree_fail_sleepable_lock_across_rcu,
-	     struct file *file, struct kobject *kobj,
-	     struct bin_attribute *bin_attr, char *buf, loff_t off, size_t len)
+	     int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
 {
 	struct node_acquire *n;
 
diff --git a/tools/testing/selftests/bpf/progs/verifier_helper_restricted.c b/tools/testing/selftests/bpf/progs/verifier_helper_restricted.c
index 889c9b78b912..a87792353dfd 100644
--- a/tools/testing/selftests/bpf/progs/verifier_helper_restricted.c
+++ b/tools/testing/selftests/bpf/progs/verifier_helper_restricted.c
@@ -87,6 +87,7 @@ __naked void in_bpf_prog_type_kprobe_3(void)
 	call %[bpf_map_lookup_elem];			\
 	if r0 == 0 goto l0_%=;				\
 	r1 = r0;					\
+	r1 += 4;					\
 	call %[bpf_spin_lock];				\
 l0_%=:	exit;						\
 "	:
@@ -110,6 +111,7 @@ __naked void in_bpf_prog_type_tracepoint_3(void)
 	call %[bpf_map_lookup_elem];			\
 	if r0 == 0 goto l0_%=;				\
 	r1 = r0;					\
+	r1 += 4;					\
 	call %[bpf_spin_lock];				\
 l0_%=:	exit;						\
 "	:
@@ -133,6 +135,7 @@ __naked void bpf_prog_type_perf_event_3(void)
 	call %[bpf_map_lookup_elem];			\
 	if r0 == 0 goto l0_%=;				\
 	r1 = r0;					\
+	r1 += 4;					\
 	call %[bpf_spin_lock];				\
 l0_%=:	exit;						\
 "	:
@@ -156,6 +159,7 @@ __naked void bpf_prog_type_raw_tracepoint_3(void)
 	call %[bpf_map_lookup_elem];			\
 	if r0 == 0 goto l0_%=;				\
 	r1 = r0;					\
+	r1 += 4;					\
 	call %[bpf_spin_lock];				\
 l0_%=:	exit;						\
 "	:
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts
  2026-07-19 11:35 ` [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts Kumar Kartikeya Dwivedi
@ 2026-07-19 11:56   ` sashiko-bot
  2026-07-19 12:02     ` Kumar Kartikeya Dwivedi
  2026-07-20 22:00   ` Emil Tsalapatis
  1 sibling, 1 reply; 9+ messages in thread
From: sashiko-bot @ 2026-07-19 11:56 UTC (permalink / raw)
  To: Kumar Kartikeya Dwivedi; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] bpf_res_spin_lock() remains disabled for socket filter programs, contradicting the commit title 'Allow bpf_res_spin_lock() in all contexts'.

Pre-existing issues:
- [High] When parsing BTF fields, the check for a valid `bpf_res_spin_lock` offset incorrectly checks `rec->spin_lock_off` instead of `rec->res_spin_lock_off`.
--

--- Patch [1]: [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts ---
commit 88a844e18ff8ff22c90389d929ce1c63353b73fe
Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>

bpf: Allow bpf_res_spin_lock() in all contexts

This commit removes the restriction that prevents tracing programs from
using bpf_res_spin_lock(). The stated goal is to allow its use in all
contexts.

> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 4446f0bde88b5..bb6e16668d0d1 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -17815,7 +17815,9 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
>  			verbose(env, "socket filter progs cannot use bpf_spin_lock yet\n");
>  			return -EINVAL;
>  		}
> +	}

[Severity: Medium]
The commit message states the goal is to allow bpf_res_spin_lock() in all
contexts. However, just above this block in check_map_prog_compatibility(),
there is a check that still blocks it:

	if (btf_record_has_field(map->record, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK)) {
		if (prog_type == BPF_PROG_TYPE_SOCKET_FILTER) {

Does this contradict the commit title by leaving it disabled for socket
filter programs?

>  
> +	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
>  		if (is_tracing_prog_type(prog_type)) {
>  			verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
>  			return -EINVAL;


While reviewing this area, I also noticed a potential issue in another file.

kernel/bpf/btf.c:btf_parse_fields() {
	...
		case BPF_RES_SPIN_LOCK:
			WARN_ON_ONCE(rec->spin_lock_off >= 0);
			/* Cache offset for faster lookup at runtime */
			rec->res_spin_lock_off = rec->fields[i].offset;
			break;
	...
}

[Severity: High]
This is a pre-existing issue, but does this WARN_ON_ONCE() incorrectly check 
rec->spin_lock_off instead of rec->res_spin_lock_off?

If a user creates a BPF map value containing both a bpf_spin_lock and a
bpf_res_spin_lock, and BPF_SPIN_LOCK is parsed first, rec->spin_lock_off will
be non-negative. When BPF_RES_SPIN_LOCK is then processed, it appears this
would trivially trigger the warning, which could cause a kernel panic if
panic_on_warn is enabled.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260719113551.1294284-1-memxor@gmail.com?part=1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts
  2026-07-19 11:56   ` sashiko-bot
@ 2026-07-19 12:02     ` Kumar Kartikeya Dwivedi
  0 siblings, 0 replies; 9+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-07-19 12:02 UTC (permalink / raw)
  To: sashiko-reviews, Kumar Kartikeya Dwivedi; +Cc: bpf

On Sun Jul 19, 2026 at 1:56 PM CEST, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>
> New issues:
> - [Medium] bpf_res_spin_lock() remains disabled for socket filter programs, contradicting the commit title 'Allow bpf_res_spin_lock() in all contexts'.
>
> Pre-existing issues:
> - [High] When parsing BTF fields, the check for a valid `bpf_res_spin_lock` offset incorrectly checks `rec->spin_lock_off` instead of `rec->res_spin_lock_off`.
> --
>
> --- Patch [1]: [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts ---
> commit 88a844e18ff8ff22c90389d929ce1c63353b73fe
> Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>
> bpf: Allow bpf_res_spin_lock() in all contexts
>
> This commit removes the restriction that prevents tracing programs from
> using bpf_res_spin_lock(). The stated goal is to allow its use in all
> contexts.
>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index 4446f0bde88b5..bb6e16668d0d1 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -17815,7 +17815,9 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
>>  			verbose(env, "socket filter progs cannot use bpf_spin_lock yet\n");
>>  			return -EINVAL;
>>  		}
>> +	}
>
> [Severity: Medium]
> The commit message states the goal is to allow bpf_res_spin_lock() in all
> contexts. However, just above this block in check_map_prog_compatibility(),
> there is a check that still blocks it:
>
> 	if (btf_record_has_field(map->record, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK)) {
> 		if (prog_type == BPF_PROG_TYPE_SOCKET_FILTER) {
>
> Does this contradict the commit title by leaving it disabled for socket
> filter programs?
>

We don't want to enable it for socket filter.

>>
>> +	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
>>  		if (is_tracing_prog_type(prog_type)) {
>>  			verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
>>  			return -EINVAL;
>
>
> While reviewing this area, I also noticed a potential issue in another file.
>
> kernel/bpf/btf.c:btf_parse_fields() {
> 	...
> 		case BPF_RES_SPIN_LOCK:
> 			WARN_ON_ONCE(rec->spin_lock_off >= 0);
> 			/* Cache offset for faster lookup at runtime */
> 			rec->res_spin_lock_off = rec->fields[i].offset;
> 			break;
> 	...
> }
>
> [Severity: High]
> This is a pre-existing issue, but does this WARN_ON_ONCE() incorrectly check
> rec->spin_lock_off instead of rec->res_spin_lock_off?
>
> If a user creates a BPF map value containing both a bpf_spin_lock and a
> bpf_res_spin_lock, and BPF_SPIN_LOCK is parsed first, rec->spin_lock_off will
> be non-negative. When BPF_RES_SPIN_LOCK is then processed, it appears this
> would trivially trigger the warning, which could cause a kernel panic if
> panic_on_warn is enabled.

Yeah, it's not that serious, but will fix when I respin (or follow up separately).
That said, for now, I will wait for more reviews.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret
  2026-07-19 11:35 ` [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret Kumar Kartikeya Dwivedi
@ 2026-07-19 14:09   ` sashiko-bot
  2026-07-19 14:12     ` Kumar Kartikeya Dwivedi
  2026-07-20 22:40   ` Emil Tsalapatis
  1 sibling, 1 reply; 9+ messages in thread
From: sashiko-bot @ 2026-07-19 14:09 UTC (permalink / raw)
  To: Kumar Kartikeya Dwivedi; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] Tracing programs can bypass the bpf_spin_lock restriction using bpf_map_update_elem() with BPF_F_LOCK, leading to per-CPU IRQ state corruption.
- [Medium] EXT programs extending iterators are incorrectly classified as tracing programs, restricting them from using spin locks, lists, and rbtrees.

Pre-existing issues:
- [High] Kernel warning and memory leak in `bpf_obj_free_fields` when freeing map elements containing lists or rbtrees protected by `bpf_res_spin_lock`.
--

--- Patch [2]: [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret ---
commit 94d71df738bb27d6ad27a15a0ce402fd7032420d
Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>

bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret

This patch tightens the tracing program type checks and delays the evaluation
of map spin lock and list restrictions to the point of use rather than during
map compatibility checks.

> Fix this by tightening the check, and moving predicates checking for the
> restriction closer to the point of use. This change might affect
> existing programs using them in unsafe contexts, but in such cases, it
> is recommended for users to switch over to bpf_res_spin_lock instead.

[Severity: High]
This is a pre-existing issue, but recommending users switch to
bpf_res_spin_lock exposes an issue in bpf_obj_free_fields() when freeing
map elements containing lists or rbtrees.

When btf_parse_fields() encounters BPF_RES_SPIN_LOCK, it sets
res_spin_lock_off but leaves spin_lock_off as -EINVAL:

kernel/bpf/btf.c:btf_parse_fields() {
    ...
    rec->spin_lock_off = -EINVAL;
    rec->res_spin_lock_off = -EINVAL;
    ...
}

Later, bpf_obj_free_fields() unconditionally checks spin_lock_off:

kernel/bpf/syscall.c:bpf_obj_free_fields() {
    ...
    if (WARN_ON_ONCE(rec->spin_lock_off < 0))
        continue;
    ...
}

Could this trigger a WARN_ON_ONCE and leak memory for list/rbtree nodes
because the check skips the freeing logic when a bpf_res_spin_lock is
used instead of a standard bpf_spin_lock?


> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -17769,9 +17780,11 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
[ ... ]
> -static bool is_tracing_prog_type(enum bpf_prog_type type)
> +static bool is_tracing_prog_type(struct bpf_prog *prog)
>  {
> -	switch (type) {
> +	switch (resolve_prog_type(prog)) {
> +	case BPF_PROG_TYPE_TRACING:
> +		return prog->expected_attach_type != BPF_TRACE_ITER;

[Severity: Medium]
Does this check correctly handle extension programs (BPF_PROG_TYPE_EXT)?

For an extension program, the resolved type is BPF_PROG_TYPE_TRACING, but
its expected_attach_type is its own attach type (typically 0), not the
target's attach type which is stored in saved_dst_attach_type.

Could this cause valid extension programs that extend iterators to be
erroneously rejected by the verifier when trying to use spin locks, lists,
or rbtrees?


> @@ -17802,14 +17815,6 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
[ ... ]
> -	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
> -		if (is_tracing_prog_type(prog_type)) {
> -			verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
> -			return -EINVAL;
> -		}
> -	}
> +	/*
> +	 * Restrictions on using BPF list,rbtree,spin_lock is checked later upon
> +	 * use, since rejecting accesing map containing them in programs is too
> +	 * conservative.
> +	 */

[Severity: High]
Does removing this map-level check allow tracing programs to bypass the
lock restriction using bpf_map_update_elem() with the BPF_F_LOCK flag?

While the explicit lock helper calls are now blocked in process_spin_lock(),
the BPF_F_LOCK flag bypasses those verifier checks and executes
copy_map_value_locked():

kernel/bpf/helpers.c:copy_map_value_locked() {
    ...
    __bpf_spin_lock_irqsave(lock);
    ...
}

Can this corrupt the irqsave_flags per-CPU variable when tracing programs
execute in NMI or arbitrary IRQ contexts, potentially leading to deadlocks?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260719113551.1294284-1-memxor@gmail.com?part=2

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret
  2026-07-19 14:09   ` sashiko-bot
@ 2026-07-19 14:12     ` Kumar Kartikeya Dwivedi
  0 siblings, 0 replies; 9+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-07-19 14:12 UTC (permalink / raw)
  To: sashiko-reviews, Kumar Kartikeya Dwivedi; +Cc: bpf

On Sun Jul 19, 2026 at 4:09 PM CEST, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
>
> New issues:
> - [High] Tracing programs can bypass the bpf_spin_lock restriction using bpf_map_update_elem() with BPF_F_LOCK, leading to per-CPU IRQ state corruption.
> - [Medium] EXT programs extending iterators are incorrectly classified as tracing programs, restricting them from using spin locks, lists, and rbtrees.
>
> Pre-existing issues:
> - [High] Kernel warning and memory leak in `bpf_obj_free_fields` when freeing map elements containing lists or rbtrees protected by `bpf_res_spin_lock`.
> --
>
> --- Patch [2]: [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret ---
> commit 94d71df738bb27d6ad27a15a0ce402fd7032420d
> Author: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>
> bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret
>
> This patch tightens the tracing program type checks and delays the evaluation
> of map spin lock and list restrictions to the point of use rather than during
> map compatibility checks.
>
>> Fix this by tightening the check, and moving predicates checking for the
>> restriction closer to the point of use. This change might affect
>> existing programs using them in unsafe contexts, but in such cases, it
>> is recommended for users to switch over to bpf_res_spin_lock instead.
>
> [Severity: High]
> This is a pre-existing issue, but recommending users switch to
> bpf_res_spin_lock exposes an issue in bpf_obj_free_fields() when freeing
> map elements containing lists or rbtrees.
>
> When btf_parse_fields() encounters BPF_RES_SPIN_LOCK, it sets
> res_spin_lock_off but leaves spin_lock_off as -EINVAL:
>
> kernel/bpf/btf.c:btf_parse_fields() {
>     ...
>     rec->spin_lock_off = -EINVAL;
>     rec->res_spin_lock_off = -EINVAL;
>     ...
> }
>
> Later, bpf_obj_free_fields() unconditionally checks spin_lock_off:
>
> kernel/bpf/syscall.c:bpf_obj_free_fields() {
>     ...
>     if (WARN_ON_ONCE(rec->spin_lock_off < 0))
>         continue;
>     ...
> }
>
> Could this trigger a WARN_ON_ONCE and leak memory for list/rbtree nodes
> because the check skips the freeing logic when a bpf_res_spin_lock is
> used instead of a standard bpf_spin_lock?
>

Sent fix for this.

>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -17769,9 +17780,11 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
> [ ... ]
>> -static bool is_tracing_prog_type(enum bpf_prog_type type)
>> +static bool is_tracing_prog_type(struct bpf_prog *prog)
>>  {
>> -	switch (type) {
>> +	switch (resolve_prog_type(prog)) {
>> +	case BPF_PROG_TYPE_TRACING:
>> +		return prog->expected_attach_type != BPF_TRACE_ITER;
>
> [Severity: Medium]
> Does this check correctly handle extension programs (BPF_PROG_TYPE_EXT)?
>
> For an extension program, the resolved type is BPF_PROG_TYPE_TRACING, but
> its expected_attach_type is its own attach type (typically 0), not the
> target's attach type which is stored in saved_dst_attach_type.
>
> Could this cause valid extension programs that extend iterators to be
> erroneously rejected by the verifier when trying to use spin locks, lists,
> or rbtrees?
>

This is a separate problem in multiple places, let's keep this one as is for
now, bpf_prog_check_recur() has similar issue. We need audit and fix all places
properly.

>
>> @@ -17802,14 +17815,6 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
> [ ... ]
>> -	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
>> -		if (is_tracing_prog_type(prog_type)) {
>> -			verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
>> -			return -EINVAL;
>> -		}
>> -	}
>> +	/*
>> +	 * Restrictions on using BPF list,rbtree,spin_lock is checked later upon
>> +	 * use, since rejecting accesing map containing them in programs is too
>> +	 * conservative.
>> +	 */
>
> [Severity: High]
> Does removing this map-level check allow tracing programs to bypass the
> lock restriction using bpf_map_update_elem() with the BPF_F_LOCK flag?
>
> While the explicit lock helper calls are now blocked in process_spin_lock(),
> the BPF_F_LOCK flag bypasses those verifier checks and executes
> copy_map_value_locked():
>
> kernel/bpf/helpers.c:copy_map_value_locked() {
>     ...
>     __bpf_spin_lock_irqsave(lock);
>     ...
> }
>
> Can this corrupt the irqsave_flags per-CPU variable when tracing programs
> execute in NMI or arbitrary IRQ contexts, potentially leading to deadlocks?

Hmm, valid point. Let me think about this, I might have to keep it during map
compatibility checks, and see how tests should be adjusted.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts
  2026-07-19 11:35 ` [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts Kumar Kartikeya Dwivedi
  2026-07-19 11:56   ` sashiko-bot
@ 2026-07-20 22:00   ` Emil Tsalapatis
  1 sibling, 0 replies; 9+ messages in thread
From: Emil Tsalapatis @ 2026-07-20 22:00 UTC (permalink / raw)
  To: Kumar Kartikeya Dwivedi, bpf
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Eduard Zingerman, kkd, kernel-team

On Sun Jul 19, 2026 at 7:35 AM EDT, Kumar Kartikeya Dwivedi wrote:
> There is no particular reason to keep bpf_res_spin_lock() disabled in
> tracing programs, since it is safe against reentrancy and deadlocks.
> Remove the restriction for tracing programs covered by the predicate
> is_tracing_prog_type().
>
> This is a prerequisite before the definition of is_tracing_prog_type()
> is updated to include raw_tp, fentry, fexit, and fmod_ret. Existing
> tracing programs will be updated to use bpf_res_spin_lock() instead when
> it is available.
>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>

Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>

I assume we do not want to enable this for socket filter to avoid
additional testing, since there is currently no clear use case for
it?

> ---
>  kernel/bpf/verifier.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 4446f0bde88b..bb6e16668d0d 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -17815,7 +17815,9 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
>  			verbose(env, "socket filter progs cannot use bpf_spin_lock yet\n");
>  			return -EINVAL;
>  		}
> +	}
>  
> +	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
>  		if (is_tracing_prog_type(prog_type)) {
>  			verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
>  			return -EINVAL;


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret
  2026-07-19 11:35 ` [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret Kumar Kartikeya Dwivedi
  2026-07-19 14:09   ` sashiko-bot
@ 2026-07-20 22:40   ` Emil Tsalapatis
  1 sibling, 0 replies; 9+ messages in thread
From: Emil Tsalapatis @ 2026-07-20 22:40 UTC (permalink / raw)
  To: Kumar Kartikeya Dwivedi, bpf
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Eduard Zingerman, kkd, kernel-team

On Sun Jul 19, 2026 at 7:35 AM EDT, Kumar Kartikeya Dwivedi wrote:
> The is_tracing_prog_type() predicate currently skips fentry, fexit,
> fmod_ret, and also raw_tp attach type in BPF_PROG_TYPE_TRACING, due to
> oversight.
>
> Fix this by tightening the check, and moving predicates checking for the
> restriction closer to the point of use. This change might affect
> existing programs using them in unsafe contexts, but in such cases, it
> is recommended for users to switch over to bpf_res_spin_lock instead.
>
> Make appropriate changes to selftests to adjust to the change in error
> messages and added restrictions.
>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>

Overall makes sense, nits below. For the bpf_map_update_elem edge case
Sashiko brought up, can't we carve out a check in the verifier specifically
for this edge case (tracing program calling the helper with flags that 
cannot be proven not to include BPF_F_LOCK)?

> ---
>  kernel/bpf/verifier.c                         | 48 ++++++++++---------
>  .../selftests/bpf/prog_tests/linked_list.c    |  6 +--
>  .../selftests/bpf/prog_tests/map_btf.c        | 19 ++++----
>  .../selftests/bpf/progs/map_in_map_btf.c      |  2 +-
>  .../selftests/bpf/progs/normal_map_btf.c      |  2 +-
>  .../selftests/bpf/progs/refcounted_kptr.c     | 10 ++--
>  .../bpf/progs/refcounted_kptr_fail.c          |  5 +-
>  .../bpf/progs/verifier_helper_restricted.c    |  4 ++
>  8 files changed, 50 insertions(+), 46 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index bb6e16668d0d..3fe2410c7ce3 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -207,7 +207,7 @@ static int release_reference_nomark(struct bpf_verifier_state *state, int id);
>  static int release_reference(struct bpf_verifier_env *env, int id);
>  static void invalidate_non_owning_refs(struct bpf_verifier_env *env);
>  static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env);
> -static bool is_tracing_prog_type(enum bpf_prog_type type);
> +static bool is_tracing_prog_type(struct bpf_prog *prog);
>  static int ref_set_non_owning(struct bpf_verifier_env *env,
>  			      struct bpf_reg_state *reg);
>  static bool is_trusted_reg(struct bpf_verifier_env *env, const struct bpf_reg_state *reg);
> @@ -7089,6 +7089,12 @@ static int process_spin_lock(struct bpf_verifier_env *env, struct bpf_reg_state
>  			val, lock_str, spin_lock_off);
>  		return -EINVAL;
>  	}
> +
> +	if (is_tracing_prog_type(env->prog) && !is_res_lock) {
> +		verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");

Should we change the "yet" phrasing? Are we ever planning on
implementng BPF vanilla spinlock support for tracing programs?

> +		return -EINVAL;
> +	}
> +
>  	if (is_lock) {
>  		void *ptr;
>  		int type;
> @@ -12317,6 +12323,10 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me
>  				verbose(env, "allocated object must be referenced\n");
>  				return -EINVAL;
>  			}
> +			if (is_tracing_prog_type(env->prog)) {
> +				verbose(env, "tracing progs cannot use bpf_{list_head,rb_root} yet\n");

Same here.

> +				return -EINVAL;
> +			}
>  			ret = process_kf_arg_ptr_to_list_head(env, reg, argno, meta);
>  			if (ret < 0)
>  				return ret;
> @@ -12333,6 +12343,10 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me
>  				verbose(env, "allocated object must be referenced\n");
>  				return -EINVAL;
>  			}
> +			if (is_tracing_prog_type(env->prog)) {
> +				verbose(env, "tracing progs cannot use bpf_{list_head,rb_root} yet\n");
> +				return -EINVAL;
> +			}
>  			ret = process_kf_arg_ptr_to_rbtree_root(env, reg, argno, meta);
>  			if (ret < 0)
>  				return ret;
> @@ -12966,7 +12980,6 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
>  			    int *insn_idx_p)
>  {
>  	bool sleepable, rcu_lock, rcu_unlock, preempt_disable, preempt_enable;
> -	enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
>  	struct bpf_reg_state *regs = cur_regs(env);
>  	const char *func_name, *ptr_type_name;
>  	const struct btf_type *t, *ptr_type;
> @@ -13044,10 +13057,8 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
>  		return err;
>  
>  	if ((is_bpf_obj_drop_kfunc(meta.func_id) ||
> -	     is_bpf_percpu_obj_drop_kfunc(meta.func_id)) && (is_tracing_prog_type(prog_type) ||
> -	     /* is_tracing_prog_type() for now doesn't cover non-iterator tracing progs. */
> -	     (prog_type == BPF_PROG_TYPE_TRACING && env->prog->expected_attach_type != BPF_TRACE_ITER
> -	      && !env->prog->sleepable))) {
> +	     is_bpf_percpu_obj_drop_kfunc(meta.func_id)) && (is_tracing_prog_type(env->prog)
> +	     && !env->prog->sleepable)) {

This was already the case, but the way we split the terms is confusing
and AFAICT there's an extra pair of parentheses. Can we do:

	if ((is_bpf_obj_drop_kfunc(meta.func_id) || is_bpf_percpu_obj_drop_kfunc(meta.func_id)) &&
	    is_tracing_prog_type(prog_type) &&
	    !env->prog->sleepable) {
	}

and maybe add a predicate about drop_kfuncs to clean up line 1? We have
many similar precicates already.

>  		struct btf_struct_meta *struct_meta;
>  
>  		struct_meta = btf_find_struct_meta(meta.arg_btf, meta.arg_btf_id);
> @@ -17769,9 +17780,11 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
>  	return __add_used_btf(env, btf);
>  }
>  
> -static bool is_tracing_prog_type(enum bpf_prog_type type)
> +static bool is_tracing_prog_type(struct bpf_prog *prog)
>  {
> -	switch (type) {
> +	switch (resolve_prog_type(prog)) {
> +	case BPF_PROG_TYPE_TRACING:
> +		return prog->expected_attach_type != BPF_TRACE_ITER;
>  	case BPF_PROG_TYPE_KPROBE:
>  	case BPF_PROG_TYPE_TRACEPOINT:
>  	case BPF_PROG_TYPE_PERF_EVENT:
> @@ -17802,14 +17815,6 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
>  		return -EACCES;
>  	}
>  
> -	if (btf_record_has_field(map->record, BPF_LIST_HEAD) ||
> -	    btf_record_has_field(map->record, BPF_RB_ROOT)) {
> -		if (is_tracing_prog_type(prog_type)) {
> -			verbose(env, "tracing progs cannot use bpf_{list_head,rb_root} yet\n");
> -			return -EINVAL;
> -		}
> -	}
> -
>  	if (btf_record_has_field(map->record, BPF_SPIN_LOCK | BPF_RES_SPIN_LOCK)) {
>  		if (prog_type == BPF_PROG_TYPE_SOCKET_FILTER) {
>  			verbose(env, "socket filter progs cannot use bpf_spin_lock yet\n");
> @@ -17817,12 +17822,11 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
>  		}
>  	}
>  
> -	if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
> -		if (is_tracing_prog_type(prog_type)) {
> -			verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
> -			return -EINVAL;
> -		}
> -	}
> +	/*
> +	 * Restrictions on using BPF list,rbtree,spin_lock is checked later upon
> +	 * use, since rejecting accesing map containing them in programs is too
> +	 * conservative.
> +	 */
>  
>  	if ((bpf_prog_is_offloaded(prog->aux) || bpf_map_is_offloaded(map)) &&
>  	    !bpf_offload_prog_map_match(prog, map)) {
> diff --git a/tools/testing/selftests/bpf/prog_tests/linked_list.c b/tools/testing/selftests/bpf/prog_tests/linked_list.c
> index c3d133c6a00d..702268422673 100644
> --- a/tools/testing/selftests/bpf/prog_tests/linked_list.c
> +++ b/tools/testing/selftests/bpf/prog_tests/linked_list.c
> @@ -59,12 +59,12 @@ static struct {
>  	TEST(inner_map, pop_front)
>  	TEST(inner_map, pop_back)
>  #undef TEST
> -	{ "map_compat_kprobe", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
> -	{ "map_compat_kretprobe", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
> +	{ "map_compat_kprobe", "calling kernel function bpf_list_push_front is not allowed" },
> +	{ "map_compat_kretprobe", "calling kernel function bpf_list_push_front is not allowed" },
>  	{ "map_compat_tp", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
>  	{ "map_compat_perf", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
>  	{ "map_compat_raw_tp", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
> -	{ "map_compat_raw_tp_w", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
> +	{ "map_compat_raw_tp_w", "calling kernel function bpf_list_push_front is not allowed" },
>  	{ "obj_type_id_oor", "local type ID argument must be in range [0, U32_MAX]" },
>  	{ "obj_new_no_composite", "bpf_obj_new/bpf_percpu_obj_new type ID argument must be of a struct" },
>  	{ "obj_new_no_struct", "bpf_obj_new/bpf_percpu_obj_new type ID argument must be of a struct" },
> diff --git a/tools/testing/selftests/bpf/prog_tests/map_btf.c b/tools/testing/selftests/bpf/prog_tests/map_btf.c
> index 2c4ef6037573..1313f680fcda 100644
> --- a/tools/testing/selftests/bpf/prog_tests/map_btf.c
> +++ b/tools/testing/selftests/bpf/prog_tests/map_btf.c
> @@ -7,6 +7,7 @@
>  
>  static void do_test_normal_map_btf(void)
>  {
> +	LIBBPF_OPTS(bpf_test_run_opts, opts);
>  	struct normal_map_btf *skel;
>  	int i, err, new_fd = -1;
>  	int map_fd_arr[64];
> @@ -15,12 +16,10 @@ static void do_test_normal_map_btf(void)
>  	if (!ASSERT_OK_PTR(skel, "open_load"))
>  		return;
>  
> -	err = normal_map_btf__attach(skel);
> -	if (!ASSERT_OK(err, "attach"))
> -		goto out;
> -
>  	skel->bss->pid = getpid();
> -	usleep(1);
> +	err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.add_to_list_in_array), &opts);
> +	if (!ASSERT_OK(err, "test_run"))
> +		goto out;
>  	ASSERT_TRUE(skel->bss->done, "done");
>  
>  	/* Use percpu_array to slow bpf_map_free_deferred() down.
> @@ -55,6 +54,7 @@ static void do_test_normal_map_btf(void)
>  
>  static void do_test_map_in_map_btf(void)
>  {
> +	LIBBPF_OPTS(bpf_test_run_opts, opts);
>  	int err, zero = 0, new_fd = -1;
>  	struct map_in_map_btf *skel;
>  
> @@ -62,12 +62,11 @@ static void do_test_map_in_map_btf(void)
>  	if (!ASSERT_OK_PTR(skel, "open_load"))
>  		return;
>  
> -	err = map_in_map_btf__attach(skel);
> -	if (!ASSERT_OK(err, "attach"))
> -		goto out;
> -
>  	skel->bss->pid = getpid();
> -	usleep(1);
> +	err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.add_to_list_in_inner_array),
> +				     &opts);
> +	if (!ASSERT_OK(err, "test_run"))
> +		goto out;
>  	ASSERT_TRUE(skel->bss->done, "done");
>  
>  	/* Close inner_array fd later */
> diff --git a/tools/testing/selftests/bpf/progs/map_in_map_btf.c b/tools/testing/selftests/bpf/progs/map_in_map_btf.c
> index 7a1336d7b16a..eb4d009b8a62 100644
> --- a/tools/testing/selftests/bpf/progs/map_in_map_btf.c
> +++ b/tools/testing/selftests/bpf/progs/map_in_map_btf.c
> @@ -41,7 +41,7 @@ char _license[] SEC("license") = "GPL";
>  int pid = 0;
>  bool done = false;
>  
> -SEC("fentry/" SYS_PREFIX "sys_nanosleep")
> +SEC("syscall")
>  int add_to_list_in_inner_array(void *ctx)
>  {
>  	struct map_value *value;
> diff --git a/tools/testing/selftests/bpf/progs/normal_map_btf.c b/tools/testing/selftests/bpf/progs/normal_map_btf.c
> index a45c9299552c..90ac1ec365b9 100644
> --- a/tools/testing/selftests/bpf/progs/normal_map_btf.c
> +++ b/tools/testing/selftests/bpf/progs/normal_map_btf.c
> @@ -29,7 +29,7 @@ char _license[] SEC("license") = "GPL";
>  int pid = 0;
>  bool done = false;
>  
> -SEC("fentry/" SYS_PREFIX "sys_nanosleep")
> +SEC("syscall")
>  int add_to_list_in_array(void *ctx)
>  {
>  	struct map_value *value;
> diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr.c b/tools/testing/selftests/bpf/progs/refcounted_kptr.c
> index 61906f48025c..9a783693ce08 100644
> --- a/tools/testing/selftests/bpf/progs/refcounted_kptr.c
> +++ b/tools/testing/selftests/bpf/progs/refcounted_kptr.c
> @@ -921,11 +921,10 @@ long rbtree_wrong_owner_remove_fail_a2(void *ctx)
>  	return 0;
>  }
>  
> -SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
> +SEC("?lsm.s/bpf")
>  __success
>  int BPF_PROG(rbtree_sleepable_rcu,
> -	     struct file *file, struct kobject *kobj,
> -	     struct bin_attribute *bin_attr, char *buf, loff_t off, size_t len)
> +	     int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
>  {
>  	struct bpf_rb_node *rb;
>  	struct node_data *n, *m = NULL;
> @@ -955,11 +954,10 @@ int BPF_PROG(rbtree_sleepable_rcu,
>  	return 0;
>  }
>  
> -SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
> +SEC("?lsm.s/bpf")
>  __success
>  int BPF_PROG(rbtree_sleepable_rcu_no_explicit_rcu_lock,
> -	     struct file *file, struct kobject *kobj,
> -	     struct bin_attribute *bin_attr, char *buf, loff_t off, size_t len)
> +	     int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
>  {
>  	struct bpf_rb_node *rb;
>  	struct node_data *n, *m = NULL;
> diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c b/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c
> index 024ef2aae200..c47fc9d8e27f 100644
> --- a/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c
> +++ b/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c
> @@ -127,11 +127,10 @@ long refcount_acquire_list_node_offset(void *ctx)
>  	return 0;
>  }
>  
> -SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
> +SEC("?lsm.s/bpf")
>  __failure __msg("function calls are not allowed while holding a lock")
>  int BPF_PROG(rbtree_fail_sleepable_lock_across_rcu,
> -	     struct file *file, struct kobject *kobj,
> -	     struct bin_attribute *bin_attr, char *buf, loff_t off, size_t len)
> +	     int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
>  {
>  	struct node_acquire *n;
>  
> diff --git a/tools/testing/selftests/bpf/progs/verifier_helper_restricted.c b/tools/testing/selftests/bpf/progs/verifier_helper_restricted.c
> index 889c9b78b912..a87792353dfd 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_helper_restricted.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_helper_restricted.c
> @@ -87,6 +87,7 @@ __naked void in_bpf_prog_type_kprobe_3(void)
>  	call %[bpf_map_lookup_elem];			\
>  	if r0 == 0 goto l0_%=;				\
>  	r1 = r0;					\
> +	r1 += 4;					\
>  	call %[bpf_spin_lock];				\
>  l0_%=:	exit;						\
>  "	:
> @@ -110,6 +111,7 @@ __naked void in_bpf_prog_type_tracepoint_3(void)
>  	call %[bpf_map_lookup_elem];			\
>  	if r0 == 0 goto l0_%=;				\
>  	r1 = r0;					\
> +	r1 += 4;					\
>  	call %[bpf_spin_lock];				\
>  l0_%=:	exit;						\
>  "	:
> @@ -133,6 +135,7 @@ __naked void bpf_prog_type_perf_event_3(void)
>  	call %[bpf_map_lookup_elem];			\
>  	if r0 == 0 goto l0_%=;				\
>  	r1 = r0;					\
> +	r1 += 4;					\
>  	call %[bpf_spin_lock];				\
>  l0_%=:	exit;						\
>  "	:
> @@ -156,6 +159,7 @@ __naked void bpf_prog_type_raw_tracepoint_3(void)
>  	call %[bpf_map_lookup_elem];			\
>  	if r0 == 0 goto l0_%=;				\
>  	r1 = r0;					\
> +	r1 += 4;					\
>  	call %[bpf_spin_lock];				\
>  l0_%=:	exit;						\
>  "	:


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-07-20 22:40 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-19 11:35 [PATCH bpf-next v1 0/2] Open up res_spin_lock for tracing programs, fix is_tracing_prog_type() Kumar Kartikeya Dwivedi
2026-07-19 11:35 ` [PATCH bpf-next v1 1/2] bpf: Allow bpf_res_spin_lock() in all contexts Kumar Kartikeya Dwivedi
2026-07-19 11:56   ` sashiko-bot
2026-07-19 12:02     ` Kumar Kartikeya Dwivedi
2026-07-20 22:00   ` Emil Tsalapatis
2026-07-19 11:35 ` [PATCH bpf-next v1 2/2] bpf: Fix is_tracing_prog_type() to cover fentry/fexit/fmod_ret Kumar Kartikeya Dwivedi
2026-07-19 14:09   ` sashiko-bot
2026-07-19 14:12     ` Kumar Kartikeya Dwivedi
2026-07-20 22:40   ` Emil Tsalapatis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.