Skip to content

Commit f66b4aa

Browse files
luisgerhorstAlexei Starovoitov
authored andcommitted
bpf: Remove redundant free_verifier_state()/pop_stack()
This patch removes duplicated code. Eduard points out [1]: Same cleanup cycles are done in push_stack() and push_async_cb(), both functions are only reachable from do_check_common() via do_check() -> do_check_insn(). Hence, I think that cur state should not be freed in push_*() functions and pop_stack() loop there is not needed. This would also fix the 'symptom' for [2], but the issue also has a simpler fix which was sent separately. This fix also makes sure the push_*() callers always return an error for which error_recoverable_with_nospec(err) is false. This is required because otherwise we try to recover and access the stale `state`. Moving free_verifier_state() and pop_stack(..., pop_log=false) to happen after the bpf_vlog_reset() call in do_check_common() is fine because the pop_stack() call that is moved does not call bpf_vlog_reset() with the pop_log=false parameter. [1] https://lore.kernel.org/all/[email protected]/ [2] https://lore.kernel.org/all/[email protected]/ Reported-by: Eduard Zingerman <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Acked-by: Eduard Zingerman <[email protected]> Signed-off-by: Luis Gerhorst <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 4a4b84b commit f66b4aa

File tree

1 file changed

+10
-26
lines changed

1 file changed

+10
-26
lines changed

kernel/bpf/verifier.c

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,7 +2097,7 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
20972097

20982098
elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL_ACCOUNT);
20992099
if (!elem)
2100-
goto err;
2100+
return NULL;
21012101

21022102
elem->insn_idx = insn_idx;
21032103
elem->prev_insn_idx = prev_insn_idx;
@@ -2107,12 +2107,12 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
21072107
env->stack_size++;
21082108
err = copy_verifier_state(&elem->st, cur);
21092109
if (err)
2110-
goto err;
2110+
return NULL;
21112111
elem->st.speculative |= speculative;
21122112
if (env->stack_size > BPF_COMPLEXITY_LIMIT_JMP_SEQ) {
21132113
verbose(env, "The sequence of %d jumps is too complex.\n",
21142114
env->stack_size);
2115-
goto err;
2115+
return NULL;
21162116
}
21172117
if (elem->st.parent) {
21182118
++elem->st.parent->branches;
@@ -2127,12 +2127,6 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
21272127
*/
21282128
}
21292129
return &elem->st;
2130-
err:
2131-
free_verifier_state(env->cur_state, true);
2132-
env->cur_state = NULL;
2133-
/* pop all elements and return */
2134-
while (!pop_stack(env, NULL, NULL, false));
2135-
return NULL;
21362130
}
21372131

21382132
#define CALLER_SAVED_REGS 6
@@ -2864,7 +2858,7 @@ static struct bpf_verifier_state *push_async_cb(struct bpf_verifier_env *env,
28642858

28652859
elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL_ACCOUNT);
28662860
if (!elem)
2867-
goto err;
2861+
return NULL;
28682862

28692863
elem->insn_idx = insn_idx;
28702864
elem->prev_insn_idx = prev_insn_idx;
@@ -2876,7 +2870,7 @@ static struct bpf_verifier_state *push_async_cb(struct bpf_verifier_env *env,
28762870
verbose(env,
28772871
"The sequence of %d jumps is too complex for async cb.\n",
28782872
env->stack_size);
2879-
goto err;
2873+
return NULL;
28802874
}
28812875
/* Unlike push_stack() do not copy_verifier_state().
28822876
* The caller state doesn't matter.
@@ -2887,19 +2881,13 @@ static struct bpf_verifier_state *push_async_cb(struct bpf_verifier_env *env,
28872881
elem->st.in_sleepable = is_sleepable;
28882882
frame = kzalloc(sizeof(*frame), GFP_KERNEL_ACCOUNT);
28892883
if (!frame)
2890-
goto err;
2884+
return NULL;
28912885
init_func_state(env, frame,
28922886
BPF_MAIN_FUNC /* callsite */,
28932887
0 /* frameno within this callchain */,
28942888
subprog /* subprog number within this prog */);
28952889
elem->st.frame[0] = frame;
28962890
return &elem->st;
2897-
err:
2898-
free_verifier_state(env->cur_state, true);
2899-
env->cur_state = NULL;
2900-
/* pop all elements and return */
2901-
while (!pop_stack(env, NULL, NULL, false));
2902-
return NULL;
29032891
}
29042892

29052893

@@ -22935,6 +22923,10 @@ static void free_states(struct bpf_verifier_env *env)
2293522923
struct bpf_scc_info *info;
2293622924
int i, j;
2293722925

22926+
free_verifier_state(env->cur_state, true);
22927+
env->cur_state = NULL;
22928+
while (!pop_stack(env, NULL, NULL, false));
22929+
2293822930
list_for_each_safe(pos, tmp, &env->free_list) {
2293922931
sl = container_of(pos, struct bpf_verifier_state_list, node);
2294022932
free_verifier_state(&sl->state, false);
@@ -23086,14 +23078,6 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog)
2308623078

2308723079
ret = do_check(env);
2308823080
out:
23089-
/* check for NULL is necessary, since cur_state can be freed inside
23090-
* do_check() under memory pressure.
23091-
*/
23092-
if (env->cur_state) {
23093-
free_verifier_state(env->cur_state, true);
23094-
env->cur_state = NULL;
23095-
}
23096-
while (!pop_stack(env, NULL, NULL, false));
2309723081
if (!ret && pop_log)
2309823082
bpf_vlog_reset(&env->log, 0);
2309923083
free_states(env);

0 commit comments

Comments
 (0)