diff mbox series

[v1,bpf-next] bpf: Disable migration when freeing stashed local kptr using obj drop

Message ID 20230313214641.3731908-1-davemarchevsky@fb.com (mailing list archive)
State Accepted
Commit 9e36a204bd43553a9cd4bd574612cd9a5df791ea
Delegated to: BPF
Headers show
Series [v1,bpf-next] bpf: Disable migration when freeing stashed local kptr using obj drop | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-5 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 success Logs for build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-7 success Logs for llvm-toolchain
bpf/vmtest-bpf-next-VM_Test-8 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-2 success Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-3 success Logs for build for aarch64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-4 success Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for test_maps on aarch64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-12 success Logs for test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-14 fail Logs for test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-15 fail Logs for test_progs on aarch64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-17 fail Logs for test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 fail Logs for test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-19 fail Logs for test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 fail Logs for test_progs_no_alu32 on aarch64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-22 fail Logs for test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 fail Logs for test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-25 success Logs for test_progs_no_alu32_parallel on aarch64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-26 success Logs for test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for test_progs_no_alu32_parallel on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-28 success Logs for test_progs_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-29 success Logs for test_progs_parallel on aarch64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-30 success Logs for test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-31 success Logs for test_progs_parallel on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-32 success Logs for test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-33 success Logs for test_verifier on aarch64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-34 success Logs for test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-35 success Logs for test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-36 success Logs for test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-21 fail Logs for test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 fail Logs for test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for test_progs_no_alu32_parallel on aarch64 with gcc
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for bpf-next, async
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 success Errors and warnings before: 1469 this patch: 1469
netdev/cc_maintainers warning 8 maintainers not CCed: song@kernel.org sdf@google.com haoluo@google.com yhs@fb.com john.fastabend@gmail.com kpsingh@kernel.org jolsa@kernel.org martin.lau@linux.dev
netdev/build_clang success Errors and warnings before: 168 this patch: 168
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 Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 1463 this patch: 1463
netdev/checkpatch warning WARNING: Reported-by: should be immediately followed by Link: with a URL to the report WARNING: line length of 86 exceeds 80 columns WARNING: line length of 94 exceeds 80 columns
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-11 success Logs for test_maps on s390x with gcc

Commit Message

Dave Marchevsky March 13, 2023, 9:46 p.m. UTC
When a local kptr is stashed in a map and freed when the map goes away,
currently an error like the below appears:

[   39.195695] BUG: using smp_processor_id() in preemptible [00000000] code: kworker/u32:15/2875
[   39.196549] caller is bpf_mem_free+0x56/0xc0
[   39.196958] CPU: 15 PID: 2875 Comm: kworker/u32:15 Tainted: G           O       6.2.0-13016-g22df776a9a86 #4477
[   39.197897] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014
[   39.198949] Workqueue: events_unbound bpf_map_free_deferred
[   39.199470] Call Trace:
[   39.199703]  <TASK>
[   39.199911]  dump_stack_lvl+0x60/0x70
[   39.200267]  check_preemption_disabled+0xbf/0xe0
[   39.200704]  bpf_mem_free+0x56/0xc0
[   39.201032]  ? bpf_obj_new_impl+0xa0/0xa0
[   39.201430]  bpf_obj_free_fields+0x1cd/0x200
[   39.201838]  array_map_free+0xad/0x220
[   39.202193]  ? finish_task_switch+0xe5/0x3c0
[   39.202614]  bpf_map_free_deferred+0xea/0x210
[   39.203006]  ? lockdep_hardirqs_on_prepare+0xe/0x220
[   39.203460]  process_one_work+0x64f/0xbe0
[   39.203822]  ? pwq_dec_nr_in_flight+0x110/0x110
[   39.204264]  ? do_raw_spin_lock+0x107/0x1c0
[   39.204662]  ? lockdep_hardirqs_on_prepare+0xe/0x220
[   39.205107]  worker_thread+0x74/0x7a0
[   39.205451]  ? process_one_work+0xbe0/0xbe0
[   39.205818]  kthread+0x171/0x1a0
[   39.206111]  ? kthread_complete_and_exit+0x20/0x20
[   39.206552]  ret_from_fork+0x1f/0x30
[   39.206886]  </TASK>

This happens because the call to __bpf_obj_drop_impl I added in the patch
adding support for stashing local kptrs doesn't disable migration. Prior
to that patch, __bpf_obj_drop_impl logic only ran when called by a BPF
progarm, whereas now it can be called from map free path, so it's
necessary to explicitly disable migration.

Also, refactor a bit to just call __bpf_obj_drop_impl directly instead
of bothering w/ dtor union and setting pointer-to-obj_drop.

Fixes: c8e187540914 ("bpf: Support __kptr to local kptrs")
Reported-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
---
 include/linux/bpf.h  | 12 ++++--------
 kernel/bpf/btf.c     |  4 +---
 kernel/bpf/syscall.c | 10 +++++++---
 3 files changed, 12 insertions(+), 14 deletions(-)

Comments

patchwork-bot+netdevbpf@kernel.org March 14, 2023, midnight UTC | #1
Hello:

This patch was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Mon, 13 Mar 2023 14:46:41 -0700 you wrote:
> When a local kptr is stashed in a map and freed when the map goes away,
> currently an error like the below appears:
> 
> [   39.195695] BUG: using smp_processor_id() in preemptible [00000000] code: kworker/u32:15/2875
> [   39.196549] caller is bpf_mem_free+0x56/0xc0
> [   39.196958] CPU: 15 PID: 2875 Comm: kworker/u32:15 Tainted: G           O       6.2.0-13016-g22df776a9a86 #4477
> [   39.197897] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014
> [   39.198949] Workqueue: events_unbound bpf_map_free_deferred
> [   39.199470] Call Trace:
> [   39.199703]  <TASK>
> [   39.199911]  dump_stack_lvl+0x60/0x70
> [   39.200267]  check_preemption_disabled+0xbf/0xe0
> [   39.200704]  bpf_mem_free+0x56/0xc0
> [   39.201032]  ? bpf_obj_new_impl+0xa0/0xa0
> [   39.201430]  bpf_obj_free_fields+0x1cd/0x200
> [   39.201838]  array_map_free+0xad/0x220
> [   39.202193]  ? finish_task_switch+0xe5/0x3c0
> [   39.202614]  bpf_map_free_deferred+0xea/0x210
> [   39.203006]  ? lockdep_hardirqs_on_prepare+0xe/0x220
> [   39.203460]  process_one_work+0x64f/0xbe0
> [   39.203822]  ? pwq_dec_nr_in_flight+0x110/0x110
> [   39.204264]  ? do_raw_spin_lock+0x107/0x1c0
> [   39.204662]  ? lockdep_hardirqs_on_prepare+0xe/0x220
> [   39.205107]  worker_thread+0x74/0x7a0
> [   39.205451]  ? process_one_work+0xbe0/0xbe0
> [   39.205818]  kthread+0x171/0x1a0
> [   39.206111]  ? kthread_complete_and_exit+0x20/0x20
> [   39.206552]  ret_from_fork+0x1f/0x30
> [   39.206886]  </TASK>
> 
> [...]

Here is the summary with links:
  - [v1,bpf-next] bpf: Disable migration when freeing stashed local kptr using obj drop
    https://git.kernel.org/bpf/bpf-next/c/9e36a204bd43

You are awesome, thank you!
John Fastabend March 14, 2023, 5:35 a.m. UTC | #2
patchwork-bot+netdevbpf@ wrote:
> Hello:
> 
> This patch was applied to bpf/bpf-next.git (master)
> by Alexei Starovoitov <ast@kernel.org>:
> 
> On Mon, 13 Mar 2023 14:46:41 -0700 you wrote:
> > When a local kptr is stashed in a map and freed when the map goes away,
> > currently an error like the below appears:
> > 
> > [   39.195695] BUG: using smp_processor_id() in preemptible [00000000] code: kworker/u32:15/2875
> > [   39.196549] caller is bpf_mem_free+0x56/0xc0
> > [   39.196958] CPU: 15 PID: 2875 Comm: kworker/u32:15 Tainted: G           O       6.2.0-13016-g22df776a9a86 #4477
> > [   39.197897] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014
> > [   39.198949] Workqueue: events_unbound bpf_map_free_deferred
> > [   39.199470] Call Trace:
> > [   39.199703]  <TASK>
> > [   39.199911]  dump_stack_lvl+0x60/0x70
> > [   39.200267]  check_preemption_disabled+0xbf/0xe0
> > [   39.200704]  bpf_mem_free+0x56/0xc0
> > [   39.201032]  ? bpf_obj_new_impl+0xa0/0xa0
> > [   39.201430]  bpf_obj_free_fields+0x1cd/0x200
> > [   39.201838]  array_map_free+0xad/0x220
> > [   39.202193]  ? finish_task_switch+0xe5/0x3c0
> > [   39.202614]  bpf_map_free_deferred+0xea/0x210
> > [   39.203006]  ? lockdep_hardirqs_on_prepare+0xe/0x220
> > [   39.203460]  process_one_work+0x64f/0xbe0
> > [   39.203822]  ? pwq_dec_nr_in_flight+0x110/0x110
> > [   39.204264]  ? do_raw_spin_lock+0x107/0x1c0
> > [   39.204662]  ? lockdep_hardirqs_on_prepare+0xe/0x220
> > [   39.205107]  worker_thread+0x74/0x7a0
> > [   39.205451]  ? process_one_work+0xbe0/0xbe0
> > [   39.205818]  kthread+0x171/0x1a0
> > [   39.206111]  ? kthread_complete_and_exit+0x20/0x20
> > [   39.206552]  ret_from_fork+0x1f/0x30
> > [   39.206886]  </TASK>
> > 
> > [...]
> 
> Here is the summary with links:
>   - [v1,bpf-next] bpf: Disable migration when freeing stashed local kptr using obj drop
>     https://git.kernel.org/bpf/bpf-next/c/9e36a204bd43
> 
> You are awesome, thank you!
> -- 
> Deet-doot-dot, I am a bot.
> https://korg.docs.kernel.org/patchwork/pwbot.html
> 
> 

Alexei is quick but FWIW LGTM as well.
Alexei Starovoitov March 15, 2023, 12:07 a.m. UTC | #3
On Mon, Mar 13, 2023 at 10:35 PM John Fastabend
<john.fastabend@gmail.com> wrote:
>
> >
> > Here is the summary with links:
> >   - [v1,bpf-next] bpf: Disable migration when freeing stashed local kptr using obj drop
> >     https://git.kernel.org/bpf/bpf-next/c/9e36a204bd43
> >
> > You are awesome, thank you!
> > --
> > Deet-doot-dot, I am a bot.
> > https://korg.docs.kernel.org/patchwork/pwbot.html
> >
> >
>
> Alexei is quick but FWIW LGTM as well.

Thanks for the review.
Just want to remind everyone that "patch in the tree"
is not a final stage. The patch can be reverted and if there are
review comments they need to be taken just as seriously as
before the patch was applied.
diff mbox series

Patch

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 756b85f0d0d3..71cc92a4ba48 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -190,18 +190,14 @@  enum btf_field_type {
 };
 
 typedef void (*btf_dtor_kfunc_t)(void *);
-typedef void (*btf_dtor_obj_drop)(void *, const struct btf_record *);
 
 struct btf_field_kptr {
 	struct btf *btf;
 	struct module *module;
-	union {
-		/* dtor used if btf_is_kernel(btf), otherwise the type
-		 * is program-allocated and obj_drop is used
-		 */
-		btf_dtor_kfunc_t dtor;
-		btf_dtor_obj_drop obj_drop;
-	};
+	/* dtor used if btf_is_kernel(btf), otherwise the type is
+	 * program-allocated, dtor is NULL,  and __bpf_obj_drop_impl is used
+	 */
+	btf_dtor_kfunc_t dtor;
 	u32 btf_id;
 };
 
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 66fad7a16b6c..b7e5a5510b91 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3551,8 +3551,6 @@  static int btf_find_field(const struct btf *btf, const struct btf_type *t,
 	return -EINVAL;
 }
 
-extern void __bpf_obj_drop_impl(void *p, const struct btf_record *rec);
-
 static int btf_parse_kptr(const struct btf *btf, struct btf_field *field,
 			  struct btf_field_info *info)
 {
@@ -3578,7 +3576,7 @@  static int btf_parse_kptr(const struct btf *btf, struct btf_field *field,
 		/* Type exists only in program BTF. Assume that it's a MEM_ALLOC
 		 * kptr allocated via bpf_obj_new
 		 */
-		field->kptr.dtor = (void *)&__bpf_obj_drop_impl;
+		field->kptr.dtor = NULL;
 		id = info->kptr.type_id;
 		kptr_btf = (struct btf *)btf;
 		btf_get(kptr_btf);
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 0684febc447a..5b88301a2ae0 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -650,6 +650,8 @@  void bpf_obj_free_timer(const struct btf_record *rec, void *obj)
 	bpf_timer_cancel_and_free(obj + rec->timer_off);
 }
 
+extern void __bpf_obj_drop_impl(void *p, const struct btf_record *rec);
+
 void bpf_obj_free_fields(const struct btf_record *rec, void *obj)
 {
 	const struct btf_field *fields;
@@ -679,9 +681,11 @@  void bpf_obj_free_fields(const struct btf_record *rec, void *obj)
 				pointee_struct_meta = btf_find_struct_meta(field->kptr.btf,
 									   field->kptr.btf_id);
 				WARN_ON_ONCE(!pointee_struct_meta);
-				field->kptr.obj_drop(xchgd_field, pointee_struct_meta ?
-								  pointee_struct_meta->record :
-								  NULL);
+				migrate_disable();
+				__bpf_obj_drop_impl(xchgd_field, pointee_struct_meta ?
+								 pointee_struct_meta->record :
+								 NULL);
+				migrate_enable();
 			} else {
 				field->kptr.dtor(xchgd_field);
 			}