* [PATCH bpf-next 0/2] bpf: Require CAP_BPF for pseudo-BTF ksym loads
@ 2026-06-19 16:04 Nuoqi Gui
2026-06-19 16:04 ` [PATCH bpf-next 1/2] " Nuoqi Gui
2026-06-19 16:04 ` [PATCH bpf-next 2/2] selftests/bpf: Cover pseudo-BTF ksym load capability Nuoqi Gui
0 siblings, 2 replies; 5+ messages in thread
From: Nuoqi Gui @ 2026-06-19 16:04 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, Hao Luo
Cc: John Fastabend, Martin KaFai Lau, Shuah Khan, bpf,
linux-kselftest, linux-kernel, Nuoqi Gui
BPF_PSEUDO_BTF_ID resolves a BTF id for a kernel symbol into a concrete
kernel address before the main verifier pass. A raw ldimm64 using this
pseudo source can currently reach kallsyms resolution without CAP_BPF,
and verbose verifier logging can print the rewritten immediate.
Require CAP_BPF before pseudo-BTF ksym materialization and add focused
verifier selftests for both the no-CAP rejection and the CAP_BPF-allowed
case.
Fixes: 4976b718c3551 ("bpf: Introduce pseudo_btf_id")
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
Nuoqi Gui (2):
bpf: Require CAP_BPF for pseudo-BTF ksym loads
selftests/bpf: Cover pseudo-BTF ksym load capability
kernel/bpf/verifier.c | 5 ++++
.../testing/selftests/bpf/progs/verifier_unpriv.c | 32 ++++++++++++++++++++++
2 files changed, 37 insertions(+)
---
base-commit: a3847994b4d20c0701ccc54fe110920ea78e73dc
change-id: 20260619-f01-13-pseudo-btf-id-cap-bpf-585f98eac268
Best regards,
--
Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH bpf-next 1/2] bpf: Require CAP_BPF for pseudo-BTF ksym loads
2026-06-19 16:04 [PATCH bpf-next 0/2] bpf: Require CAP_BPF for pseudo-BTF ksym loads Nuoqi Gui
@ 2026-06-19 16:04 ` Nuoqi Gui
2026-06-19 20:05 ` Eduard Zingerman
2026-06-19 16:04 ` [PATCH bpf-next 2/2] selftests/bpf: Cover pseudo-BTF ksym load capability Nuoqi Gui
1 sibling, 1 reply; 5+ messages in thread
From: Nuoqi Gui @ 2026-06-19 16:04 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, Hao Luo
Cc: John Fastabend, Martin KaFai Lau, Shuah Khan, bpf,
linux-kselftest, linux-kernel, Nuoqi Gui
BPF_PSEUDO_BTF_ID is resolved before the main verifier pass. The resolver
looks up the referenced kernel symbol through kallsyms and rewrites the
ldimm64 immediate to the concrete address that later becomes verifier
state.
Require CAP_BPF before doing that materialization. This keeps typed ksym
address resolution on the privileged side and prevents loaders without
CAP_BPF from receiving a verifier log that contains the resolved address.
Fixes: 4976b718c3551 ("bpf: Introduce pseudo_btf_id")
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
kernel/bpf/verifier.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index ed7ba0e6a9ce..dbf5df995fc2 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -17639,6 +17639,11 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
int btf_fd;
int err;
+ if (!env->bpf_capable) {
+ verbose(env, "BPF_PSEUDO_BTF_ID loads require CAP_BPF\n");
+ return -EACCES;
+ }
+
btf_fd = insn[1].imm;
if (btf_fd) {
btf = btf_get_by_fd(btf_fd);
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH bpf-next 2/2] selftests/bpf: Cover pseudo-BTF ksym load capability
2026-06-19 16:04 [PATCH bpf-next 0/2] bpf: Require CAP_BPF for pseudo-BTF ksym loads Nuoqi Gui
2026-06-19 16:04 ` [PATCH bpf-next 1/2] " Nuoqi Gui
@ 2026-06-19 16:04 ` Nuoqi Gui
1 sibling, 0 replies; 5+ messages in thread
From: Nuoqi Gui @ 2026-06-19 16:04 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, Hao Luo
Cc: John Fastabend, Martin KaFai Lau, Shuah Khan, bpf,
linux-kselftest, linux-kernel, Nuoqi Gui
Add verifier_unpriv cases for a raw socket-filter load of the typed ksym
bpf_prog_active.
The first case verifies that a program without CAP_BPF is rejected before
the pseudo-BTF ksym is materialized. The second case grants CAP_BPF in
the unprivileged test-loader mode and verifies that the same load remains
accepted when the capability requirement is satisfied.
Declare the typed ksym in verifier_unpriv.c so these raw verifier tests do
not need a separate selftest header.
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
.../testing/selftests/bpf/progs/verifier_unpriv.c | 32 ++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/verifier_unpriv.c b/tools/testing/selftests/bpf/progs/verifier_unpriv.c
index c16f8382cf17..90e7ffc426ae 100644
--- a/tools/testing/selftests/bpf/progs/verifier_unpriv.c
+++ b/tools/testing/selftests/bpf/progs/verifier_unpriv.c
@@ -6,6 +6,8 @@
#include "../../../include/linux/filter.h"
#include "bpf_misc.h"
+extern const int bpf_prog_active __ksym;
+
#define BPF_SK_LOOKUP(func) \
/* struct bpf_sock_tuple tuple = {} */ \
"r2 = 0;" \
@@ -77,6 +79,36 @@ __naked void dummy_prog_loop1_socket(void)
: __clobber_all);
}
+SEC("socket")
+__description("unpriv: pseudo btf id ksym requires CAP_BPF")
+__success __failure_unpriv
+__msg_unpriv("BPF_PSEUDO_BTF_ID loads require CAP_BPF")
+__retval(0)
+__naked void pseudo_btf_id_ksym_requires_cap_bpf(void)
+{
+ asm volatile ("r1 = %[bpf_prog_active] ll;"
+ "r0 = 0;"
+ "exit;"
+ :
+ : __imm_addr(bpf_prog_active)
+ : __clobber_all);
+}
+
+SEC("socket")
+__description("unpriv: pseudo btf id ksym works with CAP_BPF")
+__success_unpriv
+__caps_unpriv(CAP_BPF)
+__retval_unpriv(0)
+__naked void pseudo_btf_id_ksym_with_cap_bpf(void)
+{
+ asm volatile ("r1 = %[bpf_prog_active] ll;"
+ "r0 = 0;"
+ "exit;"
+ :
+ : __imm_addr(bpf_prog_active)
+ : __clobber_all);
+}
+
SEC("socket")
__description("unpriv: return pointer")
__success __failure_unpriv __msg_unpriv("R0 leaks addr")
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: Require CAP_BPF for pseudo-BTF ksym loads
2026-06-19 16:04 ` [PATCH bpf-next 1/2] " Nuoqi Gui
@ 2026-06-19 20:05 ` Eduard Zingerman
2026-06-20 15:34 ` Nuoqi Gui
0 siblings, 1 reply; 5+ messages in thread
From: Eduard Zingerman @ 2026-06-19 20:05 UTC (permalink / raw)
To: Nuoqi Gui, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Hao Luo
Cc: John Fastabend, Martin KaFai Lau, Shuah Khan, bpf,
linux-kselftest, linux-kernel
On Sat, 2026-06-20 at 00:04 +0800, Nuoqi Gui wrote:
> BPF_PSEUDO_BTF_ID is resolved before the main verifier pass. The resolver
> looks up the referenced kernel symbol through kallsyms and rewrites the
> ldimm64 immediate to the concrete address that later becomes verifier
> state.
>
> Require CAP_BPF before doing that materialization. This keeps typed ksym
> address resolution on the privileged side and prevents loaders without
> CAP_BPF from receiving a verifier log that contains the resolved address.
>
> Fixes: 4976b718c3551 ("bpf: Introduce pseudo_btf_id")
> Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
> ---
> kernel/bpf/verifier.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index ed7ba0e6a9ce..dbf5df995fc2 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -17639,6 +17639,11 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
> int btf_fd;
> int err;
>
> + if (!env->bpf_capable) {
> + verbose(env, "BPF_PSEUDO_BTF_ID loads require CAP_BPF\n");
> + return -EACCES;
> + }
> +
Thank you for identifying this issue.
I think the correct way to fix it is to extend the `is_ptr && !allow_ptr_leaks`
logic in kernel/bpf/disasm.c:print_bpf_insn().
Note that it seems there are additional cases that are not covered,
something like below seem warranted:
bool is_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD ||
insn->src_reg == BPF_PSEUDO_MAP_VALUE ||
insn->src_reg == BPF_PSEUDO_MAP_IDX ||
insn->src_reg == BPF_PSEUDO_MAP_IDX_VALUE ||
insn->src_reg == BPF_PSEUDO_BTF_ID;
Could you please double check?
> btf_fd = insn[1].imm;
> if (btf_fd) {
> btf = btf_get_by_fd(btf_fd);
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Re: [PATCH bpf-next 1/2] bpf: Require CAP_BPF for pseudo-BTF ksym loads
2026-06-19 20:05 ` Eduard Zingerman
@ 2026-06-20 15:34 ` Nuoqi Gui
0 siblings, 0 replies; 5+ messages in thread
From: Nuoqi Gui @ 2026-06-20 15:34 UTC (permalink / raw)
To: Eduard Zingerman
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Hao Luo, John Fastabend, Martin KaFai Lau,
Shuah Khan, bpf, linux-kselftest, linux-kernel
> -----Original Messages-----
> From: "Eduard Zingerman" <eddyz87@gmail.com>
> Send time:Saturday, 20/06/2026 04:05:22
> To: "Nuoqi Gui" <gnq25@mails.tsinghua.edu.cn>, "Alexei Starovoitov" <ast@kernel.org>, "Daniel Borkmann" <daniel@iogearbox.net>, "Andrii Nakryiko" <andrii@kernel.org>, "Kumar Kartikeya Dwivedi" <memxor@gmail.com>, "Song Liu" <song@kernel.org>, "Yonghong Song" <yonghong.song@linux.dev>, "Jiri Olsa" <jolsa@kernel.org>, "Emil Tsalapatis" <emil@etsalapatis.com>, "Hao Luo" <haoluo@google.com>
> Cc: "John Fastabend" <john.fastabend@gmail.com>, "Martin KaFai Lau" <martin.lau@linux.dev>, "Shuah Khan" <shuah@kernel.org>, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
> Subject: Re: [PATCH bpf-next 1/2] bpf: Require CAP_BPF for pseudo-BTF ksym loads
>
> On Sat, 2026-06-20 at 00:04 +0800, Nuoqi Gui wrote:
> > BPF_PSEUDO_BTF_ID is resolved before the main verifier pass. The resolver
> > looks up the referenced kernel symbol through kallsyms and rewrites the
> > ldimm64 immediate to the concrete address that later becomes verifier
> > state.
> >
> > Require CAP_BPF before doing that materialization. This keeps typed ksym
> > address resolution on the privileged side and prevents loaders without
> > CAP_BPF from receiving a verifier log that contains the resolved address.
> >
> > Fixes: 4976b718c3551 ("bpf: Introduce pseudo_btf_id")
> > Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
> > ---
> > kernel/bpf/verifier.c | 5 +++++
> > 1 file changed, 5 insertions(+)
> >
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index ed7ba0e6a9ce..dbf5df995fc2 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -17639,6 +17639,11 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
> > int btf_fd;
> > int err;
> >
> > + if (!env->bpf_capable) {
> > + verbose(env, "BPF_PSEUDO_BTF_ID loads require CAP_BPF\n");
> > + return -EACCES;
> > + }
> > +
>
> Thank you for identifying this issue.
> I think the correct way to fix it is to extend the `is_ptr && !allow_ptr_leaks`
> logic in kernel/bpf/disasm.c:print_bpf_insn().
> Note that it seems there are additional cases that are not covered,
> something like below seem warranted:
>
>
> bool is_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD ||
> insn->src_reg == BPF_PSEUDO_MAP_VALUE ||
> insn->src_reg == BPF_PSEUDO_MAP_IDX ||
> insn->src_reg == BPF_PSEUDO_MAP_IDX_VALUE ||
> insn->src_reg == BPF_PSEUDO_BTF_ID;
>
> Could you please double check?
>
> > btf_fd = insn[1].imm;
> > if (btf_fd) {
> > btf = btf_get_by_fd(btf_fd);
Thanks for the guidance. I'll rework this to extend the pointer-like
ldimm64 sanitization in print_bpf_insn().
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-20 15:34 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-19 16:04 [PATCH bpf-next 0/2] bpf: Require CAP_BPF for pseudo-BTF ksym loads Nuoqi Gui
2026-06-19 16:04 ` [PATCH bpf-next 1/2] " Nuoqi Gui
2026-06-19 20:05 ` Eduard Zingerman
2026-06-20 15:34 ` Nuoqi Gui
2026-06-19 16:04 ` [PATCH bpf-next 2/2] selftests/bpf: Cover pseudo-BTF ksym load capability Nuoqi Gui
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®