Message ID | 162388400488.151936.1658153981415911010.stgit@john-XPS-13-9370 |
---|---|
Headers | show |
Series | BPF fixes mixed tail and bpf2bpf calls | expand |
On Wed, Jun 16, 2021 at 7:34 PM John Fastabend <john.fastabend@gmail.com> wrote: > > We recently tried to use mixed programs that have both tail calls and > subprograms, but it needs the attached fixes. > > Also added a new test case tailcall_bpf2bpf_5 that simply runs the > previous test case tailcall_bpf2bpf_4 and adds some "noise". The > noise here is just a bunch of map calls to get the verifier to insert > instructions and cause code movement plus it forces used_maps logic > to be used. Originally, I just extended bpf2bpf_4 directly, but if I > got the feedback correct it seems the preference is to have another > test case for this specifically. > > With attached patches our programs are happily running with mixed > subprograms and tailcalls. > > Thanks, > John > > --- Would be nice to include bpf@vger.kernel.org as well. I bet not everyone interested in BPF follows netdev@vger closely. > > John Fastabend (4): > bpf: Fix null ptr deref with mixed tail calls and subprogs > bpf: map_poke_descriptor is being called with an unstable poke_tab[] > bpf: track subprog poke correctly > bpf: selftest to verify mixing bpf2bpf calls and tailcalls with insn patch > > > include/linux/bpf.h | 1 + > kernel/bpf/core.c | 6 ++-- > kernel/bpf/verifier.c | 36 ++++++++++++++----- > .../selftests/bpf/prog_tests/tailcalls.c | 36 +++++++++++++------ > .../selftests/bpf/progs/tailcall_bpf2bpf4.c | 20 ++++++++++- > 5 files changed, 77 insertions(+), 22 deletions(-) > > -- >
On Wed, Jun 16, 2021 at 03:55:39PM -0700, John Fastabend wrote: > > -static void bpf_free_used_maps(struct bpf_prog_aux *aux) > +void bpf_free_used_maps(struct bpf_prog_aux *aux) > { > __bpf_free_used_maps(aux, aux->used_maps, aux->used_map_cnt); > kfree(aux->used_maps); > @@ -2211,8 +2211,10 @@ static void bpf_prog_free_deferred(struct work_struct *work) > #endif > if (aux->dst_trampoline) > bpf_trampoline_put(aux->dst_trampoline); > - for (i = 0; i < aux->func_cnt; i++) > + for (i = 0; i < aux->func_cnt; i++) { > + bpf_free_used_maps(aux->func[i]->aux); > bpf_jit_free(aux->func[i]); > + } The sub-progs don't have all the properties of the main prog. Only main prog suppose to keep maps incremented. After this patch the prog with 100 subprogs will artificially bump maps refcnt 100 times as a workaround for poke_tab access. May be we can use single poke_tab in the main prog instead. Looks like jit_subprogs is splitting the poke_tab into individual arrays for each subprog, but maps are tracked by the main prog only. That's the root cause of the issue, right? I think that split of poke_tab isn't necessary. bpf_int_jit_compile() can look into main prog poke_tab instead. Then the loop: for (j = 0; j < prog->aux->size_poke_tab) bpf_jit_add_poke_descriptor(func[i], &prog->aux->poke_tab[j]); can be removed (It will address the concern in patch 2 as well, right?) And hopefully will fix UAF too?
Alexei Starovoitov wrote: > On Wed, Jun 16, 2021 at 03:55:39PM -0700, John Fastabend wrote: > > > > -static void bpf_free_used_maps(struct bpf_prog_aux *aux) > > +void bpf_free_used_maps(struct bpf_prog_aux *aux) > > { > > __bpf_free_used_maps(aux, aux->used_maps, aux->used_map_cnt); > > kfree(aux->used_maps); > > @@ -2211,8 +2211,10 @@ static void bpf_prog_free_deferred(struct work_struct *work) > > #endif > > if (aux->dst_trampoline) > > bpf_trampoline_put(aux->dst_trampoline); > > - for (i = 0; i < aux->func_cnt; i++) > > + for (i = 0; i < aux->func_cnt; i++) { > > + bpf_free_used_maps(aux->func[i]->aux); > > bpf_jit_free(aux->func[i]); > > + } > > The sub-progs don't have all the properties of the main prog. > Only main prog suppose to keep maps incremented. > After this patch the prog with 100 subprogs will artificially bump maps > refcnt 100 times as a workaround for poke_tab access. Yep. > May be we can use single poke_tab in the main prog instead. > Looks like jit_subprogs is splitting the poke_tab into individual arrays > for each subprog, but maps are tracked by the main prog only. > That's the root cause of the issue, right? Correct. > I think that split of poke_tab isn't necessary. > bpf_int_jit_compile() can look into main prog poke_tab instead. > Then the loop: > for (j = 0; j < prog->aux->size_poke_tab) > bpf_jit_add_poke_descriptor(func[i], &prog->aux->poke_tab[j]); > can be removed (It will address the concern in patch 2 as well, right?) > And hopefully will fix UAF too? Looks like it to me as well. A few details to work out around imm value and emit hooks on the jit side, but looks doable to me. I'll give it a try tomorrow or tonight. Thanks, John
On Tue, Jun 22, 2021 at 4:02 PM John Fastabend <john.fastabend@gmail.com> wrote: > > Alexei Starovoitov wrote: > > On Wed, Jun 16, 2021 at 03:55:39PM -0700, John Fastabend wrote: > > > > > > -static void bpf_free_used_maps(struct bpf_prog_aux *aux) > > > +void bpf_free_used_maps(struct bpf_prog_aux *aux) > > > { > > > __bpf_free_used_maps(aux, aux->used_maps, aux->used_map_cnt); > > > kfree(aux->used_maps); > > > @@ -2211,8 +2211,10 @@ static void bpf_prog_free_deferred(struct work_struct *work) > > > #endif > > > if (aux->dst_trampoline) > > > bpf_trampoline_put(aux->dst_trampoline); > > > - for (i = 0; i < aux->func_cnt; i++) > > > + for (i = 0; i < aux->func_cnt; i++) { > > > + bpf_free_used_maps(aux->func[i]->aux); > > > bpf_jit_free(aux->func[i]); > > > + } > > > > The sub-progs don't have all the properties of the main prog. > > Only main prog suppose to keep maps incremented. > > After this patch the prog with 100 subprogs will artificially bump maps > > refcnt 100 times as a workaround for poke_tab access. > > Yep. > > > May be we can use single poke_tab in the main prog instead. > > Looks like jit_subprogs is splitting the poke_tab into individual arrays > > for each subprog, but maps are tracked by the main prog only. > > That's the root cause of the issue, right? > > Correct. > > > I think that split of poke_tab isn't necessary. > > bpf_int_jit_compile() can look into main prog poke_tab instead. > > Then the loop: > > for (j = 0; j < prog->aux->size_poke_tab) > > bpf_jit_add_poke_descriptor(func[i], &prog->aux->poke_tab[j]); > > can be removed (It will address the concern in patch 2 as well, right?) > > And hopefully will fix UAF too? > > Looks like it to me as well. A few details to work out around > imm value and emit hooks on the jit side, but looks doable to me. > I'll give it a try tomorrow or tonight. Perfect. Thank you John.