Revert "bpf: Track subprog poke descriptors correctly and fix use-after-free"
This reverts commit a9f36bf361
which is
commit f263a81451c12da5a342d90572e317e611846f2c upstream.
It breaks the Android KABI and is not needed for Android devices at this
point in time.
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Id5d1b6407f9bd5228630b9a813e9799dbc448b96
This commit is contained in:
@@ -564,9 +564,6 @@ static void bpf_tail_call_direct_fixup(struct bpf_prog *prog)
|
|||||||
|
|
||||||
for (i = 0; i < prog->aux->size_poke_tab; i++) {
|
for (i = 0; i < prog->aux->size_poke_tab; i++) {
|
||||||
poke = &prog->aux->poke_tab[i];
|
poke = &prog->aux->poke_tab[i];
|
||||||
if (poke->aux && poke->aux != prog->aux)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
WARN_ON_ONCE(READ_ONCE(poke->tailcall_target_stable));
|
WARN_ON_ONCE(READ_ONCE(poke->tailcall_target_stable));
|
||||||
|
|
||||||
if (poke->reason != BPF_POKE_REASON_TAIL_CALL)
|
if (poke->reason != BPF_POKE_REASON_TAIL_CALL)
|
||||||
|
@@ -760,7 +760,6 @@ struct bpf_jit_poke_descriptor {
|
|||||||
void *tailcall_target;
|
void *tailcall_target;
|
||||||
void *tailcall_bypass;
|
void *tailcall_bypass;
|
||||||
void *bypass_addr;
|
void *bypass_addr;
|
||||||
void *aux;
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
struct bpf_map *map;
|
struct bpf_map *map;
|
||||||
|
@@ -2171,14 +2171,8 @@ static void bpf_prog_free_deferred(struct work_struct *work)
|
|||||||
#endif
|
#endif
|
||||||
if (aux->dst_trampoline)
|
if (aux->dst_trampoline)
|
||||||
bpf_trampoline_put(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++)
|
||||||
/* We can just unlink the subprog poke descriptor table as
|
|
||||||
* it was originally linked to the main program and is also
|
|
||||||
* released along with it.
|
|
||||||
*/
|
|
||||||
aux->func[i]->aux->poke_tab = NULL;
|
|
||||||
bpf_jit_free(aux->func[i]);
|
bpf_jit_free(aux->func[i]);
|
||||||
}
|
|
||||||
if (aux->func_cnt) {
|
if (aux->func_cnt) {
|
||||||
kfree(aux->func);
|
kfree(aux->func);
|
||||||
bpf_prog_unlock_free(aux->prog);
|
bpf_prog_unlock_free(aux->prog);
|
||||||
|
@@ -11157,19 +11157,33 @@ static int jit_subprogs(struct bpf_verifier_env *env)
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
func[i]->is_func = 1;
|
func[i]->is_func = 1;
|
||||||
func[i]->aux->func_idx = i;
|
func[i]->aux->func_idx = i;
|
||||||
/* Below members will be freed only at prog->aux */
|
/* the btf and func_info will be freed only at prog->aux */
|
||||||
func[i]->aux->btf = prog->aux->btf;
|
func[i]->aux->btf = prog->aux->btf;
|
||||||
func[i]->aux->func_info = prog->aux->func_info;
|
func[i]->aux->func_info = prog->aux->func_info;
|
||||||
func[i]->aux->poke_tab = prog->aux->poke_tab;
|
|
||||||
func[i]->aux->size_poke_tab = prog->aux->size_poke_tab;
|
|
||||||
|
|
||||||
for (j = 0; j < prog->aux->size_poke_tab; j++) {
|
for (j = 0; j < prog->aux->size_poke_tab; j++) {
|
||||||
struct bpf_jit_poke_descriptor *poke;
|
u32 insn_idx = prog->aux->poke_tab[j].insn_idx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
poke = &prog->aux->poke_tab[j];
|
if (!(insn_idx >= subprog_start &&
|
||||||
if (poke->insn_idx < subprog_end &&
|
insn_idx <= subprog_end))
|
||||||
poke->insn_idx >= subprog_start)
|
continue;
|
||||||
poke->aux = func[i]->aux;
|
|
||||||
|
ret = bpf_jit_add_poke_descriptor(func[i],
|
||||||
|
&prog->aux->poke_tab[j]);
|
||||||
|
if (ret < 0) {
|
||||||
|
verbose(env, "adding tail call poke descriptor failed\n");
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
func[i]->insnsi[insn_idx - subprog_start].imm = ret + 1;
|
||||||
|
|
||||||
|
map_ptr = func[i]->aux->poke_tab[ret].tail_call.map;
|
||||||
|
ret = map_ptr->ops->map_poke_track(map_ptr, func[i]->aux);
|
||||||
|
if (ret < 0) {
|
||||||
|
verbose(env, "tracking tail call prog failed\n");
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use bpf_prog_F_tag to indicate functions in stack traces.
|
/* Use bpf_prog_F_tag to indicate functions in stack traces.
|
||||||
@@ -11199,6 +11213,18 @@ static int jit_subprogs(struct bpf_verifier_env *env)
|
|||||||
cond_resched();
|
cond_resched();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Untrack main program's aux structs so that during map_poke_run()
|
||||||
|
* we will not stumble upon the unfilled poke descriptors; each
|
||||||
|
* of the main program's poke descs got distributed across subprogs
|
||||||
|
* and got tracked onto map, so we are sure that none of them will
|
||||||
|
* be missed after the operation below
|
||||||
|
*/
|
||||||
|
for (i = 0; i < prog->aux->size_poke_tab; i++) {
|
||||||
|
map_ptr = prog->aux->poke_tab[i].tail_call.map;
|
||||||
|
|
||||||
|
map_ptr->ops->map_poke_untrack(map_ptr, prog->aux);
|
||||||
|
}
|
||||||
|
|
||||||
/* at this point all bpf functions were successfully JITed
|
/* at this point all bpf functions were successfully JITed
|
||||||
* now populate all bpf_calls with correct addresses and
|
* now populate all bpf_calls with correct addresses and
|
||||||
* run last pass of JIT
|
* run last pass of JIT
|
||||||
@@ -11267,22 +11293,14 @@ static int jit_subprogs(struct bpf_verifier_env *env)
|
|||||||
bpf_prog_free_unused_jited_linfo(prog);
|
bpf_prog_free_unused_jited_linfo(prog);
|
||||||
return 0;
|
return 0;
|
||||||
out_free:
|
out_free:
|
||||||
/* We failed JIT'ing, so at this point we need to unregister poke
|
|
||||||
* descriptors from subprogs, so that kernel is not attempting to
|
|
||||||
* patch it anymore as we're freeing the subprog JIT memory.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < prog->aux->size_poke_tab; i++) {
|
|
||||||
map_ptr = prog->aux->poke_tab[i].tail_call.map;
|
|
||||||
map_ptr->ops->map_poke_untrack(map_ptr, prog->aux);
|
|
||||||
}
|
|
||||||
/* At this point we're guaranteed that poke descriptors are not
|
|
||||||
* live anymore. We can just unlink its descriptor table as it's
|
|
||||||
* released with the main prog.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < env->subprog_cnt; i++) {
|
for (i = 0; i < env->subprog_cnt; i++) {
|
||||||
if (!func[i])
|
if (!func[i])
|
||||||
continue;
|
continue;
|
||||||
func[i]->aux->poke_tab = NULL;
|
|
||||||
|
for (j = 0; j < func[i]->aux->size_poke_tab; j++) {
|
||||||
|
map_ptr = func[i]->aux->poke_tab[j].tail_call.map;
|
||||||
|
map_ptr->ops->map_poke_untrack(map_ptr, func[i]->aux);
|
||||||
|
}
|
||||||
bpf_jit_free(func[i]);
|
bpf_jit_free(func[i]);
|
||||||
}
|
}
|
||||||
kfree(func);
|
kfree(func);
|
||||||
|
Reference in New Issue
Block a user