From: Kaitao Cheng <kaitao.cheng@linux.dev>
To: sashiko-reviews@lists.linux.dev
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v11 2/8] bpf: clear list node owner and unlink before drop
Date: Thu, 21 May 2026 14:11:11 +0800 [thread overview]
Message-ID: <23c93af8-c025-4c39-b0df-b84562756c30@linux.dev> (raw)
In-Reply-To: <20260521043023.A0BD71F000E9@smtp.kernel.org>
在 2026/5/21 12:30, sashiko-bot@kernel.org 写道:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>
> New issues:
> - [High] Potentially unbounded O(N) list traversal with interrupts disabled in `bpf_list_head_free()`.
>
> Pre-existing issues:
> - [High] The patch fixes the stale `node->owner` issue for `bpf_list_head_free()` but fails to apply the equivalent fix for `bpf_rb_root_free()`, leaving `bpf_rbtree_remove()` vulnerable to the same memory corruption.
> --
>
> commit 59439e3ee3f8d57af8635b521393d245d26bbdf4
> Author: Kaitao Cheng <chengkaitao@kylinos.cn>
>
> bpf: clear list node owner and unlink before drop
>
> This commit fixes an issue where refcounted BPF list nodes can outlive their
> list head and retain a stale owner pointer. To prevent memory corruption if a
> new list is allocated at the same address, it moves nodes to a private drain
> list under the spinlock, poisons their owner pointers, and unlinks them
> before dropping the objects.
>
>> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
>> index 094457c3e6d37..59855b434f0b2 100644
>> --- a/kernel/bpf/helpers.c
>> +++ b/kernel/bpf/helpers.c
>
> [ ... ]
>
>> @@ -2261,20 +2262,30 @@ void bpf_list_head_free(const struct btf_field *field, void *list_head,
>> __bpf_spin_lock_irqsave(spin_lock);
>> if (!head->next || list_empty(head))
>> goto unlock;
>> - head = head->next;
>> + list_for_each_safe(pos, n, head) {
>> + struct bpf_list_node_kern *node;
>> +
>> + node = container_of(pos, struct bpf_list_node_kern, list_head);
>> + WRITE_ONCE(node->owner, BPF_PTR_POISON);
>> + list_move_tail(pos, &drain);
>> + }
>
> [Severity: High]
> Could this new loop potentially cause a long CPU stall?
>
> Since __bpf_spin_lock_irqsave() disables local interrupts, this O(N) list
> traversal executes with interrupts disabled.
>
> BPF lists do not have a hard size limit, so if a program accumulates a
> very large number of elements in a single list, could iterating over them
> here trigger the NMI watchdog or cause severe latency spikes?
This is merely address-taking and assignment, so it is almost negligible
in cost, and the likelihood of causing a soft lockup is very low.
>> unlock:
>> - INIT_LIST_HEAD(orig_head);
>> + INIT_LIST_HEAD(head);
>> __bpf_spin_unlock_irqrestore(spin_lock);
>>
>> - while (head != orig_head) {
>> - void *obj = head;
>> + while (!list_empty(&drain)) {
>> + struct bpf_list_node_kern *node;
>>
>> - obj -= field->graph_root.node_offset;
>> - head = head->next;
>> + pos = drain.next;
>> + node = container_of(pos, struct bpf_list_node_kern, list_head);
>> + list_del_init(pos);
>> + /* Ensure __bpf_list_add() sees the node as unlinked. */
>> + smp_store_release(&node->owner, NULL);
>> /* The contained type can also have resources, including a
>> * bpf_list_head which needs to be freed.
>> */
>> - __bpf_obj_drop_impl(obj, field->graph_root.value_rec, false);
>> + __bpf_obj_drop_impl((char *)pos - field->graph_root.node_offset,
>> + field->graph_root.value_rec, false);
>> }
>> }
>
> [Severity: High]
> This isn't a bug introduced by this patch, but does bpf_rb_root_free() need
> the exact same fix?
>
> When draining an rbtree, bpf_rb_root_free() calls __bpf_obj_drop_impl() on
> each node without clearing the node_internal->owner or unlinking the nodes.
>
> If a surviving refcounted rb-node retains a pointer to the freed rb_root,
> and a new bpf_rb_root is allocated at the old address, wouldn't a call to
> bpf_rbtree_remove(new_root, stale_node) erroneously bypass the ownership
> check and invoke rb_erase_cached() with stale tree pointers?
I will probably send a separate fix patch later; this issue does not need
to be addressed in this patch series.
--
Thanks
Kaitao Cheng
next prev parent reply other threads:[~2026-05-21 6:12 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-21 3:22 [PATCH bpf-next v11 0/8] bpf: Extend the bpf_list family of APIs Kaitao Cheng
2026-05-21 3:22 ` [PATCH bpf-next v11 1/8] bpf: refactor __bpf_list_del to take list node pointer Kaitao Cheng
2026-05-21 3:23 ` [PATCH bpf-next v11 2/8] bpf: clear list node owner and unlink before drop Kaitao Cheng
2026-05-21 4:08 ` bot+bpf-ci
2026-05-21 4:30 ` sashiko-bot
2026-05-21 6:11 ` Kaitao Cheng [this message]
2026-05-21 3:23 ` [PATCH bpf-next v11 3/8] bpf: allow non-owning list-node args via __nonown_allowed Kaitao Cheng
2026-05-21 4:08 ` bot+bpf-ci
2026-05-21 6:29 ` Kaitao Cheng
2026-05-21 3:23 ` [PATCH bpf-next v11 4/8] bpf: Introduce the bpf_list_del kfunc Kaitao Cheng
2026-05-21 4:08 ` bot+bpf-ci
2026-05-21 6:59 ` Kaitao Cheng
2026-05-21 3:23 ` [PATCH bpf-next v11 5/8] bpf: refactor __bpf_list_add to take insertion point via **prev_ptr Kaitao Cheng
2026-05-21 3:23 ` [PATCH bpf-next v11 6/8] bpf: Add bpf_list_add to insert node after a given list node Kaitao Cheng
2026-05-21 4:08 ` bot+bpf-ci
2026-05-21 7:35 ` Kaitao Cheng
2026-05-21 12:49 ` sashiko-bot
2026-05-21 3:23 ` [PATCH bpf-next v11 7/8] bpf: add bpf_list_is_first/last/empty kfuncs Kaitao Cheng
2026-05-21 13:29 ` sashiko-bot
2026-05-21 3:23 ` [PATCH bpf-next v11 8/8] selftests/bpf: Add test cases for bpf_list_del/add/is_first/is_last/empty Kaitao Cheng
2026-05-21 4:08 ` bot+bpf-ci
2026-05-21 10:00 ` [PATCH bpf-next v11 0/8] bpf: Extend the bpf_list family of APIs patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=23c93af8-c025-4c39-b0df-b84562756c30@linux.dev \
--to=kaitao.cheng@linux.dev \
--cc=bpf@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.