Re: [PATCH bpf-next v2 1/2] bpf: copy BPF token from main program to subprograms
Eduard Zingerman <[email protected]>
| Newsgroups | dev.linux.lists.sashiko,org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 2026-04-15 at 01:08 +0000, [email protected] wrote: > Sashiko AI review found 1 potential issue(s): > - [High] BPF token capability delegation is ignored for JIT blinding because blinding_requested is evaluated before the token is attached. > -- > > commit 6cda306e3c0e6ae78f183769fc6ebeb4369f35c3 > Author: Eduard Zingerman <[email protected]> > > bpf: copy BPF token from main program to subprograms > > This patch fixes an issue where bpf_jit_subprogs() omits copying the BPF > token to subprograms' aux data. By copying prog->aux->token, subprograms > inherit the same capability delegation as the main program, allowing > bpf_prog_kallsyms_add() to succeed for token-loaded subprograms. > > > diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c > > --- a/kernel/bpf/fixups.c > > +++ b/kernel/bpf/fixups.c > > @@ -1110,6 +1110,7 @@ int bpf_jit_subprogs(struct bpf_verifier_env *env) > > func[i]->aux->exception_cb = env->subprog_info[i].is_exception_cb; > > func[i]->aux->changes_pkt_data = env->subprog_info[i].changes_pkt_data; > > func[i]->aux->might_sleep = env->subprog_info[i].might_sleep; > > + func[i]->aux->token = prog->aux->token; > > While this ensures the token is propagated for bpf_prog_kallsyms_add(), does > the token delegation still fail for JIT blinding? > > Looking at bpf_prog_alloc(), it sets: > fp->blinding_requested = bpf_jit_blinding_enabled(fp); > > And bpf_jit_blinding_enabled() calls bpf_token_capable(prog->aux->token, > CAP_BPF) to bypass JIT hardening for privileged users. > > However, at the time of bpf_prog_alloc(), prog->aux->token is unconditionally > NULL, as it gets assigned later in bpf_prog_load(). As a result, > bpf_token_capable() falls back to checking the current process's global > capabilities. > > If an unprivileged user provides a valid BPF token granting CAP_BPF, the check > fails, and blinding_requested is set to true. This state is then copied to > all subprograms in bpf_jit_subprogs(): > func[i]->blinding_requested = prog->blinding_requested; > > Are token holders incorrectly forced into JIT hardening due to this sequence, > disabling direct tail-call optimizations? > > > if (!i) > > func[i]->aux->exception_boundary = env->seen_exception; I think this analysis is a dud. The token is correctly set for the main program and then is propagated to the subprograms.