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 |
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!
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.
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 --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); }
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(-)