]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Feb 2023 11:32:00 +0000 (12:32 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Feb 2023 11:32:00 +0000 (12:32 +0100)
added patches:
bpf-fix-incorrect-state-pruning-for-8b-spill-fill.patch

queue-5.10/bpf-fix-incorrect-state-pruning-for-8b-spill-fill.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/bpf-fix-incorrect-state-pruning-for-8b-spill-fill.patch b/queue-5.10/bpf-fix-incorrect-state-pruning-for-8b-spill-fill.patch
new file mode 100644 (file)
index 0000000..230e9b9
--- /dev/null
@@ -0,0 +1,88 @@
+From 345e004d023343d38088fdfea39688aa11e06ccf Mon Sep 17 00:00:00 2001
+From: Paul Chaignon <paul@isovalent.com>
+Date: Fri, 10 Dec 2021 00:46:31 +0100
+Subject: bpf: Fix incorrect state pruning for <8B spill/fill
+
+From: Paul Chaignon <paul@isovalent.com>
+
+commit 345e004d023343d38088fdfea39688aa11e06ccf upstream.
+
+Commit 354e8f1970f8 ("bpf: Support <8-byte scalar spill and refill")
+introduced support in the verifier to track <8B spill/fills of scalars.
+The backtracking logic for the precision bit was however skipping
+spill/fills of less than 8B. That could cause state pruning to consider
+two states equivalent when they shouldn't be.
+
+As an example, consider the following bytecode snippet:
+
+  0:  r7 = r1
+  1:  call bpf_get_prandom_u32
+  2:  r6 = 2
+  3:  if r0 == 0 goto pc+1
+  4:  r6 = 3
+  ...
+  8: [state pruning point]
+  ...
+  /* u32 spill/fill */
+  10: *(u32 *)(r10 - 8) = r6
+  11: r8 = *(u32 *)(r10 - 8)
+  12: r0 = 0
+  13: if r8 == 3 goto pc+1
+  14: r0 = 1
+  15: exit
+
+The verifier first walks the path with R6=3. Given the support for <8B
+spill/fills, at instruction 13, it knows the condition is true and skips
+instruction 14. At that point, the backtracking logic kicks in but stops
+at the fill instruction since it only propagates the precision bit for
+8B spill/fill. When the verifier then walks the path with R6=2, it will
+consider it safe at instruction 8 because R6 is not marked as needing
+precision. Instruction 14 is thus never walked and is then incorrectly
+removed as 'dead code'.
+
+It's also possible to lead the verifier to accept e.g. an out-of-bound
+memory access instead of causing an incorrect dead code elimination.
+
+This regression was found via Cilium's bpf-next CI where it was causing
+a conntrack map update to be silently skipped because the code had been
+removed by the verifier.
+
+This commit fixes it by enabling support for <8B spill/fills in the
+bactracking logic. In case of a <8B spill/fill, the full 8B stack slot
+will be marked as needing precision. Then, in __mark_chain_precision,
+any tracked register spilled in a marked slot will itself be marked as
+needing precision, regardless of the spill size. This logic makes two
+assumptions: (1) only 8B-aligned spill/fill are tracked and (2) spilled
+registers are only tracked if the spill and fill sizes are equal. Commit
+ef979017b837 ("bpf: selftest: Add verifier tests for <8-byte scalar
+spill and refill") covers the first assumption and the next commit in
+this patchset covers the second.
+
+Fixes: 354e8f1970f8 ("bpf: Support <8-byte scalar spill and refill")
+Signed-off-by: Paul Chaignon <paul@isovalent.com>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c |    4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -1876,8 +1876,6 @@ static int backtrack_insn(struct bpf_ver
+                */
+               if (insn->src_reg != BPF_REG_FP)
+                       return 0;
+-              if (BPF_SIZE(insn->code) != BPF_DW)
+-                      return 0;
+               /* dreg = *(u64 *)[fp - off] was a fill from the stack.
+                * that [fp - off] slot contains scalar that needs to be
+@@ -1900,8 +1898,6 @@ static int backtrack_insn(struct bpf_ver
+               /* scalars can only be spilled into stack */
+               if (insn->dst_reg != BPF_REG_FP)
+                       return 0;
+-              if (BPF_SIZE(insn->code) != BPF_DW)
+-                      return 0;
+               spi = (-insn->off - 1) / BPF_REG_SIZE;
+               if (spi >= 64) {
+                       verbose(env, "BUG spi %d\n", spi);
index 1e3a9a071c10d47ba60ab2e870241649db3eb75f..082c0cbb9a7741f4e748de3a6ad24098f7235aaa 100644 (file)
@@ -1,5 +1,6 @@
 firewire-fix-memory-leak-for-payload-of-request-subaction-to-iec-61883-1-fcp-region.patch
 bus-sunxi-rsb-fix-error-handling-in-sunxi_rsb_init.patch
+bpf-fix-incorrect-state-pruning-for-8b-spill-fill.patch
 bpf-fix-a-possible-task-gone-issue-with-bpf_send_sig.patch
 alsa-hda-via-avoid-potential-array-out-of-bound-in-a.patch
 powerpc-bpf-change-register-numbering-for-bpf_set-is.patch