From: "Kumar Kartikeya Dwivedi" <memxor@gmail.com>
To: "Daniel Borkmann" <daniel@iogearbox.net>,
"Pu Lehui" <pulehui@huaweicloud.com>, <bpf@vger.kernel.org>,
<linux-kernel@vger.kernel.org>
Cc: "Alexei Starovoitov" <ast@kernel.org>,
"Andrii Nakryiko" <andrii@kernel.org>,
"Eduard Zingerman" <eddyz87@gmail.com>,
"Martin KaFai Lau" <martin.lau@linux.dev>,
"Yonghong Song" <yonghong.song@linux.dev>,
"Song Liu" <song@kernel.org>, "Jiri Olsa" <jolsa@kernel.org>,
"Emil Tsalapatis" <emil@etsalapatis.com>,
"Pu Lehui" <pulehui@huawei.com>
Subject: Re: [PATCH bpf v4] bpf: Fix UAF when reading prog type in bpf_mprog_link
Date: Mon, 03 Aug 2026 21:14:27 +0200 [thread overview]
Message-ID: <DKFJREUTB93P.18LYK6Z4GHBUC@gmail.com> (raw)
In-Reply-To: <da7357fe-9d64-4e9c-a0f6-573a9761c8b2@iogearbox.net>
On Mon Aug 3, 2026 at 9:00 PM CEST, Daniel Borkmann wrote:
> On 7/28/26 9:42 AM, Pu Lehui wrote:
>> From: Pu Lehui <pulehui@huawei.com>
>>
>> In bpf_mprog_link, the code currently allows a user to pass an abnormal
>> non-netkit or non-tcx link via relative_fd. If a concurrent
>> BPF_LINK_UPDATE is performed on this abnormal link before dereferencing
>> link->prog->type in bpf_mprog_link(), it can trigger a UAF issue.
>>
>> CPU0 CPU1
>> netkit_link_prog_attach
>> bpf_mprog_attach
>> bpf_mprog_tuple_relative
>> bpf_mprog_link
>> /* non-netkit or non-tcx link */
>> link = bpf_link_get_from_fd(id_or_fd);
>> BPF_LINK_UPDATE on relative link
>> ...
>> old_prog = xchg(&link->link.prog, new_prog);
>> bpf_prog_put(old_prog);
>> if (type && link->prog->type != type) <-- trigger UAF
>>
>> The reason for the UAF is that each subsystem provides its own
>> protection for link->prog. Since there is no cross subsystem protection
>> (if not considering the RCU of prog tear down), dereferencing the prog
>> of an anchor link that does not belong to the current subsystem is not
>> safe: it may have been freed.
>>
>> To resolve this, we access link->prog under RCU protection to safely
>> fetch the pointer and guarantee its lifetime during the type check.
>> Meanwhile, add a comment explaining that when ptype == UNSPEC in
>> bpf_mprog_detach, it acts as a wildcard.
>>
>> Fixes: 053c8e1f235d ("bpf: Add generic attach/detach/query API for multi-progs")
>> Reported-by: Sashiko <sashiko-bot@kernel.org>
>> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
>> Signed-off-by: Pu Lehui <pulehui@huawei.com>
>> ---
>> v4:
>> - Access prog->type under rcu protection to simplify the repair logic,
>> and let unconditional detachment make sense when the bare prog or
>> link->prog being detached is NULL.
>> - Add Reviewed-by tag by Emil.
>> - Separate from patchset [0]. (Andrii)
>>
>> Link: https://lore.kernel.org/bpf/f87b53c0-8f00-45a6-82db-8242fa9b143f@huaweicloud.com [0]
>>
>> v3: https://lore.kernel.org/bpf/20260722072326.1545677-3-pulehui@huaweicloud.com
>> - BPF_F_LINK flag set means the relative id_or_fd is a link, not the object being
>> attached. We can not get the link while attach a bare prog with relative link.
>> So passing expected link type from callers of bpf_mprog_attach/detach. (Sashiko)
>> - Add comment to explain that why ptype == UNSPEC. (Emil)
>>
>> v2: https://lore.kernel.org/bpf/20260721041048.1394085-3-pulehui@huaweicloud.com
>> - Improve commit msg for patch 2. (Amery)
>>
>> v1: https://lore.kernel.org/bpf/20260720134547.1289964-3-pulehui@huaweicloud.com
>>
>> kernel/bpf/mprog.c | 17 +++++++++++++----
>> 1 file changed, 13 insertions(+), 4 deletions(-)
>>
>> diff --git a/kernel/bpf/mprog.c b/kernel/bpf/mprog.c
>> index 1394168062e8..af3e6c1c6a1f 100644
>> --- a/kernel/bpf/mprog.c
>> +++ b/kernel/bpf/mprog.c
>> @@ -10,6 +10,8 @@ static int bpf_mprog_link(struct bpf_tuple *tuple,
>> {
>> struct bpf_link *link = ERR_PTR(-EINVAL);
>> bool id = flags & BPF_F_ID;
>> + bool type_mismatch = false;
>> + struct bpf_prog *prog;
>>
>> if (id)
>> link = bpf_link_by_id(id_or_fd);
>> @@ -17,13 +19,20 @@ static int bpf_mprog_link(struct bpf_tuple *tuple,
>> link = bpf_link_get_from_fd(id_or_fd);
>> if (IS_ERR(link))
>> return PTR_ERR(link);
>> - if (type && link->prog->type != type) {
>> +
>> + rcu_read_lock();
>> + prog = READ_ONCE(link->prog);
>> + if (!prog || (type && prog->type != type))
>> + type_mismatch = true;
>> + rcu_read_unlock();
>
> Hm, what about progs under rcu_read_lock_trace cases, wouldn't the UAF
> still be there?
>
> Even though the diff is smaller, I'd kind of lean towards link->type
> testing since this addresses the underlying issue and avoids touching
> the prog completely.. do you want me to look into it and also add a
> BPF selftest to it as patch 2/2?
>
I think Pu's implication was that an RCU tasks trace GP would imply RCU gp, thus
using RCU read lock for protection in both cases would be sufficient for the
link's free path to wait for this reader. More context is available in [0]. I do
think this merits a comment for clarity, even in [0] I explicitly commented
about it everywhere even when it felt unnecessary.
I didn't closely follow this set of fixes (those in addition to this) yet but in
general, we also need to be careful about tracepoint BPF links. Those will only
wait for SRCU gp, which is not implied for rcu_read_lock() etc., so will need
their own distinct critical section. The fix pertaining to that was in [1].
[0]: https://lore.kernel.org/bpf/20260407162234.785270-1-memxor@gmail.com
[1]: https://lore.kernel.org/bpf/20260331211021.1632902-2-memxor@gmail.com
>> + if (type_mismatch) {
>> bpf_link_put(link);
>> return -EINVAL;
>> }
>>
>> tuple->link = link;
>> - tuple->prog = link->prog;
>> + tuple->prog = prog;
>> return 0;
>> }
>>
>> @@ -343,8 +352,8 @@ int bpf_mprog_detach(struct bpf_mprog_entry *entry,
>> if (!bpf_mprog_total(entry))
>> return -ENOENT;
>> ret = bpf_mprog_tuple_relative(&rtuple, id_or_fd, flags,
>> - prog ? prog->type :
>> - BPF_PROG_TYPE_UNSPEC);
>> + /* Use UNSPEC as wildcard when prog is NULL */
>> + prog ? prog->type : BPF_PROG_TYPE_UNSPEC);
>> if (ret)
>> return ret;
>> if (dtuple.prog) {
next prev parent reply other threads:[~2026-08-03 19:14 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 7:42 [PATCH bpf v4] bpf: Fix UAF when reading prog type in bpf_mprog_link Pu Lehui
2026-08-03 19:00 ` Daniel Borkmann
2026-08-03 19:14 ` Kumar Kartikeya Dwivedi [this message]
2026-08-05 4:11 ` Pu Lehui
2026-08-05 4:18 ` Pu Lehui
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=DKFJREUTB93P.18LYK6Z4GHBUC@gmail.com \
--to=memxor@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=pulehui@huawei.com \
--cc=pulehui@huaweicloud.com \
--cc=song@kernel.org \
--cc=yonghong.song@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox