All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Kaitao cheng" <kaitao.cheng@linux.dev>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH RESEND bpf-next v10 7/8] bpf: allow non-owning list-node args via __nonown_allowed
Date: Wed, 13 May 2026 22:22:58 +0000	[thread overview]
Message-ID: <20260513222258.AEB08C19425@smtp.kernel.org> (raw)
In-Reply-To: <20260512055919.95716-8-kaitao.cheng@linux.dev>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] bpf_list_add() dynamically frees the 'new' node on failure, but the verifier unconditionally assumes success, enabling a Use-After-Free.
- [Critical] bpf_list_del() does not invalidate the passed non-owning reference, leaving a direct alias to potentially freed memory (Use-After-Free).
--

commit abe3e2cc841c335580b071d1f616bb2c9d1deba4
Author: Kaitao Cheng <chengkaitao@kylinos.cn>

bpf: allow non-owning list-node args via __nonown_allowed

This commit introduces the __nonown_allowed annotation for list-node
arguments. It allows bpf_list_add, bpf_list_del, and bpf_list_is_first/last
to accept non-owning references.

> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
[ ... ]
> @@ -2571,10 +2571,10 @@ __bpf_kfunc int bpf_list_push_back_impl(struct bpf_list_head *head,
>  }
>  
>  __bpf_kfunc int bpf_list_add(struct bpf_list_head *head, struct bpf_list_node *new,
> -			     struct bpf_list_node *prev, struct btf_struct_meta *meta,
> -			     u64 off)
> +			     struct bpf_list_node *prev__nonown_allowed,
> +			     struct btf_struct_meta *meta, u64 off)
>  {
> -	struct bpf_list_node_kern *n = (void *)new, *p = (void *)prev;
> +	struct bpf_list_node_kern *n = (void *)new, *p = (void *)prev__nonown_allowed;
>  	struct list_head *prev_ptr = &p->list_head;
>  
>  	return __bpf_list_add(n, head, &prev_ptr, meta ? meta->record : NULL, off);

If a BPF program passes a non-owning reference from a completely different
list (protected by the same spinlock) to prev__nonown_allowed, can this
cause a use-after-free?

At runtime, __bpf_list_add() detects that the prev node doesn't belong to
the target head and aborts the insertion, calling __bpf_obj_drop_impl()
on the new node to free it back to the allocator.

However, the verifier unconditionally assumes bpf_list_add() successfully
consumed the new owning reference and safely converts it into a non-owning
reference in its internal state.

Because the verifier considers this non-owning reference valid until the
spinlock is unlocked, does this allow the BPF program to continuously
dereference the freed memory while holding the lock?

[ ... ]
> @@ -2620,9 +2620,9 @@ __bpf_kfunc struct bpf_list_node *bpf_list_pop_back(struct bpf_list_head *head)
>  }
>  
>  __bpf_kfunc struct bpf_list_node *bpf_list_del(struct bpf_list_head *head,
> -					       struct bpf_list_node *node)
> +				struct bpf_list_node *node__nonown_allowed)
>  {
> -	struct bpf_list_node_kern *kn = (void *)node;
> +	struct bpf_list_node_kern *kn = (void *)node__nonown_allowed;
>  
>  	/* verifier guarantees node is a list node rather than list head */
>  	return __bpf_list_del(head, &kn->list_head);

Does passing a non-owning reference here create an alias that leads to
a use-after-free?

When bpf_list_del() removes the node from the list, it returns a new owning
reference (with ref_obj_id > 0) pointing to the exact same object.

The verifier does not explicitly invalidate the original non-owning
reference argument (which has ref_obj_id == 0), so it remains fully valid
in the verifier's state until the active spinlock is released.

If the BPF program subsequently frees the object by passing the returned
owning reference to bpf_obj_drop(), won't the original non-owning reference
remain as a direct, unchecked alias to the freed memory?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260512055919.95716-1-kaitao.cheng@linux.dev?part=7

  parent reply	other threads:[~2026-05-13 22:22 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-12  5:59 [PATCH RESEND bpf-next v10 0/8] bpf: Extend the bpf_list family of APIs Kaitao cheng
2026-05-12  5:59 ` [PATCH RESEND bpf-next v10 1/8] bpf: refactor __bpf_list_del to take list node pointer Kaitao cheng
2026-05-12  6:41   ` bot+bpf-ci
2026-05-12  8:55     ` Kaitao Cheng
2026-05-13 22:30   ` Eduard Zingerman
2026-05-12  5:59 ` [PATCH RESEND bpf-next v10 2/8] bpf: clear list node owner and unlink before drop Kaitao cheng
2026-05-12  6:41   ` bot+bpf-ci
2026-05-13 22:53     ` Eduard Zingerman
2026-05-14  1:50       ` Alexei Starovoitov
2026-05-15  4:34         ` Kaitao Cheng
2026-05-15 18:24           ` Eduard Zingerman
2026-05-13  6:02   ` sashiko-bot
2026-05-12  5:59 ` [PATCH RESEND bpf-next v10 3/8] bpf: Introduce the bpf_list_del kfunc Kaitao cheng
2026-05-12  6:41   ` bot+bpf-ci
2026-05-12  9:36     ` Kaitao Cheng
2026-05-13 22:32   ` Eduard Zingerman
2026-05-12  5:59 ` [PATCH RESEND bpf-next v10 4/8] bpf: refactor __bpf_list_add to take insertion point via **prev_ptr Kaitao cheng
2026-05-13 22:33   ` Eduard Zingerman
2026-05-12  5:59 ` [PATCH RESEND bpf-next v10 5/8] bpf: Add bpf_list_add to insert node after a given list node Kaitao cheng
2026-05-12  6:41   ` bot+bpf-ci
2026-05-12 12:05     ` Kaitao Cheng
2026-05-13 20:44   ` sashiko-bot
2026-05-13 22:35   ` Eduard Zingerman
2026-05-12  5:59 ` [PATCH RESEND bpf-next v10 6/8] bpf: add bpf_list_is_first/last/empty kfuncs Kaitao cheng
2026-05-13 22:35   ` Eduard Zingerman
2026-05-12  5:59 ` [PATCH RESEND bpf-next v10 7/8] bpf: allow non-owning list-node args via __nonown_allowed Kaitao cheng
2026-05-12  6:41   ` bot+bpf-ci
2026-05-13 22:22   ` sashiko-bot [this message]
2026-05-13 22:37   ` Eduard Zingerman
2026-05-13 22:55     ` Eduard Zingerman
2026-05-12  5:59 ` [PATCH RESEND bpf-next v10 8/8] selftests/bpf: Add test cases for bpf_list_del/add/is_first/is_last/empty Kaitao cheng
2026-05-13 22:44   ` sashiko-bot

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=20260513222258.AEB08C19425@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=kaitao.cheng@linux.dev \
    --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.