Skip to content

Commit a748c69

Browse files
mfijalkoAlexei Starovoitov
authored and
Alexei Starovoitov
committed
bpf: propagate poke descriptors to subprograms
Previously, there was no need for poke descriptors being present in subprogram's bpf_prog_aux struct since tailcalls were simply not allowed in them. Each subprog is JITed independently so in order to enable JITing subprograms that use tailcalls, do the following: - in fixup_bpf_calls() store the index of tailcall insn onto the generated poke descriptor, - in case when insn patching occurs, adjust the tailcall insn idx from bpf_patch_insn_data, - then in jit_subprogs() check whether the given poke descriptor belongs to the current subprog by checking if that previously stored absolute index of tail call insn is in the scope of the insns of given subprog, - update the insn->imm with new poke descriptor slot so that while JITing the proper poke descriptor will be grabbed This way each of the main program's poke descriptors are distributed across the subprograms poke descriptor array, so main program's descriptors can be untracked out of the prog array map. Add also subprog's aux struct to the BPF map poke_progs list by calling on it map_poke_track(). In case of any error, call the map_poke_untrack() on subprog's aux structs that have already been registered to prog array map. Signed-off-by: Maciej Fijalkowski <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 0d4ddce commit a748c69

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,7 @@ struct bpf_jit_poke_descriptor {
707707
bool ip_stable;
708708
u8 adj_off;
709709
u16 reason;
710+
u32 insn_idx;
710711
};
711712

712713
/* reg_type info for ctx arguments */

kernel/bpf/verifier.c

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9623,6 +9623,18 @@ static void adjust_subprog_starts(struct bpf_verifier_env *env, u32 off, u32 len
96239623
}
96249624
}
96259625

9626+
static void adjust_poke_descs(struct bpf_prog *prog, u32 len)
9627+
{
9628+
struct bpf_jit_poke_descriptor *tab = prog->aux->poke_tab;
9629+
int i, sz = prog->aux->size_poke_tab;
9630+
struct bpf_jit_poke_descriptor *desc;
9631+
9632+
for (i = 0; i < sz; i++) {
9633+
desc = &tab[i];
9634+
desc->insn_idx += len - 1;
9635+
}
9636+
}
9637+
96269638
static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
96279639
const struct bpf_insn *patch, u32 len)
96289640
{
@@ -9639,6 +9651,7 @@ static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 of
96399651
if (adjust_insn_aux_data(env, new_prog, off, len))
96409652
return NULL;
96419653
adjust_subprog_starts(env, off, len);
9654+
adjust_poke_descs(new_prog, len);
96429655
return new_prog;
96439656
}
96449657

@@ -10169,6 +10182,7 @@ static int jit_subprogs(struct bpf_verifier_env *env)
1016910182
{
1017010183
struct bpf_prog *prog = env->prog, **func, *tmp;
1017110184
int i, j, subprog_start, subprog_end = 0, len, subprog;
10185+
struct bpf_map *map_ptr;
1017210186
struct bpf_insn *insn;
1017310187
void *old_bpf_func;
1017410188
int err, num_exentries;
@@ -10236,6 +10250,31 @@ static int jit_subprogs(struct bpf_verifier_env *env)
1023610250
func[i]->aux->btf = prog->aux->btf;
1023710251
func[i]->aux->func_info = prog->aux->func_info;
1023810252

10253+
for (j = 0; j < prog->aux->size_poke_tab; j++) {
10254+
u32 insn_idx = prog->aux->poke_tab[j].insn_idx;
10255+
int ret;
10256+
10257+
if (!(insn_idx >= subprog_start &&
10258+
insn_idx <= subprog_end))
10259+
continue;
10260+
10261+
ret = bpf_jit_add_poke_descriptor(func[i],
10262+
&prog->aux->poke_tab[j]);
10263+
if (ret < 0) {
10264+
verbose(env, "adding tail call poke descriptor failed\n");
10265+
goto out_free;
10266+
}
10267+
10268+
func[i]->insnsi[insn_idx - subprog_start].imm = ret + 1;
10269+
10270+
map_ptr = func[i]->aux->poke_tab[ret].tail_call.map;
10271+
ret = map_ptr->ops->map_poke_track(map_ptr, func[i]->aux);
10272+
if (ret < 0) {
10273+
verbose(env, "tracking tail call prog failed\n");
10274+
goto out_free;
10275+
}
10276+
}
10277+
1023910278
/* Use bpf_prog_F_tag to indicate functions in stack traces.
1024010279
* Long term would need debug info to populate names
1024110280
*/
@@ -10261,6 +10300,19 @@ static int jit_subprogs(struct bpf_verifier_env *env)
1026110300
}
1026210301
cond_resched();
1026310302
}
10303+
10304+
/* Untrack main program's aux structs so that during map_poke_run()
10305+
* we will not stumble upon the unfilled poke descriptors; each
10306+
* of the main program's poke descs got distributed across subprogs
10307+
* and got tracked onto map, so we are sure that none of them will
10308+
* be missed after the operation below
10309+
*/
10310+
for (i = 0; i < prog->aux->size_poke_tab; i++) {
10311+
map_ptr = prog->aux->poke_tab[i].tail_call.map;
10312+
10313+
map_ptr->ops->map_poke_untrack(map_ptr, prog->aux);
10314+
}
10315+
1026410316
/* at this point all bpf functions were successfully JITed
1026510317
* now populate all bpf_calls with correct addresses and
1026610318
* run last pass of JIT
@@ -10329,9 +10381,16 @@ static int jit_subprogs(struct bpf_verifier_env *env)
1032910381
bpf_prog_free_unused_jited_linfo(prog);
1033010382
return 0;
1033110383
out_free:
10332-
for (i = 0; i < env->subprog_cnt; i++)
10333-
if (func[i])
10334-
bpf_jit_free(func[i]);
10384+
for (i = 0; i < env->subprog_cnt; i++) {
10385+
if (!func[i])
10386+
continue;
10387+
10388+
for (j = 0; j < func[i]->aux->size_poke_tab; j++) {
10389+
map_ptr = func[i]->aux->poke_tab[j].tail_call.map;
10390+
map_ptr->ops->map_poke_untrack(map_ptr, func[i]->aux);
10391+
}
10392+
bpf_jit_free(func[i]);
10393+
}
1033510394
kfree(func);
1033610395
out_undo_insn:
1033710396
/* cleanup main prog to be interpreted */
@@ -10549,6 +10608,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
1054910608
.reason = BPF_POKE_REASON_TAIL_CALL,
1055010609
.tail_call.map = BPF_MAP_PTR(aux->map_ptr_state),
1055110610
.tail_call.key = bpf_map_key_immediate(aux),
10611+
.insn_idx = i + delta,
1055210612
};
1055310613

1055410614
ret = bpf_jit_add_poke_descriptor(prog, &desc);

0 commit comments

Comments
 (0)