BPF List
 help / color / mirror / Atom feed
* [PATCH bpf] bpf: Skip unsettled links in link iterator
@ 2026-09-14 17:02 Weiming Shi
  2026-09-14 17:16 ` sashiko-bot
  2026-09-17 22:10 ` patchwork-bot+netdevbpf
  0 siblings, 2 replies; 3+ messages in thread
From: Weiming Shi @ 2026-09-14 17:02 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
	Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
	Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
	Emil Tsalapatis, Ihor Solodrai
  Cc: bpf, linux-kernel, Dmitrii Dolgov, Xiang Mei, Weiming Shi

bpf_link_prime() inserts a link into link_idr before anon_inode_getfile()
succeeds and before bpf_link_settle() publishes the ID in link->id.
bpf_link_by_id() treats such an ID-zero link as unsettled, but the link
iterator takes a reference without this check.

If anon_inode_getfile() then fails, the creator removes the ID and frees
its still-private link directly.  The iterator is left with a dangling
reference and its next bpf_link_put() accesses freed memory.

Treat ID-zero entries as transient in bpf_link_get_curr_or_next(), just as
bpf_link_by_id() does.

  BUG: KASAN: slab-use-after-free in bpf_link_put
  Write of size 8 by task exp/384
  Call Trace:
  bpf_link_put                    kernel/bpf/syscall.c:3372
  bpf_link_seq_next               kernel/bpf/link_iter.c:33
  bpf_seq_read                    kernel/bpf/bpf_iter.c:158
  vfs_read                        fs/read_write.c:572
  ksys_read                       fs/read_write.c:716
  do_syscall_64                   arch/x86/entry/syscall_64.c:84
  entry_SYSCALL_64_after_hwframe  arch/x86/entry/entry_64.S:121
  Kernel panic - not syncing: KASAN: panic_on_warn set ...

Fixes: 9f8836127308 ("bpf: Add bpf_link iterator")
Reported-by: Xiang Mei <xmei5@asu.edu>
Assisted-by: LLM
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
 kernel/bpf/syscall.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index a8c9b2865c5df..2870ff3167d42 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -6044,7 +6044,10 @@ struct bpf_link *bpf_link_get_curr_or_next(u32 *id)
 again:
 	link = idr_get_next(&link_idr, id);
 	if (link) {
-		link = bpf_link_inc_not_zero(link);
+		if (link->id)
+			link = bpf_link_inc_not_zero(link);
+		else
+			link = ERR_PTR(-EAGAIN);
 		if (IS_ERR(link)) {
 			(*id)++;
 			goto again;
-- 
2.55.0

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH bpf] bpf: Skip unsettled links in link iterator
  2026-09-14 17:02 [PATCH bpf] bpf: Skip unsettled links in link iterator Weiming Shi
@ 2026-09-14 17:16 ` sashiko-bot
  2026-09-17 22:10 ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-09-14 17:16 UTC (permalink / raw)
  To: Weiming Shi; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Preexisting race condition between btf_put() and btf_idr iteration causes refcount saturation and Use-After-Free.
--

commit c9cafeb12312032e3482a8253aec4ec8da20e91f
Author: Weiming Shi <bestswngs@gmail.com>

bpf: Skip unsettled links in link iterator

This commit fixes a use-after-free in the BPF link iterator by ensuring
unsettled links (with ID zero) are skipped during IDR traversal. It prevents
taking references on transient links that might be freed concurrently.

> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 853b47f813842..244a939b9d2da 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -6042,7 +6042,10 @@ struct bpf_link *bpf_link_get_curr_or_next(u32 *id)
>  again:
>  	link = idr_get_next(&link_idr, id);
>  	if (link) {
> -		link = bpf_link_inc_not_zero(link);
> +		if (link->id)
> +			link = bpf_link_inc_not_zero(link);
> +		else
> +			link = ERR_PTR(-EAGAIN);

[Severity: High]
This isn't a bug introduced by this patch, but while looking at this fix for
bpf_link IDR iteration, is there a similar race condition in the BTF IDR
iteration?

In kernel/bpf/btf.c, btf_put() decrements the refcount outside the IDR lock:

kernel/bpf/btf.c:btf_put() {
    if (btf && refcount_dec_and_test(&btf->refcnt)) {
        ...
        /* btf_free_id(btf) is called later, acquiring the lock */

Concurrently, iterators like bpf_find_btf_id() or bpf_core_add_cands()
iterate over btf_idr holding btf_idr_lock and unconditionally increment
the refcount via btf_get() (which maps to refcount_inc()).

Could this lead to btf_get() incrementing a 0-refcount object before it is
removed from the IDR?

If the refcount is incremented from 0, it saturates the refcount and triggers
a kernel warning.

Furthermore, after the iterator drops btf_idr_lock to do a slow linear
search without holding rcu_read_lock(), btf_put() can proceed to remove
the ID and schedule the RCU callback to free the BTF memory.

Does this expose the iterator to a use-after-free when accessing the BTF
object later?

Would it be safer to use refcount_inc_not_zero() during BTF IDR traversal,
similar to how bpf_link_inc_not_zero() is used here?

>  		if (IS_ERR(link)) {
>  			(*id)++;
>  			goto again;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260914170206.170723-2-bestswngs@gmail.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH bpf] bpf: Skip unsettled links in link iterator
  2026-09-14 17:02 [PATCH bpf] bpf: Skip unsettled links in link iterator Weiming Shi
  2026-09-14 17:16 ` sashiko-bot
@ 2026-09-17 22:10 ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-17 22:10 UTC (permalink / raw)
  To: Weiming Shi
  Cc: ast, daniel, john.fastabend, andrii, eddyz87, memxor, martin.lau,
	song, yonghong.song, jolsa, emil, ihor.solodrai, bpf,
	linux-kernel, 9erthalion6, xmei5

Hello:

This patch was applied to bpf/bpf.git (master)
by Andrii Nakryiko <andrii@kernel.org>:

On Tue, 15 Sep 2026 01:02:07 +0800 you wrote:
> bpf_link_prime() inserts a link into link_idr before anon_inode_getfile()
> succeeds and before bpf_link_settle() publishes the ID in link->id.
> bpf_link_by_id() treats such an ID-zero link as unsettled, but the link
> iterator takes a reference without this check.
> 
> If anon_inode_getfile() then fails, the creator removes the ID and frees
> its still-private link directly.  The iterator is left with a dangling
> reference and its next bpf_link_put() accesses freed memory.
> 
> [...]

Here is the summary with links:
  - [bpf] bpf: Skip unsettled links in link iterator
    https://git.kernel.org/bpf/bpf/c/50e80e2bb5e2

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-17 22:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-14 17:02 [PATCH bpf] bpf: Skip unsettled links in link iterator Weiming Shi
2026-09-14 17:16 ` sashiko-bot
2026-09-17 22:10 ` patchwork-bot+netdevbpf

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