Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH bpf-next v1 05/10] selftests/bpf: Add tests for KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-09 18:48 UTC (permalink / raw)
  To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman
  Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
	Jiri Kosina, bpf, linux-kernel, linux-input, sched-ext
In-Reply-To: <20260109184852.1089786-1-ihor.solodrai@linux.dev>

Add trivial end-to-end tests to validate that KF_IMPLICIT_ARGS flag is
properly handled by both resolve_btfids and the verifier.

Declare kfuncs in bpf_testmod. Check that bpf_prog_aux pointer is set
in the kfunc implementation. Verify that calls with implicit args and
a legacy case all work.

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
 .../bpf/prog_tests/kfunc_implicit_args.c      | 10 +++++
 .../selftests/bpf/progs/kfunc_implicit_args.c | 41 +++++++++++++++++++
 .../selftests/bpf/test_kmods/bpf_testmod.c    | 26 ++++++++++++
 3 files changed, 77 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/kfunc_implicit_args.c
 create mode 100644 tools/testing/selftests/bpf/progs/kfunc_implicit_args.c

diff --git a/tools/testing/selftests/bpf/prog_tests/kfunc_implicit_args.c b/tools/testing/selftests/bpf/prog_tests/kfunc_implicit_args.c
new file mode 100644
index 000000000000..5e4793c9c29a
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/kfunc_implicit_args.c
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
+
+#include <test_progs.h>
+#include "kfunc_implicit_args.skel.h"
+
+void test_kfunc_implicit_args(void)
+{
+	RUN_TESTS(kfunc_implicit_args);
+}
diff --git a/tools/testing/selftests/bpf/progs/kfunc_implicit_args.c b/tools/testing/selftests/bpf/progs/kfunc_implicit_args.c
new file mode 100644
index 000000000000..a1e456500442
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/kfunc_implicit_args.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
+
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+extern int bpf_kfunc_implicit_arg(int a) __weak __ksym;
+extern int bpf_kfunc_implicit_arg_impl(int a, void *aux__prog) __weak __ksym; // illegal
+extern int bpf_kfunc_implicit_arg_legacy(int a, int b) __weak __ksym;
+extern int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, void *aux__prog) __weak __ksym;
+
+char _license[] SEC("license") = "GPL";
+
+SEC("syscall")
+__retval(5)
+int test_kfunc_implicit_arg(void *ctx)
+{
+	return bpf_kfunc_implicit_arg(5);
+}
+
+SEC("syscall")
+__failure
+int test_kfunc_implicit_arg_impl_illegal(void *ctx)
+{
+	return bpf_kfunc_implicit_arg_impl(5, NULL);
+}
+
+SEC("syscall")
+__retval(7)
+int test_kfunc_implicit_arg_legacy(void *ctx)
+{
+	return bpf_kfunc_implicit_arg_legacy(3, 4);
+}
+
+SEC("syscall")
+__retval(11)
+int test_kfunc_implicit_arg_legacy_impl(void *ctx)
+{
+	return bpf_kfunc_implicit_arg_legacy_impl(5, 6, NULL);
+}
diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
index 1c41d03bd5a1..503451875d33 100644
--- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
+++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
@@ -1136,6 +1136,10 @@ __bpf_kfunc int bpf_kfunc_st_ops_inc10(struct st_ops_args *args)
 __bpf_kfunc int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id);
 __bpf_kfunc int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux_prog);
 
+__bpf_kfunc int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux);
+__bpf_kfunc int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux);
+__bpf_kfunc int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, void *aux__prog);
+
 BTF_KFUNCS_START(bpf_testmod_check_kfunc_ids)
 BTF_ID_FLAGS(func, bpf_testmod_test_mod_kfunc)
 BTF_ID_FLAGS(func, bpf_kfunc_call_test1)
@@ -1178,6 +1182,9 @@ BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_pro_epilogue, KF_SLEEPABLE)
 BTF_ID_FLAGS(func, bpf_kfunc_st_ops_inc10)
 BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1)
 BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1_impl)
+BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg, KF_IMPLICIT_ARGS)
+BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy, KF_IMPLICIT_ARGS)
+BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy_impl)
 BTF_KFUNCS_END(bpf_testmod_check_kfunc_ids)
 
 static int bpf_testmod_ops_init(struct btf *btf)
@@ -1669,6 +1676,25 @@ int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux__prog
 	return ret;
 }
 
+int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux)
+{
+	if (aux && a > 0)
+		return a;
+	return -EINVAL;
+}
+
+int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux)
+{
+	if (aux)
+		return a + b;
+	return -EINVAL;
+}
+
+int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, void *aux__prog)
+{
+	return bpf_kfunc_implicit_arg_legacy(a, b, aux__prog);
+}
+
 static int multi_st_ops_reg(void *kdata, struct bpf_link *link)
 {
 	struct bpf_testmod_multi_st_ops *st_ops =
-- 
2.52.0


^ permalink raw reply related

* [PATCH bpf-next v1 06/10] bpf: Add bpf_wq_set_callback kfunc with KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-09 18:48 UTC (permalink / raw)
  To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman
  Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
	Jiri Kosina, bpf, linux-kernel, linux-input, sched-ext
In-Reply-To: <20260109184852.1089786-1-ihor.solodrai@linux.dev>

Implement bpf_wq_set_callback() with an implicit bpf_prog_aux
argument, and change bpf_wq_set_callback_impl() to call the new kfunc.

Update special kfunc checks in the verifier to accept both versions of
the function.

In the selftests, a bpf_wq_set_callback_impl() call is intentionally
introduced to confirm that both signatures are handled correctly.

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
 kernel/bpf/helpers.c                           | 18 +++++++++++++-----
 kernel/bpf/verifier.c                          | 15 +++++++++------
 tools/testing/selftests/bpf/bpf_experimental.h |  5 -----
 tools/testing/selftests/bpf/progs/wq.c         |  2 +-
 .../testing/selftests/bpf/progs/wq_failures.c  |  4 ++--
 5 files changed, 25 insertions(+), 19 deletions(-)

diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 9eaa4185e0a7..23aa785c0f99 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -3120,12 +3120,11 @@ __bpf_kfunc int bpf_wq_start(struct bpf_wq *wq, unsigned int flags)
 	return 0;
 }
 
-__bpf_kfunc int bpf_wq_set_callback_impl(struct bpf_wq *wq,
-					 int (callback_fn)(void *map, int *key, void *value),
-					 unsigned int flags,
-					 void *aux__prog)
+__bpf_kfunc int bpf_wq_set_callback(struct bpf_wq *wq,
+				    int (callback_fn)(void *map, int *key, void *value),
+				    unsigned int flags,
+				    struct bpf_prog_aux *aux)
 {
-	struct bpf_prog_aux *aux = (struct bpf_prog_aux *)aux__prog;
 	struct bpf_async_kern *async = (struct bpf_async_kern *)wq;
 
 	if (flags)
@@ -3134,6 +3133,14 @@ __bpf_kfunc int bpf_wq_set_callback_impl(struct bpf_wq *wq,
 	return __bpf_async_set_callback(async, callback_fn, aux, flags, BPF_ASYNC_TYPE_WQ);
 }
 
+__bpf_kfunc int bpf_wq_set_callback_impl(struct bpf_wq *wq,
+					 int (callback_fn)(void *map, int *key, void *value),
+					 unsigned int flags,
+					 void *aux__prog)
+{
+	return bpf_wq_set_callback(wq, callback_fn, flags, aux__prog);
+}
+
 __bpf_kfunc void bpf_preempt_disable(void)
 {
 	preempt_disable();
@@ -4488,6 +4495,7 @@ BTF_ID_FLAGS(func, bpf_dynptr_memset)
 BTF_ID_FLAGS(func, bpf_modify_return_test_tp)
 #endif
 BTF_ID_FLAGS(func, bpf_wq_init)
+BTF_ID_FLAGS(func, bpf_wq_set_callback, KF_IMPLICIT_ARGS)
 BTF_ID_FLAGS(func, bpf_wq_set_callback_impl)
 BTF_ID_FLAGS(func, bpf_wq_start)
 BTF_ID_FLAGS(func, bpf_preempt_disable)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 5541ab674e30..e5aeee554377 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -520,7 +520,7 @@ static bool is_async_callback_calling_kfunc(u32 btf_id);
 static bool is_callback_calling_kfunc(u32 btf_id);
 static bool is_bpf_throw_kfunc(struct bpf_insn *insn);
 
-static bool is_bpf_wq_set_callback_impl_kfunc(u32 btf_id);
+static bool is_bpf_wq_set_callback_kfunc(u32 btf_id);
 static bool is_task_work_add_kfunc(u32 func_id);
 
 static bool is_sync_callback_calling_function(enum bpf_func_id func_id)
@@ -562,7 +562,7 @@ static bool is_async_cb_sleepable(struct bpf_verifier_env *env, struct bpf_insn
 
 	/* bpf_wq and bpf_task_work callbacks are always sleepable. */
 	if (bpf_pseudo_kfunc_call(insn) && insn->off == 0 &&
-	    (is_bpf_wq_set_callback_impl_kfunc(insn->imm) || is_task_work_add_kfunc(insn->imm)))
+	    (is_bpf_wq_set_callback_kfunc(insn->imm) || is_task_work_add_kfunc(insn->imm)))
 		return true;
 
 	verifier_bug(env, "unhandled async callback in is_async_cb_sleepable");
@@ -12470,6 +12470,7 @@ enum special_kfunc_type {
 	KF_bpf_arena_alloc_pages,
 	KF_bpf_arena_free_pages,
 	KF_bpf_arena_reserve_pages,
+	KF_bpf_wq_set_callback,
 };
 
 BTF_ID_LIST(special_kfunc_list)
@@ -12547,6 +12548,7 @@ BTF_ID(func, bpf_task_work_schedule_resume_impl)
 BTF_ID(func, bpf_arena_alloc_pages)
 BTF_ID(func, bpf_arena_free_pages)
 BTF_ID(func, bpf_arena_reserve_pages)
+BTF_ID(func, bpf_wq_set_callback)
 
 static bool is_task_work_add_kfunc(u32 func_id)
 {
@@ -13002,7 +13004,7 @@ static bool is_sync_callback_calling_kfunc(u32 btf_id)
 
 static bool is_async_callback_calling_kfunc(u32 btf_id)
 {
-	return btf_id == special_kfunc_list[KF_bpf_wq_set_callback_impl] ||
+	return is_bpf_wq_set_callback_kfunc(btf_id) ||
 	       is_task_work_add_kfunc(btf_id);
 }
 
@@ -13012,9 +13014,10 @@ static bool is_bpf_throw_kfunc(struct bpf_insn *insn)
 	       insn->imm == special_kfunc_list[KF_bpf_throw];
 }
 
-static bool is_bpf_wq_set_callback_impl_kfunc(u32 btf_id)
+static bool is_bpf_wq_set_callback_kfunc(u32 btf_id)
 {
-	return btf_id == special_kfunc_list[KF_bpf_wq_set_callback_impl];
+	return btf_id == special_kfunc_list[KF_bpf_wq_set_callback_impl] ||
+	       btf_id == special_kfunc_list[KF_bpf_wq_set_callback];
 }
 
 static bool is_callback_calling_kfunc(u32 btf_id)
@@ -14093,7 +14096,7 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
 		meta.r0_rdonly = false;
 	}
 
-	if (is_bpf_wq_set_callback_impl_kfunc(meta.func_id)) {
+	if (is_bpf_wq_set_callback_kfunc(meta.func_id)) {
 		err = push_callback_call(env, insn, insn_idx, meta.subprogno,
 					 set_timer_callback_state);
 		if (err) {
diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index 2cd9165c7348..68a49b1f77ae 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -580,11 +580,6 @@ extern void bpf_iter_css_destroy(struct bpf_iter_css *it) __weak __ksym;
 
 extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
 extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
-extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
-		int (callback_fn)(void *map, int *key, void *value),
-		unsigned int flags__k, void *aux__ign) __ksym;
-#define bpf_wq_set_callback(timer, cb, flags) \
-	bpf_wq_set_callback_impl(timer, cb, flags, NULL)
 
 struct bpf_iter_kmem_cache;
 extern int bpf_iter_kmem_cache_new(struct bpf_iter_kmem_cache *it) __weak __ksym;
diff --git a/tools/testing/selftests/bpf/progs/wq.c b/tools/testing/selftests/bpf/progs/wq.c
index 25be2cd9d42c..f265242b954d 100644
--- a/tools/testing/selftests/bpf/progs/wq.c
+++ b/tools/testing/selftests/bpf/progs/wq.c
@@ -107,7 +107,7 @@ static int test_hmap_elem_callback(void *map, int *key,
 	if (bpf_wq_init(wq, map, 0) != 0)
 		return -3;
 
-	if (bpf_wq_set_callback(wq, callback_fn, 0))
+	if (bpf_wq_set_callback_impl(wq, callback_fn, 0, NULL))
 		return -4;
 
 	if (bpf_wq_start(wq, 0))
diff --git a/tools/testing/selftests/bpf/progs/wq_failures.c b/tools/testing/selftests/bpf/progs/wq_failures.c
index d06f6d40594a..3767f5595bbc 100644
--- a/tools/testing/selftests/bpf/progs/wq_failures.c
+++ b/tools/testing/selftests/bpf/progs/wq_failures.c
@@ -97,7 +97,7 @@ __failure
 /* check that the first argument of bpf_wq_set_callback()
  * is a correct bpf_wq pointer.
  */
-__msg(": (85) call bpf_wq_set_callback_impl#") /* anchor message */
+__msg(": (85) call bpf_wq_set_callback#") /* anchor message */
 __msg("arg#0 doesn't point to a map value")
 long test_wrong_wq_pointer(void *ctx)
 {
@@ -123,7 +123,7 @@ __failure
 /* check that the first argument of bpf_wq_set_callback()
  * is a correct bpf_wq pointer.
  */
-__msg(": (85) call bpf_wq_set_callback_impl#") /* anchor message */
+__msg(": (85) call bpf_wq_set_callback#") /* anchor message */
 __msg("off 1 doesn't point to 'struct bpf_wq' that is at 0")
 long test_wrong_wq_pointer_offset(void *ctx)
 {
-- 
2.52.0


^ permalink raw reply related

* [PATCH bpf-next v1 07/10] HID: Use bpf_wq_set_callback kernel function
From: Ihor Solodrai @ 2026-01-09 18:48 UTC (permalink / raw)
  To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman
  Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
	Jiri Kosina, bpf, linux-kernel, linux-input, sched-ext
In-Reply-To: <20260109184852.1089786-1-ihor.solodrai@linux.dev>

Remove extern declaration of bpf_wq_set_callback_impl() from
hid_bpf_helpers.h and replace bpf_wq_set_callback macro with a
corresponding new declaration.

Fix selftests/hid build failure caused by missing BPF_CFLAGS.

Tested with:
  # append tools/testing/selftests/hid/config and build the kernel
  $ make -C tools/testing/selftests/hid
  # in built kernel
  $ ./tools/testing/selftests/hid/hid_bpf -t test_multiply_events_wq

  TAP version 13
  1..1
  # Starting 1 tests from 1 test cases.
  #  RUN           hid_bpf.test_multiply_events_wq ...
  [    2.575520] hid-generic 0003:0001:0A36.0001: hidraw0: USB HID v0.00 Device [test-uhid-device-138] on 138
  #            OK  hid_bpf.test_multiply_events_wq
  ok 1 hid_bpf.test_multiply_events_wq
  # PASSED: 1 / 1 tests passed.
  # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0
  PASS

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
 drivers/hid/bpf/progs/hid_bpf_helpers.h             | 8 +++-----
 tools/testing/selftests/hid/Makefile                | 4 +++-
 tools/testing/selftests/hid/progs/hid_bpf_helpers.h | 8 +++-----
 3 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/bpf/progs/hid_bpf_helpers.h b/drivers/hid/bpf/progs/hid_bpf_helpers.h
index bf19785a6b06..228f8d787567 100644
--- a/drivers/hid/bpf/progs/hid_bpf_helpers.h
+++ b/drivers/hid/bpf/progs/hid_bpf_helpers.h
@@ -33,11 +33,9 @@ extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx,
 /* bpf_wq implementation */
 extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
 extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
-extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
-		int (callback_fn)(void *map, int *key, void *value),
-		unsigned int flags__k, void *aux__ign) __ksym;
-#define bpf_wq_set_callback(wq, cb, flags) \
-	bpf_wq_set_callback_impl(wq, cb, flags, NULL)
+extern int bpf_wq_set_callback(struct bpf_wq *wq,
+		int (*callback_fn)(void *, int *, void *),
+		unsigned int flags) __weak __ksym;
 
 #define HID_MAX_DESCRIPTOR_SIZE	4096
 #define HID_IGNORE_EVENT	-1
diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index 2839d2612ce3..4c01bb649913 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -184,7 +184,9 @@ MENDIAN=$(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian)
 
 CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG))
 BPF_CFLAGS = -g -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) 		\
-	     -I$(INCLUDE_DIR)
+	     -I$(INCLUDE_DIR)						\
+	     -Wno-microsoft-anon-tag					\
+	     -fms-extensions
 
 CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \
 	       -Wno-compare-distinct-pointer-types
diff --git a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
index 531228b849da..80ab60905865 100644
--- a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
+++ b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
@@ -116,10 +116,8 @@ extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx,
 /* bpf_wq implementation */
 extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
 extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
-extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
-		int (callback_fn)(void *map, int *key, void *wq),
-		unsigned int flags__k, void *aux__ign) __weak __ksym;
-#define bpf_wq_set_callback(timer, cb, flags) \
-	bpf_wq_set_callback_impl(timer, cb, flags, NULL)
+extern int bpf_wq_set_callback(struct bpf_wq *wq,
+		int (*callback_fn)(void *, int *, void *),
+		unsigned int flags) __weak __ksym;
 
 #endif /* __HID_BPF_HELPERS_H */
-- 
2.52.0


^ permalink raw reply related

* [PATCH bpf-next v1 08/10] bpf: Add bpf_task_work_schedule_* kfuncs with KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-09 18:48 UTC (permalink / raw)
  To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman
  Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
	Jiri Kosina, bpf, linux-kernel, linux-input, sched-ext
In-Reply-To: <20260109184852.1089786-1-ihor.solodrai@linux.dev>

Implement bpf_task_work_schedule_* with an implicit bpf_prog_aux
argument, and change corresponding _impl funcs to call the new kfunc.

Update special kfunc checks in the verifier to accept both new and old
variants of the functions.

Update the selftests to use the new API with implicit argument.

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
 kernel/bpf/helpers.c                          | 28 +++++++++++++++----
 kernel/bpf/verifier.c                         |  8 +++++-
 .../testing/selftests/bpf/progs/file_reader.c |  4 ++-
 tools/testing/selftests/bpf/progs/task_work.c | 11 ++++++--
 .../selftests/bpf/progs/task_work_fail.c      | 16 ++++++++---
 .../selftests/bpf/progs/task_work_stress.c    |  5 ++--
 .../bpf/progs/verifier_async_cb_context.c     |  6 ++--
 7 files changed, 59 insertions(+), 19 deletions(-)

diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 23aa785c0f99..2e01973f2c18 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -4282,41 +4282,55 @@ static int bpf_task_work_schedule(struct task_struct *task, struct bpf_task_work
 }
 
 /**
- * bpf_task_work_schedule_signal_impl - Schedule BPF callback using task_work_add with TWA_SIGNAL
+ * bpf_task_work_schedule_signal - Schedule BPF callback using task_work_add with TWA_SIGNAL
  * mode
  * @task: Task struct for which callback should be scheduled
  * @tw: Pointer to struct bpf_task_work in BPF map value for internal bookkeeping
  * @map__map: bpf_map that embeds struct bpf_task_work in the values
  * @callback: pointer to BPF subprogram to call
- * @aux__prog: user should pass NULL
+ * @aux: pointer to bpf_prog_aux of the caller BPF program, implicitly set by the verifier
  *
  * Return: 0 if task work has been scheduled successfully, negative error code otherwise
  */
+__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
+					      void *map__map, bpf_task_work_callback_t callback,
+					      struct bpf_prog_aux *aux)
+{
+	return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_SIGNAL);
+}
+
 __bpf_kfunc int bpf_task_work_schedule_signal_impl(struct task_struct *task,
 						   struct bpf_task_work *tw, void *map__map,
 						   bpf_task_work_callback_t callback,
 						   void *aux__prog)
 {
-	return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_SIGNAL);
+	return bpf_task_work_schedule_signal(task, tw, map__map, callback, aux__prog);
 }
 
 /**
- * bpf_task_work_schedule_resume_impl - Schedule BPF callback using task_work_add with TWA_RESUME
+ * bpf_task_work_schedule_resume - Schedule BPF callback using task_work_add with TWA_RESUME
  * mode
  * @task: Task struct for which callback should be scheduled
  * @tw: Pointer to struct bpf_task_work in BPF map value for internal bookkeeping
  * @map__map: bpf_map that embeds struct bpf_task_work in the values
  * @callback: pointer to BPF subprogram to call
- * @aux__prog: user should pass NULL
+ * @aux: pointer to bpf_prog_aux of the caller BPF program, implicitly set by the verifier
  *
  * Return: 0 if task work has been scheduled successfully, negative error code otherwise
  */
+__bpf_kfunc int bpf_task_work_schedule_resume(struct task_struct *task, struct bpf_task_work *tw,
+					      void *map__map, bpf_task_work_callback_t callback,
+					      struct bpf_prog_aux *aux)
+{
+	return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_RESUME);
+}
+
 __bpf_kfunc int bpf_task_work_schedule_resume_impl(struct task_struct *task,
 						   struct bpf_task_work *tw, void *map__map,
 						   bpf_task_work_callback_t callback,
 						   void *aux__prog)
 {
-	return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_RESUME);
+	return bpf_task_work_schedule_resume(task, tw, map__map, callback, aux__prog);
 }
 
 static int make_file_dynptr(struct file *file, u32 flags, bool may_sleep,
@@ -4545,7 +4559,9 @@ BTF_ID_FLAGS(func, bpf_strncasestr);
 BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU)
 #endif
 BTF_ID_FLAGS(func, bpf_stream_vprintk_impl)
+BTF_ID_FLAGS(func, bpf_task_work_schedule_signal, KF_IMPLICIT_ARGS)
 BTF_ID_FLAGS(func, bpf_task_work_schedule_signal_impl)
+BTF_ID_FLAGS(func, bpf_task_work_schedule_resume, KF_IMPLICIT_ARGS)
 BTF_ID_FLAGS(func, bpf_task_work_schedule_resume_impl)
 BTF_ID_FLAGS(func, bpf_dynptr_from_file)
 BTF_ID_FLAGS(func, bpf_dynptr_file_discard)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index e5aeee554377..fdd17d19d5be 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -12471,6 +12471,8 @@ enum special_kfunc_type {
 	KF_bpf_arena_free_pages,
 	KF_bpf_arena_reserve_pages,
 	KF_bpf_wq_set_callback,
+	KF_bpf_task_work_schedule_signal,
+	KF_bpf_task_work_schedule_resume,
 };
 
 BTF_ID_LIST(special_kfunc_list)
@@ -12549,10 +12551,14 @@ BTF_ID(func, bpf_arena_alloc_pages)
 BTF_ID(func, bpf_arena_free_pages)
 BTF_ID(func, bpf_arena_reserve_pages)
 BTF_ID(func, bpf_wq_set_callback)
+BTF_ID(func, bpf_task_work_schedule_signal)
+BTF_ID(func, bpf_task_work_schedule_resume)
 
 static bool is_task_work_add_kfunc(u32 func_id)
 {
-	return func_id == special_kfunc_list[KF_bpf_task_work_schedule_signal_impl] ||
+	return func_id == special_kfunc_list[KF_bpf_task_work_schedule_signal] ||
+	       func_id == special_kfunc_list[KF_bpf_task_work_schedule_signal_impl] ||
+	       func_id == special_kfunc_list[KF_bpf_task_work_schedule_resume] ||
 	       func_id == special_kfunc_list[KF_bpf_task_work_schedule_resume_impl];
 }
 
diff --git a/tools/testing/selftests/bpf/progs/file_reader.c b/tools/testing/selftests/bpf/progs/file_reader.c
index 4d756b623557..ff3270a0cb9b 100644
--- a/tools/testing/selftests/bpf/progs/file_reader.c
+++ b/tools/testing/selftests/bpf/progs/file_reader.c
@@ -77,7 +77,9 @@ int on_open_validate_file_read(void *c)
 		err = 1;
 		return 0;
 	}
-	bpf_task_work_schedule_signal_impl(task, &work->tw, &arrmap, task_work_callback, NULL);
+
+	bpf_task_work_schedule_signal(task, &work->tw, &arrmap, task_work_callback);
+
 	return 0;
 }
 
diff --git a/tools/testing/selftests/bpf/progs/task_work.c b/tools/testing/selftests/bpf/progs/task_work.c
index 663a80990f8f..eec422af20b8 100644
--- a/tools/testing/selftests/bpf/progs/task_work.c
+++ b/tools/testing/selftests/bpf/progs/task_work.c
@@ -66,7 +66,8 @@ int oncpu_hash_map(struct pt_regs *args)
 	if (!work)
 		return 0;
 
-	bpf_task_work_schedule_resume_impl(task, &work->tw, &hmap, process_work, NULL);
+	bpf_task_work_schedule_resume(task, &work->tw, &hmap, process_work);
+
 	return 0;
 }
 
@@ -80,7 +81,9 @@ int oncpu_array_map(struct pt_regs *args)
 	work = bpf_map_lookup_elem(&arrmap, &key);
 	if (!work)
 		return 0;
-	bpf_task_work_schedule_signal_impl(task, &work->tw, &arrmap, process_work, NULL);
+
+	bpf_task_work_schedule_signal(task, &work->tw, &arrmap, process_work);
+
 	return 0;
 }
 
@@ -102,6 +105,8 @@ int oncpu_lru_map(struct pt_regs *args)
 	work = bpf_map_lookup_elem(&lrumap, &key);
 	if (!work || work->data[0])
 		return 0;
-	bpf_task_work_schedule_resume_impl(task, &work->tw, &lrumap, process_work, NULL);
+
+	bpf_task_work_schedule_resume(task, &work->tw, &lrumap, process_work);
+
 	return 0;
 }
diff --git a/tools/testing/selftests/bpf/progs/task_work_fail.c b/tools/testing/selftests/bpf/progs/task_work_fail.c
index 1270953fd092..557bdf9eb0fc 100644
--- a/tools/testing/selftests/bpf/progs/task_work_fail.c
+++ b/tools/testing/selftests/bpf/progs/task_work_fail.c
@@ -53,7 +53,9 @@ int mismatch_map(struct pt_regs *args)
 	work = bpf_map_lookup_elem(&arrmap, &key);
 	if (!work)
 		return 0;
-	bpf_task_work_schedule_resume_impl(task, &work->tw, &hmap, process_work, NULL);
+
+	bpf_task_work_schedule_resume(task, &work->tw, &hmap, process_work);
+
 	return 0;
 }
 
@@ -65,7 +67,9 @@ int no_map_task_work(struct pt_regs *args)
 	struct bpf_task_work tw;
 
 	task = bpf_get_current_task_btf();
-	bpf_task_work_schedule_resume_impl(task, &tw, &hmap, process_work, NULL);
+
+	bpf_task_work_schedule_resume(task, &tw, &hmap, process_work);
+
 	return 0;
 }
 
@@ -76,7 +80,9 @@ int task_work_null(struct pt_regs *args)
 	struct task_struct *task;
 
 	task = bpf_get_current_task_btf();
-	bpf_task_work_schedule_resume_impl(task, NULL, &hmap, process_work, NULL);
+
+	bpf_task_work_schedule_resume(task, NULL, &hmap, process_work);
+
 	return 0;
 }
 
@@ -91,6 +97,8 @@ int map_null(struct pt_regs *args)
 	work = bpf_map_lookup_elem(&arrmap, &key);
 	if (!work)
 		return 0;
-	bpf_task_work_schedule_resume_impl(task, &work->tw, NULL, process_work, NULL);
+
+	bpf_task_work_schedule_resume(task, &work->tw, NULL, process_work);
+
 	return 0;
 }
diff --git a/tools/testing/selftests/bpf/progs/task_work_stress.c b/tools/testing/selftests/bpf/progs/task_work_stress.c
index 55e555f7f41b..0cba36569714 100644
--- a/tools/testing/selftests/bpf/progs/task_work_stress.c
+++ b/tools/testing/selftests/bpf/progs/task_work_stress.c
@@ -51,8 +51,9 @@ int schedule_task_work(void *ctx)
 		if (!work)
 			return 0;
 	}
-	err = bpf_task_work_schedule_signal_impl(bpf_get_current_task_btf(), &work->tw, &hmap,
-						 process_work, NULL);
+	err = bpf_task_work_schedule_signal(bpf_get_current_task_btf(), &work->tw, &hmap,
+					    process_work);
+
 	if (err)
 		__sync_fetch_and_add(&schedule_error, 1);
 	else
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 7efa9521105e..6c50aff03baa 100644
--- a/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
+++ b/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
@@ -156,7 +156,8 @@ int task_work_non_sleepable_prog(void *ctx)
 	if (!task)
 		return 0;
 
-	bpf_task_work_schedule_resume_impl(task, &val->tw, &task_work_map, task_work_cb, NULL);
+	bpf_task_work_schedule_resume(task, &val->tw, &task_work_map, task_work_cb);
+
 	return 0;
 }
 
@@ -176,6 +177,7 @@ int task_work_sleepable_prog(void *ctx)
 	if (!task)
 		return 0;
 
-	bpf_task_work_schedule_resume_impl(task, &val->tw, &task_work_map, task_work_cb, NULL);
+	bpf_task_work_schedule_resume(task, &val->tw, &task_work_map, task_work_cb);
+
 	return 0;
 }
-- 
2.52.0


^ permalink raw reply related

* [PATCH bpf-next v1 09/10] bpf: Add bpf_stream_vprintk with KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-09 18:48 UTC (permalink / raw)
  To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman
  Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
	Jiri Kosina, bpf, linux-kernel, linux-input, sched-ext
In-Reply-To: <20260109184852.1089786-1-ihor.solodrai@linux.dev>

Implement bpf_stream_vprintk with an implicit bpf_prog_aux argument,
and change bpf_stream_vprintk_impl to call the new kfunc.

Update the selftests to use the new API with implicit argument.

bpf_stream_vprintk macro is changed to use the new bpf_stream_vprintk
kfunc, and the extern definition of bpf_stream_vprintk_impl is
replaced accordingly.

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
 kernel/bpf/helpers.c                            |  1 +
 kernel/bpf/stream.c                             | 11 ++++++++---
 tools/lib/bpf/bpf_helpers.h                     |  6 +++---
 tools/testing/selftests/bpf/progs/stream_fail.c |  6 +++---
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 2e01973f2c18..b35b78c08583 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -4558,6 +4558,7 @@ BTF_ID_FLAGS(func, bpf_strncasestr);
 #if defined(CONFIG_BPF_LSM) && defined(CONFIG_CGROUPS)
 BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU)
 #endif
+BTF_ID_FLAGS(func, bpf_stream_vprintk, KF_IMPLICIT_ARGS)
 BTF_ID_FLAGS(func, bpf_stream_vprintk_impl)
 BTF_ID_FLAGS(func, bpf_task_work_schedule_signal, KF_IMPLICIT_ARGS)
 BTF_ID_FLAGS(func, bpf_task_work_schedule_signal_impl)
diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
index 0b6bc3f30335..4e4713d9c771 100644
--- a/kernel/bpf/stream.c
+++ b/kernel/bpf/stream.c
@@ -212,14 +212,13 @@ __bpf_kfunc_start_defs();
  * Avoid using enum bpf_stream_id so that kfunc users don't have to pull in the
  * enum in headers.
  */
-__bpf_kfunc int bpf_stream_vprintk_impl(int stream_id, const char *fmt__str, const void *args,
-					u32 len__sz, void *aux__prog)
+__bpf_kfunc int bpf_stream_vprintk(int stream_id, const char *fmt__str, const void *args,
+				   u32 len__sz, struct bpf_prog_aux *aux)
 {
 	struct bpf_bprintf_data data = {
 		.get_bin_args	= true,
 		.get_buf	= true,
 	};
-	struct bpf_prog_aux *aux = aux__prog;
 	u32 fmt_size = strlen(fmt__str) + 1;
 	struct bpf_stream *stream;
 	u32 data_len = len__sz;
@@ -246,6 +245,12 @@ __bpf_kfunc int bpf_stream_vprintk_impl(int stream_id, const char *fmt__str, con
 	return ret;
 }
 
+__bpf_kfunc int bpf_stream_vprintk_impl(int stream_id, const char *fmt__str, const void *args,
+					u32 len__sz, void *aux__prog)
+{
+	return bpf_stream_vprintk(stream_id, fmt__str, args, len__sz, aux__prog);
+}
+
 __bpf_kfunc_end_defs();
 
 /* Added kfunc to common_btf_ids */
diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h
index d4e4e388e625..c145da05a67c 100644
--- a/tools/lib/bpf/bpf_helpers.h
+++ b/tools/lib/bpf/bpf_helpers.h
@@ -315,8 +315,8 @@ enum libbpf_tristate {
 			  ___param, sizeof(___param));		\
 })
 
-extern int bpf_stream_vprintk_impl(int stream_id, const char *fmt__str, const void *args,
-				   __u32 len__sz, void *aux__prog) __weak __ksym;
+extern int bpf_stream_vprintk(int stream_id, const char *fmt__str, const void *args,
+			      __u32 len__sz) __weak __ksym;
 
 #define bpf_stream_printk(stream_id, fmt, args...)					\
 ({											\
@@ -328,7 +328,7 @@ extern int bpf_stream_vprintk_impl(int stream_id, const char *fmt__str, const vo
 	___bpf_fill(___param, args);							\
 	_Pragma("GCC diagnostic pop")							\
 											\
-	bpf_stream_vprintk_impl(stream_id, ___fmt, ___param, sizeof(___param), NULL);	\
+	bpf_stream_vprintk(stream_id, ___fmt, ___param, sizeof(___param));		\
 })
 
 /* Use __bpf_printk when bpf_printk call has 3 or fewer fmt args
diff --git a/tools/testing/selftests/bpf/progs/stream_fail.c b/tools/testing/selftests/bpf/progs/stream_fail.c
index 3662515f0107..8e8249f3521c 100644
--- a/tools/testing/selftests/bpf/progs/stream_fail.c
+++ b/tools/testing/selftests/bpf/progs/stream_fail.c
@@ -10,7 +10,7 @@ SEC("syscall")
 __failure __msg("Possibly NULL pointer passed")
 int stream_vprintk_null_arg(void *ctx)
 {
-	bpf_stream_vprintk_impl(BPF_STDOUT, "", NULL, 0, NULL);
+	bpf_stream_vprintk(BPF_STDOUT, "", NULL, 0);
 	return 0;
 }
 
@@ -18,7 +18,7 @@ SEC("syscall")
 __failure __msg("R3 type=scalar expected=")
 int stream_vprintk_scalar_arg(void *ctx)
 {
-	bpf_stream_vprintk_impl(BPF_STDOUT, "", (void *)46, 0, NULL);
+	bpf_stream_vprintk(BPF_STDOUT, "", (void *)46, 0);
 	return 0;
 }
 
@@ -26,7 +26,7 @@ SEC("syscall")
 __failure __msg("arg#1 doesn't point to a const string")
 int stream_vprintk_string_arg(void *ctx)
 {
-	bpf_stream_vprintk_impl(BPF_STDOUT, ctx, NULL, 0, NULL);
+	bpf_stream_vprintk(BPF_STDOUT, ctx, NULL, 0);
 	return 0;
 }
 
-- 
2.52.0


^ permalink raw reply related

* [PATCH bpf-next v1 10/10] bpf,docs: Document KF_IMPLICIT_ARGS flag
From: Ihor Solodrai @ 2026-01-09 18:48 UTC (permalink / raw)
  To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman
  Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
	Jiri Kosina, bpf, linux-kernel, linux-input, sched-ext
In-Reply-To: <20260109184852.1089786-1-ihor.solodrai@linux.dev>

Add sections explaining KF_IMPLICIT_ARGS kfunc flag. Mark __prog
annotation as deprecated.

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
 Documentation/bpf/kfuncs.rst | 44 +++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst
index 3eb59a8f9f34..b849598271d2 100644
--- a/Documentation/bpf/kfuncs.rst
+++ b/Documentation/bpf/kfuncs.rst
@@ -232,7 +232,7 @@ Or::
                 ...
         }
 
-2.3.6 __prog Annotation
+2.3.6 __prog Annotation (deprecated, use KF_IMPLICIT_ARGS instead)
 ---------------------------
 This annotation is used to indicate that the argument needs to be fixed up to
 the bpf_prog_aux of the caller BPF program. Any value passed into this argument
@@ -381,6 +381,48 @@ encouraged to make their use-cases known as early as possible, and participate
 in upstream discussions regarding whether to keep, change, deprecate, or remove
 those kfuncs if and when such discussions occur.
 
+2.5.9 KF_IMPLICIT_ARGS flag
+------------------------------------
+
+The KF_IMPLICIT_ARGS flag is used to indicate that the BPF signature
+of the kfunc is different from it's kernel signature, and the values
+for implicit arguments are provided at load time by the verifier.
+
+Only arguments of specific types are implicit.
+Currently only ``struct bpf_prog_aux *`` type is supported.
+
+A kfunc with KF_IMPLICIT_ARGS flag therefore has two types in BTF: one
+function matching the kernel declaration (with _impl suffix in the
+name by convention), and another matching the intended BPF API.
+
+Verifier only allows calls to the non-_impl version of a kfunc, that
+uses a signature without the implicit arguments.
+
+Example declaration:
+
+.. code-block:: c
+
+	__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
+						      void *map__map, bpf_task_work_callback_t callback,
+						      struct bpf_prog_aux *aux) { ... }
+
+Example usage in BPF program:
+
+.. code-block:: c
+
+	/* note that the last argument is omitted */
+        bpf_task_work_schedule_signal(task, &work->tw, &arrmap, task_work_callback);
+
+An exception to this are kfuncs that use __prog argument, and were
+implemented before KF_IMPLICIT_ARGS mechanism was introduced:
+  * bpf_stream_vprintk_impl
+  * bpf_task_work_schedule_resume_impl
+  * bpf_task_work_schedule_signal_impl
+  * bpf_wq_set_callback_impl
+
+These are allowed for backwards compatibility, however BPF programs
+should use newer API that omits implicit arguments in BPF.
+
 2.6 Registering the kfuncs
 --------------------------
 
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH bpf-next v1 04/10] resolve_btfids: Support for KF_IMPLICIT_ARGS
From: bot+bpf-ci @ 2026-01-09 19:15 UTC (permalink / raw)
  To: ihor.solodrai, ast, andrii, daniel, martin.lau, eddyz87
  Cc: yatsenko, tj, alan.maguire, bentiss, jikos, bpf, linux-kernel,
	linux-input, sched-ext, ast, andrii, daniel, martin.lau, eddyz87,
	yonghong.song, clm, ihor.solodrai
In-Reply-To: <20260109184852.1089786-5-ihor.solodrai@linux.dev>

[-- Attachment #1: Type: text/plain, Size: 1417 bytes --]

> diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
> index df39982f51df..b361e726fa36 100644
> --- a/tools/bpf/resolve_btfids/main.c
> +++ b/tools/bpf/resolve_btfids/main.c

[ ... ]

> +static s64 btf__collect_decl_tags(const struct btf *btf, s32 *decl_tags, u32 decl_tags_sz)
> +{
> +	const u32 type_cnt = btf__type_cnt(btf);
> +	const struct btf_type *t;
> +	s64 nr_decl_tags = 0;
> +
> +	for (u32 id = 1; id < type_cnt; id++) {
> +		t = btf__type_by_id(btf, id);
> +		if (!btf_is_decl_tag(t))
> +			continue;
> +		if (nr_decl_tags >= decl_tags_sz) {
> +			pr_err("ERROR: resolve_btfids: too many decl tags in BTF - limit %s\n",
> +				decl_tags_sz);
                                ^^^^^^^^^^^^^^^^^

Should this be %u instead of %s? The decl_tags_sz parameter is a u32, but
the format specifier %s expects a string pointer. When the error path is
triggered (more than MAX_DECL_TAGS decl tags in BTF), this will cause
undefined behavior as printf tries to interpret the integer value as a
memory address to read a string from.

> +			return -E2BIG;
> +		}
> +		decl_tags[nr_decl_tags++] = id;
> +	}
> +
> +	return nr_decl_tags;
> +}

[ ... ]


---
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/20862592244

^ permalink raw reply

* Re: [PATCH bpf-next v1 04/10] resolve_btfids: Support for KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-09 19:34 UTC (permalink / raw)
  To: bot+bpf-ci, ast, andrii, daniel, martin.lau, eddyz87
  Cc: yatsenko, tj, alan.maguire, bentiss, jikos, bpf, linux-kernel,
	linux-input, sched-ext, martin.lau, yonghong.song, clm
In-Reply-To: <614a1ac62ade1a2c93f3669dea78d37d1fba159f1f00e79c5e8047047a772d75@mail.kernel.org>

On 1/9/26 11:15 AM, bot+bpf-ci@kernel.org wrote:
>> diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
>> index df39982f51df..b361e726fa36 100644
>> --- a/tools/bpf/resolve_btfids/main.c
>> +++ b/tools/bpf/resolve_btfids/main.c
> 
> [ ... ]
> 
>> +static s64 btf__collect_decl_tags(const struct btf *btf, s32 *decl_tags, u32 decl_tags_sz)
>> +{
>> +	const u32 type_cnt = btf__type_cnt(btf);
>> +	const struct btf_type *t;
>> +	s64 nr_decl_tags = 0;
>> +
>> +	for (u32 id = 1; id < type_cnt; id++) {
>> +		t = btf__type_by_id(btf, id);
>> +		if (!btf_is_decl_tag(t))
>> +			continue;
>> +		if (nr_decl_tags >= decl_tags_sz) {
>> +			pr_err("ERROR: resolve_btfids: too many decl tags in BTF - limit %s\n",
>> +				decl_tags_sz);
>                                 ^^^^^^^^^^^^^^^^^
> 
> Should this be %u instead of %s? The decl_tags_sz parameter is a u32, but
> the format specifier %s expects a string pointer. When the error path is
> triggered (more than MAX_DECL_TAGS decl tags in BTF), this will cause
> undefined behavior as printf tries to interpret the integer value as a
> memory address to read a string from.

Correct, it should be %u or %d.

> 
>> +			return -E2BIG;
>> +		}
>> +		decl_tags[nr_decl_tags++] = id;
>> +	}
>> +
>> +	return nr_decl_tags;
>> +}
> 
> [ ... ]
> 
> 
> ---
> 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/20862592244


^ permalink raw reply

* Re: [PATCH bpf-next v1 03/10] bpf: Verifier support for KF_IMPLICIT_ARGS
From: Alexei Starovoitov @ 2026-01-09 19:54 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, LKML,
	open list:HID CORE LAYER, sched-ext
In-Reply-To: <20260109184852.1089786-4-ihor.solodrai@linux.dev>

On Fri, Jan 9, 2026 at 10:49 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> +       if (unlikely(kfunc_flags && KF_IMPLICIT_ARGS & *kfunc_flags))

Please add extra () around &

that's the style we use elsewhere. Like:
if (!first && (env->log.level & BPF_LOG_LEVEL2))

> +               if (unlikely(KF_IMPLICIT_ARGS & meta.kfunc_flags
> +                               && is_kfunc_arg_implicit(desc_btf, &args[i])))

same

pw-bot: cr

^ permalink raw reply

* Re: [PATCH bpf-next v1 08/10] bpf: Add bpf_task_work_schedule_* kfuncs with KF_IMPLICIT_ARGS
From: Alexei Starovoitov @ 2026-01-09 19:58 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, LKML,
	open list:HID CORE LAYER, sched-ext
In-Reply-To: <20260109184852.1089786-9-ihor.solodrai@linux.dev>

On Fri, Jan 9, 2026 at 10:50 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> +__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
> +                                             void *map__map, bpf_task_work_callback_t callback,
> +                                             struct bpf_prog_aux *aux)
> +{
> +       return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_SIGNAL);
> +}
> +
>  __bpf_kfunc int bpf_task_work_schedule_signal_impl(struct task_struct *task,
>                                                    struct bpf_task_work *tw, void *map__map,
>                                                    bpf_task_work_callback_t callback,
>                                                    void *aux__prog)
>  {
> -       return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_SIGNAL);
> +       return bpf_task_work_schedule_signal(task, tw, map__map, callback, aux__prog);
>  }

I thought we decided that _impl() will not be marked as __bpf_kfunc
and will not be in BTF_ID(func, _impl).
We can mark it as __weak noinline and it will be in kallsyms.
That's all we need for the verifier and resolve_btfid, no?

Sorry, it's been a long time. I must have forgotten something.

^ permalink raw reply

* Re: [PATCH bpf-next v1 08/10] bpf: Add bpf_task_work_schedule_* kfuncs with KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-09 20:02 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, LKML,
	open list:HID CORE LAYER, sched-ext
In-Reply-To: <CAADnVQJDv80_T+1jz=7_8y+8hRTjMqqkm38in2er8iRU-p9W+g@mail.gmail.com>

On 1/9/26 11:58 AM, Alexei Starovoitov wrote:
> On Fri, Jan 9, 2026 at 10:50 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>>
>> +__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
>> +                                             void *map__map, bpf_task_work_callback_t callback,
>> +                                             struct bpf_prog_aux *aux)
>> +{
>> +       return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_SIGNAL);
>> +}
>> +
>>  __bpf_kfunc int bpf_task_work_schedule_signal_impl(struct task_struct *task,
>>                                                    struct bpf_task_work *tw, void *map__map,
>>                                                    bpf_task_work_callback_t callback,
>>                                                    void *aux__prog)
>>  {
>> -       return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_SIGNAL);
>> +       return bpf_task_work_schedule_signal(task, tw, map__map, callback, aux__prog);
>>  }
> 
> I thought we decided that _impl() will not be marked as __bpf_kfunc
> and will not be in BTF_ID(func, _impl).
> We can mark it as __weak noinline and it will be in kallsyms.
> That's all we need for the verifier and resolve_btfid, no?
> 
> Sorry, it's been a long time. I must have forgotten something.

For the *generated* _impl kfuncs there is no decl tags and the ids are
absent from BTF_ID sets, yes.

However for the "legacy" cases it must be there for backwards
compatibility, as well as relevant verifier checks.

^ permalink raw reply

* Re: [PATCH bpf-next v1 08/10] bpf: Add bpf_task_work_schedule_* kfuncs with KF_IMPLICIT_ARGS
From: Alexei Starovoitov @ 2026-01-09 20:47 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, LKML,
	open list:HID CORE LAYER, sched-ext
In-Reply-To: <b099a95e-5e69-4eeb-a2c9-9a52b8042a85@linux.dev>

On Fri, Jan 9, 2026 at 12:02 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> On 1/9/26 11:58 AM, Alexei Starovoitov wrote:
> > On Fri, Jan 9, 2026 at 10:50 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
> >>
> >> +__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
> >> +                                             void *map__map, bpf_task_work_callback_t callback,
> >> +                                             struct bpf_prog_aux *aux)
> >> +{
> >> +       return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_SIGNAL);
> >> +}
> >> +
> >>  __bpf_kfunc int bpf_task_work_schedule_signal_impl(struct task_struct *task,
> >>                                                    struct bpf_task_work *tw, void *map__map,
> >>                                                    bpf_task_work_callback_t callback,
> >>                                                    void *aux__prog)
> >>  {
> >> -       return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_SIGNAL);
> >> +       return bpf_task_work_schedule_signal(task, tw, map__map, callback, aux__prog);
> >>  }
> >
> > I thought we decided that _impl() will not be marked as __bpf_kfunc
> > and will not be in BTF_ID(func, _impl).
> > We can mark it as __weak noinline and it will be in kallsyms.
> > That's all we need for the verifier and resolve_btfid, no?
> >
> > Sorry, it's been a long time. I must have forgotten something.
>
> For the *generated* _impl kfuncs there is no decl tags and the ids are
> absent from BTF_ID sets, yes.
>
> However for the "legacy" cases it must be there for backwards
> compatibility, as well as relevant verifier checks.

I see.
I feel bpf_task_work_schedule_resume() is ok to break, since it's so new.
We can remove bpf_task_work_schedule_[resume|singal]_impl()
to avoid carrying forward forever.

bpf_stream_vprintk_impl() is not that clear. I would remove it too.

^ permalink raw reply

* Re: [PATCH bpf-next v1 07/10] HID: Use bpf_wq_set_callback kernel function
From: Benjamin Tissoires @ 2026-01-09 21:34 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Jiri Kosina, bpf, linux-kernel, linux-input,
	sched-ext
In-Reply-To: <20260109184852.1089786-8-ihor.solodrai@linux.dev>

On Jan 09 2026, Ihor Solodrai wrote:
> Remove extern declaration of bpf_wq_set_callback_impl() from
> hid_bpf_helpers.h and replace bpf_wq_set_callback macro with a
> corresponding new declaration.
> 
> Fix selftests/hid build failure caused by missing BPF_CFLAGS.

Already fixed in e03fb369b083 ("selftests/hid: fix bpf compilations due to -fms-extensions")

> 
> Tested with:
>   # append tools/testing/selftests/hid/config and build the kernel
>   $ make -C tools/testing/selftests/hid
>   # in built kernel
>   $ ./tools/testing/selftests/hid/hid_bpf -t test_multiply_events_wq
> 
>   TAP version 13
>   1..1
>   # Starting 1 tests from 1 test cases.
>   #  RUN           hid_bpf.test_multiply_events_wq ...
>   [    2.575520] hid-generic 0003:0001:0A36.0001: hidraw0: USB HID v0.00 Device [test-uhid-device-138] on 138
>   #            OK  hid_bpf.test_multiply_events_wq
>   ok 1 hid_bpf.test_multiply_events_wq
>   # PASSED: 1 / 1 tests passed.
>   # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0
>   PASS
> 
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
> ---
>  drivers/hid/bpf/progs/hid_bpf_helpers.h             | 8 +++-----
>  tools/testing/selftests/hid/Makefile                | 4 +++-
>  tools/testing/selftests/hid/progs/hid_bpf_helpers.h | 8 +++-----
>  3 files changed, 9 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/hid/bpf/progs/hid_bpf_helpers.h b/drivers/hid/bpf/progs/hid_bpf_helpers.h
> index bf19785a6b06..228f8d787567 100644
> --- a/drivers/hid/bpf/progs/hid_bpf_helpers.h
> +++ b/drivers/hid/bpf/progs/hid_bpf_helpers.h
> @@ -33,11 +33,9 @@ extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx,
>  /* bpf_wq implementation */
>  extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
>  extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
> -extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
> -		int (callback_fn)(void *map, int *key, void *value),
> -		unsigned int flags__k, void *aux__ign) __ksym;
> -#define bpf_wq_set_callback(wq, cb, flags) \
> -	bpf_wq_set_callback_impl(wq, cb, flags, NULL)
> +extern int bpf_wq_set_callback(struct bpf_wq *wq,
> +		int (*callback_fn)(void *, int *, void *),
> +		unsigned int flags) __weak __ksym;

FWIW, if I'm the only one using bpf_wq_set_callback_impl() that you are
aware of, I'm fine removing the _impl kfunc from the kernel, I can deal
with this when loading the programs.

>  
>  #define HID_MAX_DESCRIPTOR_SIZE	4096
>  #define HID_IGNORE_EVENT	-1
> diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
> index 2839d2612ce3..4c01bb649913 100644
> --- a/tools/testing/selftests/hid/Makefile
> +++ b/tools/testing/selftests/hid/Makefile
> @@ -184,7 +184,9 @@ MENDIAN=$(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian)
>  
>  CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG))
>  BPF_CFLAGS = -g -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) 		\
> -	     -I$(INCLUDE_DIR)
> +	     -I$(INCLUDE_DIR)						\
> +	     -Wno-microsoft-anon-tag					\
> +	     -fms-extensions

Already in Linus' tree.

>  
>  CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \
>  	       -Wno-compare-distinct-pointer-types
> diff --git a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
> index 531228b849da..80ab60905865 100644
> --- a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
> +++ b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
> @@ -116,10 +116,8 @@ extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx,
>  /* bpf_wq implementation */
>  extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
>  extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
> -extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
> -		int (callback_fn)(void *map, int *key, void *wq),
> -		unsigned int flags__k, void *aux__ign) __weak __ksym;
> -#define bpf_wq_set_callback(timer, cb, flags) \
> -	bpf_wq_set_callback_impl(timer, cb, flags, NULL)
> +extern int bpf_wq_set_callback(struct bpf_wq *wq,
> +		int (*callback_fn)(void *, int *, void *),
> +		unsigned int flags) __weak __ksym;
>  
>  #endif /* __HID_BPF_HELPERS_H */
> -- 
> 2.52.0
> 

Acked-by: Benjamin Tissoires <bentiss@kernel.org>

Cheers,
Benjamin

^ permalink raw reply

* Re: [PATCH bpf-next v1 08/10] bpf: Add bpf_task_work_schedule_* kfuncs with KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-09 21:39 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, LKML,
	open list:HID CORE LAYER, sched-ext
In-Reply-To: <CAADnVQ+_AmiwuupkVJTGyKY3KOp68GLuivs2LMEr0M_yaHPUUg@mail.gmail.com>

On 1/9/26 12:47 PM, Alexei Starovoitov wrote:
> On Fri, Jan 9, 2026 at 12:02 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>>
>> On 1/9/26 11:58 AM, Alexei Starovoitov wrote:
>>> On Fri, Jan 9, 2026 at 10:50 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>>>>
>>>> +__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
>>>> +                                             void *map__map, bpf_task_work_callback_t callback,
>>>> +                                             struct bpf_prog_aux *aux)
>>>> +{
>>>> +       return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_SIGNAL);
>>>> +}
>>>> +
>>>>  __bpf_kfunc int bpf_task_work_schedule_signal_impl(struct task_struct *task,
>>>>                                                    struct bpf_task_work *tw, void *map__map,
>>>>                                                    bpf_task_work_callback_t callback,
>>>>                                                    void *aux__prog)
>>>>  {
>>>> -       return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_SIGNAL);
>>>> +       return bpf_task_work_schedule_signal(task, tw, map__map, callback, aux__prog);
>>>>  }
>>>
>>> I thought we decided that _impl() will not be marked as __bpf_kfunc
>>> and will not be in BTF_ID(func, _impl).
>>> We can mark it as __weak noinline and it will be in kallsyms.
>>> That's all we need for the verifier and resolve_btfid, no?
>>>
>>> Sorry, it's been a long time. I must have forgotten something.
>>
>> For the *generated* _impl kfuncs there is no decl tags and the ids are
>> absent from BTF_ID sets, yes.
>>
>> However for the "legacy" cases it must be there for backwards
>> compatibility, as well as relevant verifier checks.
> 
> I see.
> I feel bpf_task_work_schedule_resume() is ok to break, since it's so new.
> We can remove bpf_task_work_schedule_[resume|singal]_impl()
> to avoid carrying forward forever.
> 
> bpf_stream_vprintk_impl() is not that clear. I would remove it too.

That leaves only bpf_wq_set_callback_impl(). Can we break that too?

Then there won't be legacy cases at all. It was introduced in v6.16
along the with __prog suffix [1][2].

If we go this route, we could clean up __prog support/docs too.

I think it's worth it to make an "all or nothing" decision here:
either break all 4 existing kfuncs, or backwards-support all of them.

git tag --contains bc049387b41f | grep -v rc
v6.16
v6.17
v6.18

[1] https://lore.kernel.org/all/20250513142812.1021591-1-memxor@gmail.com/
[2] https://lore.kernel.org/all/20240420-bpf_wq-v2-13-6c986a5a741f@kernel.org/



^ permalink raw reply

* Re: [PATCH bpf-next v1 08/10] bpf: Add bpf_task_work_schedule_* kfuncs with KF_IMPLICIT_ARGS
From: Alexei Starovoitov @ 2026-01-09 21:49 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, LKML,
	open list:HID CORE LAYER, sched-ext
In-Reply-To: <0c4d84ab-1725-45bc-9c1c-8bdc1f5fc032@linux.dev>

On Fri, Jan 9, 2026 at 1:39 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> On 1/9/26 12:47 PM, Alexei Starovoitov wrote:
> > On Fri, Jan 9, 2026 at 12:02 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
> >>
> >> On 1/9/26 11:58 AM, Alexei Starovoitov wrote:
> >>> On Fri, Jan 9, 2026 at 10:50 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
> >>>>
> >>>> +__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
> >>>> +                                             void *map__map, bpf_task_work_callback_t callback,
> >>>> +                                             struct bpf_prog_aux *aux)
> >>>> +{
> >>>> +       return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_SIGNAL);
> >>>> +}
> >>>> +
> >>>>  __bpf_kfunc int bpf_task_work_schedule_signal_impl(struct task_struct *task,
> >>>>                                                    struct bpf_task_work *tw, void *map__map,
> >>>>                                                    bpf_task_work_callback_t callback,
> >>>>                                                    void *aux__prog)
> >>>>  {
> >>>> -       return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_SIGNAL);
> >>>> +       return bpf_task_work_schedule_signal(task, tw, map__map, callback, aux__prog);
> >>>>  }
> >>>
> >>> I thought we decided that _impl() will not be marked as __bpf_kfunc
> >>> and will not be in BTF_ID(func, _impl).
> >>> We can mark it as __weak noinline and it will be in kallsyms.
> >>> That's all we need for the verifier and resolve_btfid, no?
> >>>
> >>> Sorry, it's been a long time. I must have forgotten something.
> >>
> >> For the *generated* _impl kfuncs there is no decl tags and the ids are
> >> absent from BTF_ID sets, yes.
> >>
> >> However for the "legacy" cases it must be there for backwards
> >> compatibility, as well as relevant verifier checks.
> >
> > I see.
> > I feel bpf_task_work_schedule_resume() is ok to break, since it's so new.
> > We can remove bpf_task_work_schedule_[resume|singal]_impl()
> > to avoid carrying forward forever.
> >
> > bpf_stream_vprintk_impl() is not that clear. I would remove it too.
>
> That leaves only bpf_wq_set_callback_impl(). Can we break that too?

Sounds like Benjamin is ok removing it.
So I think we can indeed remove them all.

> Then there won't be legacy cases at all. It was introduced in v6.16
> along the with __prog suffix [1][2].
>
> If we go this route, we could clean up __prog support/docs too.
>
> I think it's worth it to make an "all or nothing" decision here:
> either break all 4 existing kfuncs, or backwards-support all of them.

I don't see why "all or nothing" is a good thing.
It won't be "all" anyway.
We have bpf_rbtree_add_impl(), bpf_list_push_front_impl(), etc.
And those we cannot remove. sched-ext is using them.
Another few categories are bpf_obj_new_impl(), bpf_obj_drop_impl().
There are not __prog type, but conceptually the same thing and
KF_IMPLICIT_ARGS should support them too eventually.


> git tag --contains bc049387b41f | grep -v rc
> v6.16
> v6.17
> v6.18
>
> [1] https://lore.kernel.org/all/20250513142812.1021591-1-memxor@gmail.com/
> [2] https://lore.kernel.org/all/20240420-bpf_wq-v2-13-6c986a5a741f@kernel.org/
>
>

^ permalink raw reply

* Re: [PATCH bpf-next v1 08/10] bpf: Add bpf_task_work_schedule_* kfuncs with KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-09 21:56 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, LKML,
	open list:HID CORE LAYER, sched-ext
In-Reply-To: <CAADnVQ+k-nbq-2PGRSPJDRZ3G9sp9zu3Owqsj7zqO_G+3OQEww@mail.gmail.com>

On 1/9/26 1:49 PM, Alexei Starovoitov wrote:
> On Fri, Jan 9, 2026 at 1:39 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>>
>> On 1/9/26 12:47 PM, Alexei Starovoitov wrote:
>>> On Fri, Jan 9, 2026 at 12:02 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>>>>
>>>> On 1/9/26 11:58 AM, Alexei Starovoitov wrote:
>>>>> On Fri, Jan 9, 2026 at 10:50 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>>>>>>
>>>>>> +__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
>>>>>> +                                             void *map__map, bpf_task_work_callback_t callback,
>>>>>> +                                             struct bpf_prog_aux *aux)
>>>>>> +{
>>>>>> +       return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_SIGNAL);
>>>>>> +}
>>>>>> +
>>>>>>  __bpf_kfunc int bpf_task_work_schedule_signal_impl(struct task_struct *task,
>>>>>>                                                    struct bpf_task_work *tw, void *map__map,
>>>>>>                                                    bpf_task_work_callback_t callback,
>>>>>>                                                    void *aux__prog)
>>>>>>  {
>>>>>> -       return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_SIGNAL);
>>>>>> +       return bpf_task_work_schedule_signal(task, tw, map__map, callback, aux__prog);
>>>>>>  }
>>>>>
>>>>> I thought we decided that _impl() will not be marked as __bpf_kfunc
>>>>> and will not be in BTF_ID(func, _impl).
>>>>> We can mark it as __weak noinline and it will be in kallsyms.
>>>>> That's all we need for the verifier and resolve_btfid, no?
>>>>>
>>>>> Sorry, it's been a long time. I must have forgotten something.
>>>>
>>>> For the *generated* _impl kfuncs there is no decl tags and the ids are
>>>> absent from BTF_ID sets, yes.
>>>>
>>>> However for the "legacy" cases it must be there for backwards
>>>> compatibility, as well as relevant verifier checks.
>>>
>>> I see.
>>> I feel bpf_task_work_schedule_resume() is ok to break, since it's so new.
>>> We can remove bpf_task_work_schedule_[resume|singal]_impl()
>>> to avoid carrying forward forever.
>>>
>>> bpf_stream_vprintk_impl() is not that clear. I would remove it too.
>>
>> That leaves only bpf_wq_set_callback_impl(). Can we break that too?
> 
> Sounds like Benjamin is ok removing it.
> So I think we can indeed remove them all.
> 
>> Then there won't be legacy cases at all. It was introduced in v6.16
>> along the with __prog suffix [1][2].
>>
>> If we go this route, we could clean up __prog support/docs too.
>>
>> I think it's worth it to make an "all or nothing" decision here:
>> either break all 4 existing kfuncs, or backwards-support all of them.
> 
> I don't see why "all or nothing" is a good thing.
> It won't be "all" anyway.
> We have bpf_rbtree_add_impl(), bpf_list_push_front_impl(), etc.
> And those we cannot remove. sched-ext is using them.
> Another few categories are bpf_obj_new_impl(), bpf_obj_drop_impl().
> There are not __prog type, but conceptually the same thing and
> KF_IMPLICIT_ARGS should support them too eventually.

I was thinking we could remove/simplify code relevant to backwards
compat of existing _impl kfuncs. But you're right, if we start using
implicit args for other types/kfuncs, the "legacy" case still has to
work.

Ok, in the next revision I'll remove all the __prog users, but leave
the "legacy" case support in place for future use.

> 
> 
>> git tag --contains bc049387b41f | grep -v rc
>> v6.16
>> v6.17
>> v6.18
>>
>> [1] https://lore.kernel.org/all/20250513142812.1021591-1-memxor@gmail.com/
>> [2] https://lore.kernel.org/all/20240420-bpf_wq-v2-13-6c986a5a741f@kernel.org/
>>
>>


^ permalink raw reply

* Re: [PATCH bpf-next v1 03/10] bpf: Verifier support for KF_IMPLICIT_ARGS
From: Andrii Nakryiko @ 2026-01-09 23:25 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, linux-kernel,
	linux-input, sched-ext
In-Reply-To: <20260109184852.1089786-4-ihor.solodrai@linux.dev>

On Fri, Jan 9, 2026 at 10:49 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> A kernel function bpf_foo marked with KF_IMPLICIT_ARGS flag is
> expected to have two associated types in BTF:
>   * `bpf_foo` with a function prototype that omits implicit arguments
>   * `bpf_foo_impl` with a function prototype that matches the kernel
>      declaration of `bpf_foo`, but doesn't have a ksym associated with
>      its name
>
> In order to support kfuncs with implicit arguments, the verifier has
> to know how to resolve a call of `bpf_foo` to the correct BTF function
> prototype and address.
>
> To implement this, in add_kfunc_call() kfunc flags are checked for
> KF_IMPLICIT_ARGS. For such kfuncs a BTF func prototype is adjusted to
> the one found for `bpf_foo_impl` (func_name + "_impl" suffix, by
> convention) function in BTF.
>
> This effectively changes the signature of the `bpf_foo` kfunc in the
> context of verification: from one without implicit args to the one
> with full argument list.
>
> Whether a kfunc argument is implicit or not is determined by
> is_kfunc_arg_implicit(). The values of implicit arguments by design
> are provided by the verifier, and so they can only be of particular
> types. In this patch the only allowed implicit arg type is a pointer
> to struct bpf_prog_aux. The __prog args (usually void *) are also
> considered implicit for backwards compatibility.
>
> In order to enable the verifier to correctly set an implicit
> bpf_prog_aux arg value at runtime, is_kfunc_arg_prog() is extended to
> check for the arg type. At a point when prog arg is determined in
> check_kfunc_args() the kfunc with implicit args already has a
> prototype with full argument list, so the existing value patch
> mechanism just works.
>
> If a new kfunc with KF_IMPLICIT_ARG is declared for an existing kfunc
> that uses a __prog argument (a legacy case), the prototype
> substitution works in exactly the same way, assuming the kfunc follows
> the _impl naming convention. The difference is only in how _impl
> prototype is added to the BTF, which is not the verifier's
> concern. See a subsequent resolve_btfids patch for details.
>
> In check_kfunc_call() reset the subreg_def of registers holding
> implicit arguments to correctly track zero extensions.
>
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
> ---
>  include/linux/btf.h   |  1 +
>  kernel/bpf/verifier.c | 70 +++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 69 insertions(+), 2 deletions(-)
>

[...]

> +       impl_id = btf_find_by_name_kind(btf, impl_name, BTF_KIND_FUNC);
> +       if (impl_id <= 0) {
> +               verbose(env, "cannot find function %s in BTF\n", impl_name);
> +               return NULL;
> +       }
> +
> +       func = btf_type_by_id(btf, impl_id);
> +       if (!func || !btf_type_is_func(func)) {

btf_find_by_name_kind() above guarantees that we both will have
non-NULL func and it will be BTF_KIND_FUNC, drop these defensive
checks.

> +               verbose(env, "%s (btf_id %d) is not a function\n", impl_name, impl_id);
> +               return NULL;
> +       }
> +
> +       return btf_type_by_id(btf, func->type);
> +}
> +
>  static int fetch_kfunc_meta(struct bpf_verifier_env *env,
>                             s32 func_id,
>                             s16 offset,
> @@ -3308,7 +3340,16 @@ static int fetch_kfunc_meta(struct bpf_verifier_env *env,
>         }
>
>         func_name = btf_name_by_offset(btf, func->name_off);
> -       func_proto = btf_type_by_id(btf, func->type);
> +
> +       /*
> +        * An actual prototype of a kfunc with KF_IMPLICIT_ARGS flag
> +        * can be found through the counterpart _impl kfunc.
> +        */
> +       if (unlikely(kfunc_flags && KF_IMPLICIT_ARGS & *kfunc_flags))

drop unlikely(), it's unnecessary micro-optimization (if at all)

(I'd also swap order to more conventional: `*kfunc_flags & KF_IMPLICIT_ARGS`)

> +               func_proto = find_kfunc_impl_proto(env, btf, func_name);
> +       else
> +               func_proto = btf_type_by_id(btf, func->type);
> +
>         if (!func_proto || !btf_type_is_func_proto(func_proto)) {
>                 verbose(env, "kernel function btf_id %d does not have a valid func_proto\n",
>                         func_id);

[...]

> @@ -14303,6 +14358,17 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
>         for (i = 0; i < nargs; i++) {
>                 u32 regno = i + 1;
>
> +               /*
> +                * Implicit kfunc arguments are set after main verification pass.
> +                * For correct tracking of zero-extensions we have to reset subreg_def for such
> +                * args. Otherwise mark_btf_func_reg_size() will be inspecting subreg_def of regs
> +                * from an earlier (irrelevant) point in the program, which may lead to an error
> +                * in opt_subreg_zext_lo32_rnd_hi32().
> +                */
> +               if (unlikely(KF_IMPLICIT_ARGS & meta.kfunc_flags
> +                               && is_kfunc_arg_implicit(desc_btf, &args[i])))
> +                       regs[regno].subreg_def = DEF_NOT_SUBREG;

ditto about unlikely(), this is used for rare cases where performance
matters a lot (and it's obvious which case is "common", so should be
kept linear in assembly code)


> +
>                 t = btf_type_skip_modifiers(desc_btf, args[i].type, NULL);
>                 if (btf_type_is_ptr(t))
>                         mark_btf_func_reg_size(env, regno, sizeof(void *));
> --
> 2.52.0
>

^ permalink raw reply

* Re: [PATCH bpf-next v1 04/10] resolve_btfids: Support for KF_IMPLICIT_ARGS
From: Andrii Nakryiko @ 2026-01-09 23:25 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, linux-kernel,
	linux-input, sched-ext
In-Reply-To: <20260109184852.1089786-5-ihor.solodrai@linux.dev>

On Fri, Jan 9, 2026 at 10:49 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> Implement BTF modifications in resolve_btfids to support BPF kernel
> functions with implicit arguments.
>
> For a kfunc marked with KF_IMPLICIT_ARGS flag, a new function
> prototype is added to BTF that does not have implicit arguments. The
> kfunc's prototype is then updated to a new one in BTF. This prototype
> is the intended interface for the BPF programs.
>
> A <func_name>_impl function is added to BTF to make the original kfunc
> prototype searchable for the BPF verifier. If a <func_name>_impl
> function already exists in BTF, its interpreted as a legacy case, and
> this step is skipped.
>
> Whether an argument is implicit is determined by its type:
> currently only `struct bpf_prog_aux *` is supported.
>
> As a result, the BTF associated with kfunc is changed from
>
>     __bpf_kfunc bpf_foo(int arg1, struct bpf_prog_aux *aux);
>
> into
>
>     bpf_foo_impl(int arg1, struct bpf_prog_aux *aux);
>     __bpf_kfunc bpf_foo(int arg1);
>
> For more context see previous discussions and patches [1][2].
>
> [1] https://lore.kernel.org/dwarves/ba1650aa-fafd-49a8-bea4-bdddee7c38c9@linux.dev/
> [2] https://lore.kernel.org/bpf/20251029190113.3323406-1-ihor.solodrai@linux.dev/
>
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
> ---
>  tools/bpf/resolve_btfids/main.c | 282 ++++++++++++++++++++++++++++++++
>  1 file changed, 282 insertions(+)
>
> diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
> index df39982f51df..b361e726fa36 100644
> --- a/tools/bpf/resolve_btfids/main.c
> +++ b/tools/bpf/resolve_btfids/main.c
> @@ -152,6 +152,18 @@ struct object {
>         int nr_typedefs;
>  };
>
> +#define KF_IMPLICIT_ARGS (1 << 16)
> +#define KF_IMPL_SUFFIX "_impl"
> +#define MAX_BPF_FUNC_REG_ARGS 5
> +#define MAX_KFUNCS 256
> +#define MAX_DECL_TAGS (MAX_KFUNCS * 4)

can't we get that from include/linux/bpf.h? seems like
resolve_btfids's main.c include internal headers just fine, so why
duplicate definitions?

> +
> +struct btf2btf_context {
> +       struct btf *btf;
> +       u32 nr_decl_tags;
> +       s32 decl_tags[MAX_DECL_TAGS];
> +};
> +
>  static int verbose;
>  static int warnings;
>
> @@ -972,6 +984,273 @@ static int patch_btfids(const char *btfids_path, const char *elf_path)
>         return err;
>  }
>
> +static s64 collect_kfunc_ids_by_flags(struct object *obj,
> +                                     u32 flags,
> +                                     s32 kfunc_ids[],
> +                                     const u32 kfunc_ids_sz)
> +{
> +       Elf_Data *data = obj->efile.idlist;
> +       struct rb_node *next;
> +       s64 nr_kfuncs = 0;
> +       int i;
> +
> +       next = rb_first(&obj->sets);
> +       while (next) {
> +               struct btf_id_set8 *set8 = NULL;
> +               unsigned long addr, off;
> +               struct btf_id *id;
> +
> +               id = rb_entry(next, struct btf_id, rb_node);
> +
> +               if (id->kind != BTF_ID_KIND_SET8)
> +                       goto skip;
> +
> +               addr = id->addr[0];
> +               off = addr - obj->efile.idlist_addr;
> +               set8 = data->d_buf + off;
> +
> +               for (i = 0; i < set8->cnt; i++) {
> +                       if (set8->pairs[i].flags & flags) {

invert condition and continue, reduce nesting?

> +                               if (nr_kfuncs >= kfunc_ids_sz) {

it's silly to set static limits like this: we are not in NMI, you have
memory allocator, use it

> +                                       pr_err("ERROR: resolve_btfids: too many kfuncs with flags %u - limit %d\n",
> +                                              flags, kfunc_ids_sz);
> +                                       return -E2BIG;
> +                               }
> +                               kfunc_ids[nr_kfuncs++] = set8->pairs[i].id;
> +                       }
> +               }
> +skip:
> +               next = rb_next(next);
> +       }
> +
> +       return nr_kfuncs;
> +}
> +
> +static const struct btf_type *btf__unqualified_type_by_id(const struct btf *btf, s32 type_id)
> +{
> +       const struct btf_type *t = btf__type_by_id(btf, type_id);
> +
> +       while (btf_is_mod(t))
> +               t = btf__type_by_id(btf, t->type);
> +
> +       return t;
> +}
> +
> +/* Implicit BPF kfunc arguments can only be of particular types */
> +static bool btf__is_kf_implicit_arg(const struct btf *btf, const struct btf_param *p)

nit: not sure why you use double underscore convention, this is not
really an "API" of btf, it's just a helper... I'd just call it
"is_kf_implicit_arg", btf is just and input argument

> +{
> +       static const char *const kf_implicit_arg_types[] = {
> +               "bpf_prog_aux",
> +       };
> +       const struct btf_type *t;
> +       const char *name;
> +

[...]

> +       /* Copy all decl tags except "bpf_kfunc" from the original kfunc to the new one */
> +       for (int i = 0; i < ctx->nr_decl_tags; i++) {
> +               t = (struct btf_type *)btf__type_by_id(btf, ctx->decl_tags[i]);
> +               if (t->type != kfunc_id)
> +                       continue;
> +
> +               tag_name = btf__name_by_offset(btf, t->name_off);
> +               if (strcmp(tag_name, "bpf_kfunc") == 0)
> +                       continue;
> +
> +               err = btf__add_decl_tag(btf, tag_name, new_func_id, -1);

decl_tag can apply to arguments as well (that -1 will be actually >=
0), we should copy those as well, no?

> +               if (err < 0) {
> +                       pr_err("ERROR: resolve_btfids: failed to add decl tag %s for %s\n",
> +                              tag_name, tmp_name);
> +                       return -EINVAL;
> +               }
> +       }
> +
> +add_new_proto:
> +       /*
> +        * Drop the _impl suffix and point kfunc_name to the local buffer for later use.
> +        * When BTF is modified the original pointer is invalidated.
> +        */
> +       tmp_name[name_len] = '\0';
> +       kfunc_name = tmp_name;
> +
> +       /* Load non-implicit args from the original prototype */
> +       t = (struct btf_type *)btf__type_by_id(btf, proto_id);
> +       params = btf_params(t);
> +       nr_params = 0;
> +       for (int i = 0; i < btf_vlen(t); i++) {
> +               if (btf__is_kf_implicit_arg(btf, &params[i]))
> +                       break;
> +               new_params[nr_params++] = params[i];
> +       }

this is unnecessary, just when you working with original prototype and
its arguments, just re-fetch it back from IDs, all those pointers will
be valid until next btf__add_xxx() invocation, no need for this
awkward local copies

> +
> +       new_proto_id = btf__add_func_proto(btf, t->type);
> +       if (new_proto_id < 0) {
> +               pr_err("ERROR: resolve_btfids: failed to add func proto for %s\n", kfunc_name);
> +               return new_proto_id;
> +       }
> +
> +       /* Add non-implicit args to the new prototype */
> +       for (int i = 0; i < nr_params; i++) {
> +               param_name = btf__name_by_offset(btf, new_params[i].name_off);
> +               err = btf__add_func_param(btf, param_name, new_params[i].type);
> +               if (err < 0) {
> +                       pr_err("ERROR: resolve_btfids: failed to add param %s for %s\n",
> +                              param_name, kfunc_name);
> +                       return err;
> +               }
> +       }
> +
> +       /* Finally change the prototype of the original kfunc to the new one */
> +       t = (struct btf_type *)btf__type_by_id(btf, kfunc_id);
> +       t->type = new_proto_id;
> +
> +       pr_debug("resolve_btfids: updated BTF for kfunc with implicit args %s\n", kfunc_name);
> +
> +       return 0;
> +}
> +
> +static s64 btf__collect_decl_tags(const struct btf *btf, s32 *decl_tags, u32 decl_tags_sz)
> +{
> +       const u32 type_cnt = btf__type_cnt(btf);
> +       const struct btf_type *t;
> +       s64 nr_decl_tags = 0;
> +
> +       for (u32 id = 1; id < type_cnt; id++) {
> +               t = btf__type_by_id(btf, id);
> +               if (!btf_is_decl_tag(t))
> +                       continue;
> +               if (nr_decl_tags >= decl_tags_sz) {
> +                       pr_err("ERROR: resolve_btfids: too many decl tags in BTF - limit %s\n",

realloc is your friend, no fixed-sized arrays

> +                               decl_tags_sz);
> +                       return -E2BIG;
> +               }
> +               decl_tags[nr_decl_tags++] = id;
> +       }
> +
> +       return nr_decl_tags;
> +}
> +

[...]

^ permalink raw reply

* Re: [PATCH bpf-next v1 05/10] selftests/bpf: Add tests for KF_IMPLICIT_ARGS
From: Andrii Nakryiko @ 2026-01-09 23:25 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, linux-kernel,
	linux-input, sched-ext
In-Reply-To: <20260109184852.1089786-6-ihor.solodrai@linux.dev>

On Fri, Jan 9, 2026 at 10:49 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> Add trivial end-to-end tests to validate that KF_IMPLICIT_ARGS flag is
> properly handled by both resolve_btfids and the verifier.
>
> Declare kfuncs in bpf_testmod. Check that bpf_prog_aux pointer is set
> in the kfunc implementation. Verify that calls with implicit args and
> a legacy case all work.
>
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
> ---
>  .../bpf/prog_tests/kfunc_implicit_args.c      | 10 +++++
>  .../selftests/bpf/progs/kfunc_implicit_args.c | 41 +++++++++++++++++++
>  .../selftests/bpf/test_kmods/bpf_testmod.c    | 26 ++++++++++++
>  3 files changed, 77 insertions(+)
>  create mode 100644 tools/testing/selftests/bpf/prog_tests/kfunc_implicit_args.c
>  create mode 100644 tools/testing/selftests/bpf/progs/kfunc_implicit_args.c
>

[...]

> @@ -0,0 +1,41 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
> +
> +#include <vmlinux.h>
> +#include <bpf/bpf_helpers.h>
> +#include "bpf_misc.h"
> +
> +extern int bpf_kfunc_implicit_arg(int a) __weak __ksym;
> +extern int bpf_kfunc_implicit_arg_impl(int a, void *aux__prog) __weak __ksym; // illegal

C++ comment

> +extern int bpf_kfunc_implicit_arg_legacy(int a, int b) __weak __ksym;
> +extern int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, void *aux__prog) __weak __ksym;
> +
> +char _license[] SEC("license") = "GPL";
> +

[...]

> diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> index 1c41d03bd5a1..503451875d33 100644
> --- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> +++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> @@ -1136,6 +1136,10 @@ __bpf_kfunc int bpf_kfunc_st_ops_inc10(struct st_ops_args *args)
>  __bpf_kfunc int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id);
>  __bpf_kfunc int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux_prog);
>
> +__bpf_kfunc int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux);
> +__bpf_kfunc int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux);
> +__bpf_kfunc int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, void *aux__prog);
> +
>  BTF_KFUNCS_START(bpf_testmod_check_kfunc_ids)
>  BTF_ID_FLAGS(func, bpf_testmod_test_mod_kfunc)
>  BTF_ID_FLAGS(func, bpf_kfunc_call_test1)
> @@ -1178,6 +1182,9 @@ BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_pro_epilogue, KF_SLEEPABLE)
>  BTF_ID_FLAGS(func, bpf_kfunc_st_ops_inc10)
>  BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1)
>  BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1_impl)
> +BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg, KF_IMPLICIT_ARGS)
> +BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy, KF_IMPLICIT_ARGS)
> +BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy_impl)

(irrelevant, now that I saw patch #8 discussion, but for the future
the point will stand and we can decide how resolve_btfids handles this
upfront)

I'm wondering, should we add KF_IMPLICIT_ARGS to legacy xxx_impl
kfuncs as well to explicitly mark them to resolve_btfids as legacy
implementations? And if we somehow find xxx_impl without it, then
resolve_btfids complains louds and fails, this should never happen?



>  BTF_KFUNCS_END(bpf_testmod_check_kfunc_ids)
>
>  static int bpf_testmod_ops_init(struct btf *btf)
> @@ -1669,6 +1676,25 @@ int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux__prog
>         return ret;
>  }
>
> +int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux)
> +{
> +       if (aux && a > 0)
> +               return a;
> +       return -EINVAL;
> +}
> +
> +int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux)
> +{
> +       if (aux)
> +               return a + b;
> +       return -EINVAL;
> +}
> +
> +int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, void *aux__prog)
> +{
> +       return bpf_kfunc_implicit_arg_legacy(a, b, aux__prog);
> +}
> +
>  static int multi_st_ops_reg(void *kdata, struct bpf_link *link)
>  {
>         struct bpf_testmod_multi_st_ops *st_ops =
> --
> 2.52.0
>

^ permalink raw reply

* Re: [PATCH bpf-next v1 04/10] resolve_btfids: Support for KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-10  1:15 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, linux-kernel,
	linux-input, sched-ext
In-Reply-To: <CAEf4BzYcZ5pLCvfn8uWiKCjpBXBw9dxR_WZnKxVz1Bhf96xOGg@mail.gmail.com>

On 1/9/26 3:25 PM, Andrii Nakryiko wrote:
> On Fri, Jan 9, 2026 at 10:49 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>>
>> Implement BTF modifications in resolve_btfids to support BPF kernel
>> functions with implicit arguments.
>>
>> For a kfunc marked with KF_IMPLICIT_ARGS flag, a new function
>> prototype is added to BTF that does not have implicit arguments. The
>> kfunc's prototype is then updated to a new one in BTF. This prototype
>> is the intended interface for the BPF programs.
>>
>> A <func_name>_impl function is added to BTF to make the original kfunc
>> prototype searchable for the BPF verifier. If a <func_name>_impl
>> function already exists in BTF, its interpreted as a legacy case, and
>> this step is skipped.
>>
>> Whether an argument is implicit is determined by its type:
>> currently only `struct bpf_prog_aux *` is supported.
>>
>> As a result, the BTF associated with kfunc is changed from
>>
>>     __bpf_kfunc bpf_foo(int arg1, struct bpf_prog_aux *aux);
>>
>> into
>>
>>     bpf_foo_impl(int arg1, struct bpf_prog_aux *aux);
>>     __bpf_kfunc bpf_foo(int arg1);
>>
>> For more context see previous discussions and patches [1][2].
>>
>> [1] https://lore.kernel.org/dwarves/ba1650aa-fafd-49a8-bea4-bdddee7c38c9@linux.dev/
>> [2] https://lore.kernel.org/bpf/20251029190113.3323406-1-ihor.solodrai@linux.dev/
>>
>> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
>> ---
>>  tools/bpf/resolve_btfids/main.c | 282 ++++++++++++++++++++++++++++++++
>>  1 file changed, 282 insertions(+)
>>
>> diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
>> index df39982f51df..b361e726fa36 100644
>> --- a/tools/bpf/resolve_btfids/main.c
>> +++ b/tools/bpf/resolve_btfids/main.c
>> @@ -152,6 +152,18 @@ struct object {
>>         int nr_typedefs;
>>  };
>>
>> +#define KF_IMPLICIT_ARGS (1 << 16)
>> +#define KF_IMPL_SUFFIX "_impl"
>> +#define MAX_BPF_FUNC_REG_ARGS 5
>> +#define MAX_KFUNCS 256
>> +#define MAX_DECL_TAGS (MAX_KFUNCS * 4)
> 
> can't we get that from include/linux/bpf.h? seems like
> resolve_btfids's main.c include internal headers just fine, so why
> duplicate definitions?

Hi Andrii, thank you for a quick review.

Including internal include/linux/btf.h directly doesn't work, which is
probably expected.

resolve_btfids is currently built with:

HOSTCFLAGS_resolve_btfids += -g \
          -I$(srctree)/tools/include \
          -I$(srctree)/tools/include/uapi \
          -I$(LIBBPF_INCLUDE) \
          -I$(SUBCMD_INCLUDE) \
          $(LIBELF_FLAGS) \
          -Wall -Werror

If I add -I$(srctree)/include option and then

    #include <linux/btf.h>

A bunch of build errors happen.

AFAIU we'd have to create a stripped copy of relevant headers in
tools/include first.  Is that what you're suggesting?

> 
>> +
>> +struct btf2btf_context {
>> +       struct btf *btf;
>> +       u32 nr_decl_tags;
>> +       s32 decl_tags[MAX_DECL_TAGS];
>> +};
>> +
>>  static int verbose;
>>  static int warnings;
>>
>> @@ -972,6 +984,273 @@ static int patch_btfids(const char *btfids_path, const char *elf_path)
>>         return err;
>>  }
>>
>> +static s64 collect_kfunc_ids_by_flags(struct object *obj,
>> +                                     u32 flags,
>> +                                     s32 kfunc_ids[],
>> +                                     const u32 kfunc_ids_sz)
>> +{
>> +       Elf_Data *data = obj->efile.idlist;
>> +       struct rb_node *next;
>> +       s64 nr_kfuncs = 0;
>> +       int i;
>> +
>> +       next = rb_first(&obj->sets);
>> +       while (next) {
>> +               struct btf_id_set8 *set8 = NULL;
>> +               unsigned long addr, off;
>> +               struct btf_id *id;
>> +
>> +               id = rb_entry(next, struct btf_id, rb_node);
>> +
>> +               if (id->kind != BTF_ID_KIND_SET8)
>> +                       goto skip;
>> +
>> +               addr = id->addr[0];
>> +               off = addr - obj->efile.idlist_addr;
>> +               set8 = data->d_buf + off;
>> +
>> +               for (i = 0; i < set8->cnt; i++) {
>> +                       if (set8->pairs[i].flags & flags) {
> 
> invert condition and continue, reduce nesting?
> 
>> +                               if (nr_kfuncs >= kfunc_ids_sz) {
> 
> it's silly to set static limits like this: we are not in NMI, you have
> memory allocator, use it

I kinda like that btf2btf_context is stack allocated, but I see your
point. It's not necessary to set hard limits in resolve_btfids.

> 
>> +                                       pr_err("ERROR: resolve_btfids: too many kfuncs with flags %u - limit %d\n",
>> +                                              flags, kfunc_ids_sz);
>> +                                       return -E2BIG;
>> +                               }
>> +                               kfunc_ids[nr_kfuncs++] = set8->pairs[i].id;
>> +                       }
>> +               }
>> +skip:
>> +               next = rb_next(next);
>> +       }
>> +
>> +       return nr_kfuncs;
>> +}
>> +
>> +static const struct btf_type *btf__unqualified_type_by_id(const struct btf *btf, s32 type_id)
>> +{
>> +       const struct btf_type *t = btf__type_by_id(btf, type_id);
>> +
>> +       while (btf_is_mod(t))
>> +               t = btf__type_by_id(btf, t->type);
>> +
>> +       return t;
>> +}
>> +
>> +/* Implicit BPF kfunc arguments can only be of particular types */
>> +static bool btf__is_kf_implicit_arg(const struct btf *btf, const struct btf_param *p)
> 
> nit: not sure why you use double underscore convention, this is not
> really an "API" of btf, it's just a helper... I'd just call it
> "is_kf_implicit_arg", btf is just and input argument
> 
>> +{
>> +       static const char *const kf_implicit_arg_types[] = {
>> +               "bpf_prog_aux",
>> +       };
>> +       const struct btf_type *t;
>> +       const char *name;
>> +
> 
> [...]
> 
>> +       /* Copy all decl tags except "bpf_kfunc" from the original kfunc to the new one */
>> +       for (int i = 0; i < ctx->nr_decl_tags; i++) {
>> +               t = (struct btf_type *)btf__type_by_id(btf, ctx->decl_tags[i]);
>> +               if (t->type != kfunc_id)
>> +                       continue;
>> +
>> +               tag_name = btf__name_by_offset(btf, t->name_off);
>> +               if (strcmp(tag_name, "bpf_kfunc") == 0)
>> +                       continue;
>> +
>> +               err = btf__add_decl_tag(btf, tag_name, new_func_id, -1);
> 
> decl_tag can apply to arguments as well (that -1 will be actually >=
> 0), we should copy those as well, no?

I think you're right. Technically decl_tags can point to parameters as
well.  Is this actually used in kernel BTF?

For the type tags we don't have to do anything though, because the
param type should point to the top type tag, right?

> 
>> +               if (err < 0) {
>> +                       pr_err("ERROR: resolve_btfids: failed to add decl tag %s for %s\n",
>> +                              tag_name, tmp_name);
>> +                       return -EINVAL;
>> +               }
>> +       }
>> +
>> +add_new_proto:
>> +       /*
>> +        * Drop the _impl suffix and point kfunc_name to the local buffer for later use.
>> +        * When BTF is modified the original pointer is invalidated.
>> +        */
>> +       tmp_name[name_len] = '\0';
>> +       kfunc_name = tmp_name;
>> +
>> +       /* Load non-implicit args from the original prototype */
>> +       t = (struct btf_type *)btf__type_by_id(btf, proto_id);
>> +       params = btf_params(t);
>> +       nr_params = 0;
>> +       for (int i = 0; i < btf_vlen(t); i++) {
>> +               if (btf__is_kf_implicit_arg(btf, &params[i]))
>> +                       break;
>> +               new_params[nr_params++] = params[i];
>> +       }
> 
> this is unnecessary, just when you working with original prototype and
> its arguments, just re-fetch it back from IDs, all those pointers will
> be valid until next btf__add_xxx() invocation, no need for this
> awkward local copies
> 
>> +
>> +       new_proto_id = btf__add_func_proto(btf, t->type);
>> +       if (new_proto_id < 0) {
>> +               pr_err("ERROR: resolve_btfids: failed to add func proto for %s\n", kfunc_name);
>> +               return new_proto_id;
>> +       }
>> +
>> +       /* Add non-implicit args to the new prototype */
>> +       for (int i = 0; i < nr_params; i++) {
>> +               param_name = btf__name_by_offset(btf, new_params[i].name_off);
>> +               err = btf__add_func_param(btf, param_name, new_params[i].type);
>> +               if (err < 0) {
>> +                       pr_err("ERROR: resolve_btfids: failed to add param %s for %s\n",
>> +                              param_name, kfunc_name);
>> +                       return err;
>> +               }
>> +       }
>> +
>> +       /* Finally change the prototype of the original kfunc to the new one */
>> +       t = (struct btf_type *)btf__type_by_id(btf, kfunc_id);
>> +       t->type = new_proto_id;
>> +
>> +       pr_debug("resolve_btfids: updated BTF for kfunc with implicit args %s\n", kfunc_name);
>> +
>> +       return 0;
>> +}
>> +
>> +static s64 btf__collect_decl_tags(const struct btf *btf, s32 *decl_tags, u32 decl_tags_sz)
>> +{
>> +       const u32 type_cnt = btf__type_cnt(btf);
>> +       const struct btf_type *t;
>> +       s64 nr_decl_tags = 0;
>> +
>> +       for (u32 id = 1; id < type_cnt; id++) {
>> +               t = btf__type_by_id(btf, id);
>> +               if (!btf_is_decl_tag(t))
>> +                       continue;
>> +               if (nr_decl_tags >= decl_tags_sz) {
>> +                       pr_err("ERROR: resolve_btfids: too many decl tags in BTF - limit %s\n",
> 
> realloc is your friend, no fixed-sized arrays
> 
>> +                               decl_tags_sz);
>> +                       return -E2BIG;
>> +               }
>> +               decl_tags[nr_decl_tags++] = id;
>> +       }
>> +
>> +       return nr_decl_tags;
>> +}
>> +
> 
> [...]


^ permalink raw reply

* Re: [PATCH bpf-next v1 05/10] selftests/bpf: Add tests for KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-10  1:29 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
	Alan Maguire, Benjamin Tissoires, Jiri Kosina, bpf, linux-kernel,
	linux-input, sched-ext
In-Reply-To: <CAEf4BzZfuqpdwghCZ_TJJyt3Dm=xCBJLz3H0bbtabgToNV7V+A@mail.gmail.com>

On 1/9/26 3:25 PM, Andrii Nakryiko wrote:
> On Fri, Jan 9, 2026 at 10:49 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
> 
> [...]
> 
>> diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
>> index 1c41d03bd5a1..503451875d33 100644
>> --- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
>> +++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
>> @@ -1136,6 +1136,10 @@ __bpf_kfunc int bpf_kfunc_st_ops_inc10(struct st_ops_args *args)
>>  __bpf_kfunc int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id);
>>  __bpf_kfunc int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux_prog);
>>
>> +__bpf_kfunc int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux);
>> +__bpf_kfunc int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux);
>> +__bpf_kfunc int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, void *aux__prog);
>> +
>>  BTF_KFUNCS_START(bpf_testmod_check_kfunc_ids)
>>  BTF_ID_FLAGS(func, bpf_testmod_test_mod_kfunc)
>>  BTF_ID_FLAGS(func, bpf_kfunc_call_test1)
>> @@ -1178,6 +1182,9 @@ BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_pro_epilogue, KF_SLEEPABLE)
>>  BTF_ID_FLAGS(func, bpf_kfunc_st_ops_inc10)
>>  BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1)
>>  BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1_impl)
>> +BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg, KF_IMPLICIT_ARGS)
>> +BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy, KF_IMPLICIT_ARGS)
>> +BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy_impl)
> 
> (irrelevant, now that I saw patch #8 discussion, but for the future
> the point will stand and we can decide how resolve_btfids handles this
> upfront)
> 
> I'm wondering, should we add KF_IMPLICIT_ARGS to legacy xxx_impl
> kfuncs as well to explicitly mark them to resolve_btfids as legacy
> implementations? And if we somehow find xxx_impl without it, then
> resolve_btfids complains louds and fails, this should never happen?

Eh... I don't like the idea of flagging both foo and foo_impl.

If we use the same flag for legacy funcs, the flag becomes
insufficient to determine whether a function is legacy or not: we also
have to check the name (or something). This could be a different flag,
but I don't like that either.

For legacy kfuncs that we want to support, I don't think we have to
enforce anything. We allow to use old API, and the new one if it's
implemented.

Are you suggesting to ban _impl suffix in names of new kfuncs?
Fail build on accidental name collision?

We could implement sanity checks like these as separate passes in
resolve_btfids, for example.

> 
> 
> 
>>  BTF_KFUNCS_END(bpf_testmod_check_kfunc_ids)
>>
>>  static int bpf_testmod_ops_init(struct btf *btf)
>> @@ -1669,6 +1676,25 @@ int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux__prog
>>         return ret;
>>  }
>>
>> +int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux)
>> +{
>> +       if (aux && a > 0)
>> +               return a;
>> +       return -EINVAL;
>> +}
>> +
>> +int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux)
>> +{
>> +       if (aux)
>> +               return a + b;
>> +       return -EINVAL;
>> +}
>> +
>> +int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, void *aux__prog)
>> +{
>> +       return bpf_kfunc_implicit_arg_legacy(a, b, aux__prog);
>> +}
>> +
>>  static int multi_st_ops_reg(void *kdata, struct bpf_link *link)
>>  {
>>         struct bpf_testmod_multi_st_ops *st_ops =
>> --
>> 2.52.0
>>


^ permalink raw reply

* Re: [PATCH] HID: rapoo: Add support for side buttons on RAPOO 0x2015 mouse
From: Jiri Kosina @ 2026-01-10  8:53 UTC (permalink / raw)
  To: Nguyen Dinh Dang Duong; +Cc: linux-input, linux-kernel
In-Reply-To: <20250627170425.11166-1-dangduong31205@gmail.com>

On Sat, 28 Jun 2025, Nguyen Dinh Dang Duong wrote:

> This patch adds support for handling the side buttons
> on the RAPOO 0x2015 wireless mouse. These buttons were
> previously not generating input events due to missing
> driver logic.
> 
> The new code handles raw HID input report with Report
> ID 1 and maps the side buttons to KEY_BACK and KEY_FORWARD
> using the input subsystem.
> 
> Tested on a RAPOO mouse with USB ID 24AE:2015.
> 
> Signed-off-by: Nguyen Dinh Dang Duong <dangduong31205@gmail.com>

Sorry, this fell in betwwen cracks. Now applied.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply

* Re: [PATCH] HID: apple: Add "SONiX KN85 Keyboard" to the list of non-apple keyboards
From: Jiri Kosina @ 2026-01-10  8:55 UTC (permalink / raw)
  To: linux; +Cc: linux-kernel, linux-input, bentiss
In-Reply-To: <176292759108.7.4651202733090413990.1001877915@joeybednar.com>

On Wed, 12 Nov 2025, linux@joeybednar.com wrote:

> From: Joey Bednar <linux@joeybednar.com>
> 
> The SoNiX KN85 keyboard identifies as the "Apple, Inc. Aluminium
> Keyboard" and is not recognized as a non-apple keyboard. Adding "SoNiX
> KN85 Keyboard" to the list of non-apple keyboards fixes the function
> keys.
> 
> Signed-off-by: Joey Bednar <linux@joeybednar.com>

Sorry for the delay, now applied.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply

* Re: [PATCH] HID: playstation: Add missing check for input_ff_create_memless
From: Jiri Kosina @ 2026-01-10  9:00 UTC (permalink / raw)
  To: Haotian Zhang; +Cc: roderick.colenbrander, bentiss, linux-input, linux-kernel
In-Reply-To: <20251117082808.1492-1-vulab@iscas.ac.cn>

On Mon, 17 Nov 2025, Haotian Zhang wrote:

> The ps_gamepad_create() function calls input_ff_create_memless()
> without verifying its return value,  which can lead to incorrect
> behavior or potential crashes when FF effects are triggered.
> 
> Add a check for the return value of input_ff_create_memless().
> 
> Fixes: 51151098d7ab ("HID: playstation: add DualSense classic rumble support.")
> Signed-off-by: Haotian Zhang <vulab@iscas.ac.cn>
> ---
>  drivers/hid/hid-playstation.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
> index 63f6eb9030d1..aea8d6cf46a2 100644
> --- a/drivers/hid/hid-playstation.c
> +++ b/drivers/hid/hid-playstation.c
> @@ -769,7 +769,9 @@ ps_gamepad_create(struct hid_device *hdev,
>  #if IS_ENABLED(CONFIG_PLAYSTATION_FF)
>  	if (play_effect) {
>  		input_set_capability(gamepad, EV_FF, FF_RUMBLE);
> -		input_ff_create_memless(gamepad, NULL, play_effect);
> +		ret = input_ff_create_memless(gamepad, NULL, play_effect);
> +		if (ret)
> +			return ERR_PTR(ret);

This particular change by itself is good, and I'll be queuing it in 
hid.git#for-6.19/upstrram-fixes.

While reviewing it though, I came across the fact that just one line 
below, if input_register_device() fails, I believe we're leaking the 
already allocated struct input_dev.

I'll send out a separate patch for it.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply

* Re: [PATCH] HID: playstation: Add missing check for input_ff_create_memless
From: Jiri Kosina @ 2026-01-10  9:01 UTC (permalink / raw)
  To: Haotian Zhang; +Cc: roderick.colenbrander, bentiss, linux-input, linux-kernel
In-Reply-To: <2nn8276r-50nq-5655-o1r2-o610sp1s69q6@xreary.bet>

On Sat, 10 Jan 2026, Jiri Kosina wrote:

> While reviewing it though, I came across the fact that just one line 
> below, if input_register_device() fails, I believe we're leaking the 
> already allocated struct input_dev.

Actually we're not, it's managed device. Sorry for the noise.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox