From: Greg Kroah-Hartman Date: Tue, 24 Jun 2025 10:36:08 +0000 (+0100) Subject: 5.10-stable patches X-Git-Tag: v5.4.295~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4643c95205fee2a4cec0076747f454547f39a7bd;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: bpf-fix-precision-backtracking-instruction-iteration.patch --- diff --git a/queue-5.10/bpf-fix-precision-backtracking-instruction-iteration.patch b/queue-5.10/bpf-fix-precision-backtracking-instruction-iteration.patch new file mode 100644 index 0000000000..2dd96fd019 --- /dev/null +++ b/queue-5.10/bpf-fix-precision-backtracking-instruction-iteration.patch @@ -0,0 +1,87 @@ +From 4bb7ea946a370707315ab774432963ce47291946 Mon Sep 17 00:00:00 2001 +From: Andrii Nakryiko +Date: Thu, 9 Nov 2023 16:26:37 -0800 +Subject: bpf: fix precision backtracking instruction iteration + +From: Andrii Nakryiko + +commit 4bb7ea946a370707315ab774432963ce47291946 upstream. + +Fix an edge case in __mark_chain_precision() which prematurely stops +backtracking instructions in a state if it happens that state's first +and last instruction indexes are the same. This situations doesn't +necessarily mean that there were no instructions simulated in a state, +but rather that we starting from the instruction, jumped around a bit, +and then ended up at the same instruction before checkpointing or +marking precision. + +To distinguish between these two possible situations, we need to consult +jump history. If it's empty or contain a single record "bridging" parent +state and first instruction of processed state, then we indeed +backtracked all instructions in this state. But if history is not empty, +we are definitely not done yet. + +Move this logic inside get_prev_insn_idx() to contain it more nicely. +Use -ENOENT return code to denote "we are out of instructions" +situation. + +This bug was exposed by verifier_loop1.c's bounded_recursion subtest, once +the next fix in this patch set is applied. + +Acked-by: Eduard Zingerman +Fixes: b5dc0163d8fd ("bpf: precise scalar_value tracking") +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/r/20231110002638.4168352-3-andrii@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Aaron Lu +Reported-by: Wei Wei +Closes: https://lore.kernel.org/all/20250605070921.GA3795@bytedance/ +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1796,12 +1796,29 @@ static int push_jmp_history(struct bpf_v + + /* Backtrack one insn at a time. If idx is not at the top of recorded + * history then previous instruction came from straight line execution. ++ * Return -ENOENT if we exhausted all instructions within given state. ++ * ++ * It's legal to have a bit of a looping with the same starting and ending ++ * insn index within the same state, e.g.: 3->4->5->3, so just because current ++ * instruction index is the same as state's first_idx doesn't mean we are ++ * done. If there is still some jump history left, we should keep going. We ++ * need to take into account that we might have a jump history between given ++ * state's parent and itself, due to checkpointing. In this case, we'll have ++ * history entry recording a jump from last instruction of parent state and ++ * first instruction of given state. + */ + static int get_prev_insn_idx(struct bpf_verifier_state *st, int i, + u32 *history) + { + u32 cnt = *history; + ++ if (i == st->first_insn_idx) { ++ if (cnt == 0) ++ return -ENOENT; ++ if (cnt == 1 && st->jmp_history[0].idx == i) ++ return -ENOENT; ++ } ++ + if (cnt && st->jmp_history[cnt - 1].idx == i) { + i = st->jmp_history[cnt - 1].prev_idx; + (*history)--; +@@ -2269,9 +2286,9 @@ static int __mark_chain_precision(struct + * Nothing to be tracked further in the parent state. + */ + return 0; +- if (i == first_idx) +- break; + i = get_prev_insn_idx(st, i, &history); ++ if (i == -ENOENT) ++ break; + if (i >= env->prog->len) { + /* This can happen if backtracking reached insn 0 + * and there are still reg_mask or stack_mask