Skip to content

Commit eea1c22

Browse files
Alexei Starovoitovborkmann
authored andcommitted
bpf: fix callees pruning callers
The commit 7640ead partially resolved the issue of callees incorrectly pruning the callers. With introduction of bounded loops and jmps_processed heuristic single verifier state may contain multiple branches and calls. It's possible that new verifier state (for future pruning) will be allocated inside callee. Then callee will exit (still within the same verifier state). It will go back to the caller and there R6-R9 registers will be read and will trigger mark_reg_read. But the reg->live for all frames but the top frame is not set to LIVE_NONE. Hence mark_reg_read will fail to propagate liveness into parent and future walking will incorrectly conclude that the states are equivalent because LIVE_READ is not set. In other words the rule for parent/live should be: whenever register parentage chain is set the reg->live should be set to LIVE_NONE. is_state_visited logic already follows this rule for spilled registers. Fixes: 7640ead ("bpf: verifier: make sure callees don't prune with caller differences") Fixes: f4d7e40 ("bpf: introduce function calls (verification)") Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 2589726 commit eea1c22

File tree

1 file changed

+6
-5
lines changed

1 file changed

+6
-5
lines changed

kernel/bpf/verifier.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6834,17 +6834,18 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
68346834
* the state of the call instruction (with WRITTEN set), and r0 comes
68356835
* from callee with its full parentage chain, anyway.
68366836
*/
6837-
for (j = 0; j <= cur->curframe; j++)
6838-
for (i = j < cur->curframe ? BPF_REG_6 : 0; i < BPF_REG_FP; i++)
6839-
cur->frame[j]->regs[i].parent = &new->frame[j]->regs[i];
68406837
/* clear write marks in current state: the writes we did are not writes
68416838
* our child did, so they don't screen off its reads from us.
68426839
* (There are no read marks in current state, because reads always mark
68436840
* their parent and current state never has children yet. Only
68446841
* explored_states can get read marks.)
68456842
*/
6846-
for (i = 0; i < BPF_REG_FP; i++)
6847-
cur->frame[cur->curframe]->regs[i].live = REG_LIVE_NONE;
6843+
for (j = 0; j <= cur->curframe; j++) {
6844+
for (i = j < cur->curframe ? BPF_REG_6 : 0; i < BPF_REG_FP; i++)
6845+
cur->frame[j]->regs[i].parent = &new->frame[j]->regs[i];
6846+
for (i = 0; i < BPF_REG_FP; i++)
6847+
cur->frame[j]->regs[i].live = REG_LIVE_NONE;
6848+
}
68486849

68496850
/* all stack frames are accessible from callee, clear them all */
68506851
for (j = 0; j <= cur->curframe; j++) {

0 commit comments

Comments
 (0)