Skip to content

Commit 264d5eb

Browse files
eddyz87Alexei Starovoitov
authored andcommitted
bpf: propagate read/precision marks over state graph backedges
Current loop_entry-based exact states comparison logic does not handle the following case: .-> A --. Assume the states are visited in the order A, B, C. | | | Assume that state B reaches a state equivalent to state A. | v v At this point, state C is not processed yet, so state A '-- B C has not received any read or precision marks from C. As a result, these marks won't be propagated to B. If B has incomplete marks, it is unsafe to use it in states_equal() checks. This commit replaces the existing logic with the following: - Strongly connected components (SCCs) are computed over the program's control flow graph (intraprocedurally). - When a verifier state enters an SCC, that state is recorded as the SCC entry point. - When a verifier state is found equivalent to another (e.g., B to A in the example), it is recorded as a states graph backedge. Backedges are accumulated per SCC. - When an SCC entry state reaches `branches == 0`, read and precision marks are propagated through the backedges (e.g., from A to B, from C to A, and then again from A to B). To support nested subprogram calls, the entry state and backedge list are associated not with the SCC itself but with an object called `bpf_scc_callchain`. A callchain is a tuple `(callsite*, scc_id)`, where `callsite` is the index of a call instruction for each frame except the last. See the comments added in `is_state_visited()` and `compute_scc_callchain()` for more details. Fixes: 2a09928 ("bpf: correct loop detection for iterators convergence") Signed-off-by: Eduard Zingerman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent d297ccb commit 264d5eb

File tree

2 files changed

+422
-68
lines changed

2 files changed

+422
-68
lines changed

include/linux/bpf_verifier.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,10 @@ struct bpf_verifier_state {
459459
* See get_loop_entry() for more information.
460460
*/
461461
struct bpf_verifier_state *loop_entry;
462+
/* if this state is a backedge state then equal_state
463+
* records cached state to which this state is equal.
464+
*/
465+
struct bpf_verifier_state *equal_state;
462466
/* jmp history recorded from first to last.
463467
* backtracking is using it to go from last to first.
464468
* For most states jmp_history_cnt is [0-3].
@@ -723,6 +727,37 @@ struct bpf_idset {
723727
u32 ids[BPF_ID_MAP_SIZE];
724728
};
725729

730+
/* see verifier.c:compute_scc_callchain() */
731+
struct bpf_scc_callchain {
732+
/* call sites from bpf_verifier_state->frame[*]->callsite leading to this SCC */
733+
u32 callsites[MAX_CALL_FRAMES - 1];
734+
/* last frame in a chain is identified by SCC id */
735+
u32 scc;
736+
};
737+
738+
/* verifier state waiting for propagate_backedges() */
739+
struct bpf_scc_backedge {
740+
struct bpf_scc_backedge *next;
741+
struct bpf_verifier_state state;
742+
};
743+
744+
struct bpf_scc_visit {
745+
struct bpf_scc_callchain callchain;
746+
/* first state in current verification path that entered SCC
747+
* identified by the callchain
748+
*/
749+
struct bpf_verifier_state *entry_state;
750+
struct bpf_scc_backedge *backedges; /* list of backedges */
751+
};
752+
753+
/* An array of bpf_scc_visit structs sharing tht same bpf_scc_callchain->scc
754+
* but having different bpf_scc_callchain->callsites.
755+
*/
756+
struct bpf_scc_info {
757+
u32 num_visits;
758+
struct bpf_scc_visit visits[];
759+
};
760+
726761
/* single container for all structs
727762
* one verifier_env per bpf_check() call
728763
*/
@@ -819,6 +854,9 @@ struct bpf_verifier_env {
819854
char tmp_str_buf[TMP_STR_BUF_LEN];
820855
struct bpf_insn insn_buf[INSN_BUF_SIZE];
821856
struct bpf_insn epilogue_buf[INSN_BUF_SIZE];
857+
/* array of pointers to bpf_scc_info indexed by SCC id */
858+
struct bpf_scc_info **scc_info;
859+
u32 scc_cnt;
822860
};
823861

824862
static inline struct bpf_func_info_aux *subprog_aux(struct bpf_verifier_env *env, int subprog)

0 commit comments

Comments
 (0)