Skip to content

Commit 1969db4

Browse files
4astdavem330
authored andcommitted
bpf: fix verifier memory leaks
fix verifier memory leaks Fixes: 638f5b9 ("bpf: reduce verifier memory consumption") Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4bfbe53 commit 1969db4

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

kernel/bpf/verifier.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -341,10 +341,12 @@ static int realloc_verifier_state(struct bpf_verifier_state *state, int size,
341341
return 0;
342342
}
343343

344-
static void free_verifier_state(struct bpf_verifier_state *state)
344+
static void free_verifier_state(struct bpf_verifier_state *state,
345+
bool free_self)
345346
{
346347
kfree(state->stack);
347-
kfree(state);
348+
if (free_self)
349+
kfree(state);
348350
}
349351

350352
/* copy verifier state from src to dst growing dst stack space
@@ -382,6 +384,7 @@ static int pop_stack(struct bpf_verifier_env *env, int *prev_insn_idx,
382384
if (prev_insn_idx)
383385
*prev_insn_idx = head->prev_insn_idx;
384386
elem = head->next;
387+
free_verifier_state(&head->st, false);
385388
kfree(head);
386389
env->head = elem;
387390
env->stack_size--;
@@ -399,14 +402,14 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
399402
if (!elem)
400403
goto err;
401404

402-
err = copy_verifier_state(&elem->st, cur);
403-
if (err)
404-
return NULL;
405405
elem->insn_idx = insn_idx;
406406
elem->prev_insn_idx = prev_insn_idx;
407407
elem->next = env->head;
408408
env->head = elem;
409409
env->stack_size++;
410+
err = copy_verifier_state(&elem->st, cur);
411+
if (err)
412+
goto err;
410413
if (env->stack_size > BPF_COMPLEXITY_LIMIT_STACK) {
411414
verbose(env, "BPF program is too complex\n");
412415
goto err;
@@ -3641,7 +3644,7 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
36413644
struct bpf_verifier_state_list *new_sl;
36423645
struct bpf_verifier_state_list *sl;
36433646
struct bpf_verifier_state *cur = env->cur_state;
3644-
int i;
3647+
int i, err;
36453648

36463649
sl = env->explored_states[insn_idx];
36473650
if (!sl)
@@ -3679,7 +3682,12 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
36793682
return -ENOMEM;
36803683

36813684
/* add new state to the head of linked list */
3682-
copy_verifier_state(&new_sl->state, cur);
3685+
err = copy_verifier_state(&new_sl->state, cur);
3686+
if (err) {
3687+
free_verifier_state(&new_sl->state, false);
3688+
kfree(new_sl);
3689+
return err;
3690+
}
36833691
new_sl->next = env->explored_states[insn_idx];
36843692
env->explored_states[insn_idx] = new_sl;
36853693
/* connect new state to parentage chain */
@@ -4424,6 +4432,7 @@ static void free_states(struct bpf_verifier_env *env)
44244432
if (sl)
44254433
while (sl != STATE_LIST_MARK) {
44264434
sln = sl->next;
4435+
free_verifier_state(&sl->state, false);
44274436
kfree(sl);
44284437
sl = sln;
44294438
}
@@ -4494,7 +4503,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
44944503
env->allow_ptr_leaks = capable(CAP_SYS_ADMIN);
44954504

44964505
ret = do_check(env);
4497-
free_verifier_state(env->cur_state);
4506+
free_verifier_state(env->cur_state, true);
44984507
env->cur_state = NULL;
44994508

45004509
skip_full_check:
@@ -4601,7 +4610,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
46014610
env->allow_ptr_leaks = capable(CAP_SYS_ADMIN);
46024611

46034612
ret = do_check(env);
4604-
free_verifier_state(env->cur_state);
4613+
free_verifier_state(env->cur_state, true);
46054614
env->cur_state = NULL;
46064615

46074616
skip_full_check:

0 commit comments

Comments
 (0)