Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: dont report verifier bug for missing bpf_scc_visit on speculative path

Syzbot generated a program that triggers a verifier_bug() call in
maybe_exit_scc(). maybe_exit_scc() assumes that, when called for a
state with insn_idx in some SCC, there should be an instance of struct
bpf_scc_visit allocated for that SCC. Turns out the assumption does
not hold for speculative execution paths. See example in the next
patch.

maybe_scc_exit() is called from update_branch_counts() for states that
reach branch count of zero, meaning that path exploration for a
particular path is finished. Path exploration can finish in one of
three ways:
a. Verification error is found. In this case, update_branch_counts()
is called only for non-speculative paths.
b. Top level BPF_EXIT is reached. Such instructions are never a part of
an SCC, so compute_scc_callchain() in maybe_scc_exit() will return
false, and maybe_scc_exit() will return early.
c. A checkpoint is reached and matched. Checkpoints are created by
is_state_visited(), which calls maybe_enter_scc(), which allocates
bpf_scc_visit instances for checkpoints within SCCs.

Hence, for non-speculative symbolic execution paths, the assumption
still holds: if maybe_scc_exit() is called for a state within an SCC,
bpf_scc_visit instance must exist.

This patch removes the verifier_bug() call for speculative paths.

Fixes: c9e31900b54c ("bpf: propagate read/precision marks over state graph backedges")
Reported-by: syzbot+3afc814e8df1af64b653@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/bpf/68c85acd.050a0220.2ff435.03a4.GAE@google.com/
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20250916212251.3490455-1-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
a3c73d62 180a46bc

+18 -3
+18 -3
kernel/bpf/verifier.c
··· 1950 1950 return 0; 1951 1951 visit = scc_visit_lookup(env, callchain); 1952 1952 if (!visit) { 1953 - verifier_bug(env, "scc exit: no visit info for call chain %s", 1954 - format_callchain(env, callchain)); 1955 - return -EFAULT; 1953 + /* 1954 + * If path traversal stops inside an SCC, corresponding bpf_scc_visit 1955 + * must exist for non-speculative paths. For non-speculative paths 1956 + * traversal stops when: 1957 + * a. Verification error is found, maybe_exit_scc() is not called. 1958 + * b. Top level BPF_EXIT is reached. Top level BPF_EXIT is not a member 1959 + * of any SCC. 1960 + * c. A checkpoint is reached and matched. Checkpoints are created by 1961 + * is_state_visited(), which calls maybe_enter_scc(), which allocates 1962 + * bpf_scc_visit instances for checkpoints within SCCs. 1963 + * (c) is the only case that can reach this point. 1964 + */ 1965 + if (!st->speculative) { 1966 + verifier_bug(env, "scc exit: no visit info for call chain %s", 1967 + format_callchain(env, callchain)); 1968 + return -EFAULT; 1969 + } 1970 + return 0; 1956 1971 } 1957 1972 if (visit->entry_state != st) 1958 1973 return 0;