diff mbox series

[v2,bpf-next,6/6] selftests/bpf: add kfunc_call test for simple dtor in bpf_testmod

Message ID 20240620091733.1967885-7-alan.maguire@oracle.com (mailing list archive)
State Accepted
Commit 47a8cf0c5b3f6769b9d558301735c75119a0a165
Delegated to: BPF
Headers show
Series bpf: resilient split BTF followups | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 17 this patch: 17
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 9 maintainers not CCed: alexandre.torgue@foss.st.com lizetao1@huawei.com shuah@kernel.org zouyipeng@huawei.com mcoquelin.stm32@gmail.com linux-arm-kernel@lists.infradead.org linux-stm32@st-md-mailman.stormreply.com jrife@google.com linux-kselftest@vger.kernel.org
netdev/build_clang fail Errors and warnings before: 19 this patch: 19
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 17 this patch: 17
netdev/checkpatch warning CHECK: spaces preferred around that '*' (ctx:WxV)
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-18 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
bpf/vmtest-bpf-next-VM_Test-42 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-15 success Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-8 success Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-40 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18

Commit Message

Alan Maguire June 20, 2024, 9:17 a.m. UTC
add simple kfuncs to create/destroy a context type to bpf_testmod,
register them and add a kfunc_call test to use them.  This provides
test coverage for registration of dtor kfuncs from modules.

By transferring the context pointer to a map value as a __kptr
we also trigger the map-based dtor cleanup logic, improving test
coverage.

Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
 .../selftests/bpf/bpf_testmod/bpf_testmod.c   | 46 +++++++++++++++++++
 .../bpf/bpf_testmod/bpf_testmod_kfunc.h       |  9 ++++
 .../selftests/bpf/prog_tests/kfunc_call.c     |  1 +
 .../selftests/bpf/progs/kfunc_call_test.c     | 37 +++++++++++++++
 4 files changed, 93 insertions(+)

Comments

Eduard Zingerman June 20, 2024, 11:41 a.m. UTC | #1
On Thu, 2024-06-20 at 10:17 +0100, Alan Maguire wrote:

[...]

Hi Alan,

I still get the error message in the dmesg:

[   10.489223] BUG: sleeping function called from invalid context at include/linux/sched/mm.h:337
[   10.489454] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 184, name: test_progs
[   10.489589] preempt_count: 200, expected: 0
[   10.489659] RCU nest depth: 1, expected: 0
[   10.489733] 1 lock held by test_progs/184:
[   10.489811]  #0: ffffffff83198a60 (rcu_read_lock){....}-{1:2}, at: bpf_test_timer_enter+0x1d/0xb0
[   10.490040] Preemption disabled at:
[   10.490060] [<ffffffff81a0ee6a>] bpf_test_run+0x16a/0x300
[   10.490197] CPU: 1 PID: 184 Comm: test_progs Tainted: G           OE      6.10.0-rc2-00766-gb812ab0e1306-dirty #39
[   10.490356] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014
[   10.490475] Call Trace:
[   10.490515]  <TASK>
[   10.490557]  dump_stack_lvl+0x83/0xa0
[   10.490618]  __might_resched+0x199/0x2b0
[   10.490695]  kmalloc_trace_noprof+0x273/0x320
[   10.490756]  ? srso_alias_return_thunk+0x5/0xfbef5
[   10.490836]  ? bpf_test_run+0xc0/0x300
[   10.490836]  ? bpf_testmod_ctx_create+0x23/0x50 [bpf_testmod]
[   10.490836]  bpf_testmod_ctx_create+0x23/0x50 [bpf_testmod]
[   10.490836]  bpf_prog_d1347efc07047347_kfunc_call_ctx+0x2c/0xae
[   10.490836]  bpf_test_run+0x198/0x300
[   10.490836]  ? srso_alias_return_thunk+0x5/0xfbef5
[   10.490836]  ? lockdep_init_map_type+0x4b/0x250
[   10.490836]  bpf_prog_test_run_skb+0x381/0x7f0
[   10.490836]  __sys_bpf+0xc4f/0x2e00
[   10.490836]  ? srso_alias_return_thunk+0x5/0xfbef5
[   10.490836]  ? reacquire_held_locks+0xcf/0x1f0
[   10.490836]  __x64_sys_bpf+0x1e/0x30
[   10.490836]  do_syscall_64+0x68/0x140
[   10.490836]  entry_SYSCALL_64_after_hwframe+0x76/0x7e

The following fix helps:

--- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
+++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
@@ -164,7 +164,7 @@ bpf_testmod_ctx_create(int *err)
 {
        struct bpf_testmod_ctx *ctx;
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL | GFP_ATOMIC);
+       ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
        if (!ctx) {
                *err = -ENOMEM;
                return NULL;

Thanks,
Eduard

[...]
Andrii Nakryiko June 21, 2024, 10 p.m. UTC | #2
On Thu, Jun 20, 2024 at 4:41 AM Eduard Zingerman <eddyz87@gmail.com> wrote:
>
> On Thu, 2024-06-20 at 10:17 +0100, Alan Maguire wrote:
>
> [...]
>
> Hi Alan,
>
> I still get the error message in the dmesg:
>
> [   10.489223] BUG: sleeping function called from invalid context at include/linux/sched/mm.h:337
> [   10.489454] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 184, name: test_progs
> [   10.489589] preempt_count: 200, expected: 0
> [   10.489659] RCU nest depth: 1, expected: 0
> [   10.489733] 1 lock held by test_progs/184:
> [   10.489811]  #0: ffffffff83198a60 (rcu_read_lock){....}-{1:2}, at: bpf_test_timer_enter+0x1d/0xb0
> [   10.490040] Preemption disabled at:
> [   10.490060] [<ffffffff81a0ee6a>] bpf_test_run+0x16a/0x300
> [   10.490197] CPU: 1 PID: 184 Comm: test_progs Tainted: G           OE      6.10.0-rc2-00766-gb812ab0e1306-dirty #39
> [   10.490356] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014
> [   10.490475] Call Trace:
> [   10.490515]  <TASK>
> [   10.490557]  dump_stack_lvl+0x83/0xa0
> [   10.490618]  __might_resched+0x199/0x2b0
> [   10.490695]  kmalloc_trace_noprof+0x273/0x320
> [   10.490756]  ? srso_alias_return_thunk+0x5/0xfbef5
> [   10.490836]  ? bpf_test_run+0xc0/0x300
> [   10.490836]  ? bpf_testmod_ctx_create+0x23/0x50 [bpf_testmod]
> [   10.490836]  bpf_testmod_ctx_create+0x23/0x50 [bpf_testmod]
> [   10.490836]  bpf_prog_d1347efc07047347_kfunc_call_ctx+0x2c/0xae
> [   10.490836]  bpf_test_run+0x198/0x300
> [   10.490836]  ? srso_alias_return_thunk+0x5/0xfbef5
> [   10.490836]  ? lockdep_init_map_type+0x4b/0x250
> [   10.490836]  bpf_prog_test_run_skb+0x381/0x7f0
> [   10.490836]  __sys_bpf+0xc4f/0x2e00
> [   10.490836]  ? srso_alias_return_thunk+0x5/0xfbef5
> [   10.490836]  ? reacquire_held_locks+0xcf/0x1f0
> [   10.490836]  __x64_sys_bpf+0x1e/0x30
> [   10.490836]  do_syscall_64+0x68/0x140
> [   10.490836]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
>
> The following fix helps:
>
> --- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
> +++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
> @@ -164,7 +164,7 @@ bpf_testmod_ctx_create(int *err)
>  {
>         struct bpf_testmod_ctx *ctx;
>
> -       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL | GFP_ATOMIC);
> +       ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);

fixed while applying, thanks

>         if (!ctx) {
>                 *err = -ENOMEM;
>                 return NULL;
>
> Thanks,
> Eduard
>
> [...]
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
index 49f9a311e49b..fa7f803ea9b5 100644
--- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
+++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
@@ -159,6 +159,37 @@  __bpf_kfunc void bpf_kfunc_dynptr_test(struct bpf_dynptr *ptr,
 {
 }
 
+__bpf_kfunc struct bpf_testmod_ctx *
+bpf_testmod_ctx_create(int *err)
+{
+	struct bpf_testmod_ctx *ctx;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL | GFP_ATOMIC);
+	if (!ctx) {
+		*err = -ENOMEM;
+		return NULL;
+	}
+	refcount_set(&ctx->usage, 1);
+
+	return ctx;
+}
+
+static void testmod_free_cb(struct rcu_head *head)
+{
+	struct bpf_testmod_ctx *ctx;
+
+	ctx = container_of(head, struct bpf_testmod_ctx, rcu);
+	kfree(ctx);
+}
+
+__bpf_kfunc void bpf_testmod_ctx_release(struct bpf_testmod_ctx *ctx)
+{
+	if (!ctx)
+		return;
+	if (refcount_dec_and_test(&ctx->usage))
+		call_rcu(&ctx->rcu, testmod_free_cb);
+}
+
 struct bpf_testmod_btf_type_tag_1 {
 	int a;
 };
@@ -369,8 +400,14 @@  BTF_ID_FLAGS(func, bpf_iter_testmod_seq_next, KF_ITER_NEXT | KF_RET_NULL)
 BTF_ID_FLAGS(func, bpf_iter_testmod_seq_destroy, KF_ITER_DESTROY)
 BTF_ID_FLAGS(func, bpf_kfunc_common_test)
 BTF_ID_FLAGS(func, bpf_kfunc_dynptr_test)
+BTF_ID_FLAGS(func, bpf_testmod_ctx_create, KF_ACQUIRE | KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_testmod_ctx_release, KF_RELEASE)
 BTF_KFUNCS_END(bpf_testmod_common_kfunc_ids)
 
+BTF_ID_LIST(bpf_testmod_dtor_ids)
+BTF_ID(struct, bpf_testmod_ctx)
+BTF_ID(func, bpf_testmod_ctx_release)
+
 static const struct btf_kfunc_id_set bpf_testmod_common_kfunc_set = {
 	.owner = THIS_MODULE,
 	.set   = &bpf_testmod_common_kfunc_ids,
@@ -904,6 +941,12 @@  extern int bpf_fentry_test1(int a);
 
 static int bpf_testmod_init(void)
 {
+	const struct btf_id_dtor_kfunc bpf_testmod_dtors[] = {
+		{
+			.btf_id		= bpf_testmod_dtor_ids[0],
+			.kfunc_btf_id	= bpf_testmod_dtor_ids[1]
+		},
+	};
 	int ret;
 
 	ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, &bpf_testmod_common_kfunc_set);
@@ -912,6 +955,9 @@  static int bpf_testmod_init(void)
 	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &bpf_testmod_kfunc_set);
 	ret = ret ?: register_bpf_struct_ops(&bpf_bpf_testmod_ops, bpf_testmod_ops);
 	ret = ret ?: register_bpf_struct_ops(&bpf_testmod_ops2, bpf_testmod_ops2);
+	ret = ret ?: register_btf_id_dtor_kfuncs(bpf_testmod_dtors,
+						 ARRAY_SIZE(bpf_testmod_dtors),
+						 THIS_MODULE);
 	if (ret < 0)
 		return ret;
 	if (bpf_fentry_test1(0) < 0)
diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h
index f9809517e7fa..e587a79f2239 100644
--- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h
+++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h
@@ -80,6 +80,11 @@  struct sendmsg_args {
 	int msglen;
 };
 
+struct bpf_testmod_ctx {
+	struct callback_head	rcu;
+	refcount_t		usage;
+};
+
 struct prog_test_ref_kfunc *
 bpf_kfunc_call_test_acquire(unsigned long *scalar_ptr) __ksym;
 void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p) __ksym;
@@ -135,4 +140,8 @@  int bpf_kfunc_call_kernel_getsockname(struct addr_args *args) __ksym;
 int bpf_kfunc_call_kernel_getpeername(struct addr_args *args) __ksym;
 
 void bpf_kfunc_dynptr_test(struct bpf_dynptr *ptr, struct bpf_dynptr *ptr__nullable) __ksym;
+
+struct bpf_testmod_ctx *bpf_testmod_ctx_create(int *err) __ksym;
+void bpf_testmod_ctx_release(struct bpf_testmod_ctx *ctx) __ksym;
+
 #endif /* _BPF_TESTMOD_KFUNC_H */
diff --git a/tools/testing/selftests/bpf/prog_tests/kfunc_call.c b/tools/testing/selftests/bpf/prog_tests/kfunc_call.c
index 2eb71559713c..5b743212292f 100644
--- a/tools/testing/selftests/bpf/prog_tests/kfunc_call.c
+++ b/tools/testing/selftests/bpf/prog_tests/kfunc_call.c
@@ -78,6 +78,7 @@  static struct kfunc_test_params kfunc_tests[] = {
 	SYSCALL_TEST(kfunc_syscall_test, 0),
 	SYSCALL_NULL_CTX_TEST(kfunc_syscall_test_null, 0),
 	TC_TEST(kfunc_call_test_static_unused_arg, 0),
+	TC_TEST(kfunc_call_ctx, 0),
 };
 
 struct syscall_test_args {
diff --git a/tools/testing/selftests/bpf/progs/kfunc_call_test.c b/tools/testing/selftests/bpf/progs/kfunc_call_test.c
index cf68d1e48a0f..f502f755f567 100644
--- a/tools/testing/selftests/bpf/progs/kfunc_call_test.c
+++ b/tools/testing/selftests/bpf/progs/kfunc_call_test.c
@@ -177,4 +177,41 @@  int kfunc_call_test_static_unused_arg(struct __sk_buff *skb)
 	return actual != expected ? -1 : 0;
 }
 
+struct ctx_val {
+	struct bpf_testmod_ctx __kptr *ctx;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, 1);
+	__type(key, int);
+	__type(value, struct ctx_val);
+} ctx_map SEC(".maps");
+
+SEC("tc")
+int kfunc_call_ctx(struct __sk_buff *skb)
+{
+	struct bpf_testmod_ctx *ctx;
+	int err = 0;
+
+	ctx = bpf_testmod_ctx_create(&err);
+	if (!ctx && !err)
+		err = -1;
+	if (ctx) {
+		int key = 0;
+		struct ctx_val *ctx_val = bpf_map_lookup_elem(&ctx_map, &key);
+
+		/* Transfer ctx to map to be freed via implicit dtor call
+		 * on cleanup.
+		 */
+		if (ctx_val)
+			ctx = bpf_kptr_xchg(&ctx_val->ctx, ctx);
+		if (ctx) {
+			bpf_testmod_ctx_release(ctx);
+			err = -1;
+		}
+	}
+	return err;
+}
+
 char _license[] SEC("license") = "GPL";