bpf: Fix the off-by-two error in range markings
authorMaxim Mikityanskiy <maximmi@nvidia.com>
Tue, 6 Sep 2022 15:38:55 +0000 (18:38 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Sep 2022 10:23:49 +0000 (12:23 +0200)
commit 2fa7d94afc1afbb4d702760c058dc2d7ed30f226 upstream.

The first commit cited below attempts to fix the off-by-one error that
appeared in some comparisons with an open range. Due to this error,
arithmetically equivalent pieces of code could get different verdicts
from the verifier, for example (pseudocode):

  // 1. Passes the verifier:
  if (data + 8 > data_end)
      return early
  read *(u64 *)data, i.e. [data; data+7]

  // 2. Rejected by the verifier (should still pass):
  if (data + 7 >= data_end)
      return early
  read *(u64 *)data, i.e. [data; data+7]

The attempted fix, however, shifts the range by one in a wrong
direction, so the bug not only remains, but also such piece of code
starts failing in the verifier:

  // 3. Rejected by the verifier, but the check is stricter than in #1.
  if (data + 8 >= data_end)
      return early
  read *(u64 *)data, i.e. [data; data+7]

The change performed by that fix converted an off-by-one bug into
off-by-two. The second commit cited below added the BPF selftests
written to ensure than code chunks like #3 are rejected, however,
they should be accepted.

This commit fixes the off-by-two error by adjusting new_range in the
right direction and fixes the tests by changing the range into the
one that should actually fail.

Fixes: fb2a311a31d3 ("bpf: fix off by one for range markings with L{T, E} patterns")
Fixes: b37242c773b2 ("bpf: add test cases to bpf selftests to cover all access tests")
Signed-off-by: Maxim Mikityanskiy <maximmi@nvidia.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20211130181607.593149-1-maximmi@nvidia.com
[OP: only cherry-pick selftest changes applicable to 4.14]
Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
tools/testing/selftests/bpf/test_verifier.c

index 0846345fe1e5c03f2eafdc38501a89779dd9f517..f7757f7f6d2b94c66cff8be16d7da491cc42a05b 100644 (file)
@@ -7438,10 +7438,10 @@ static struct bpf_test tests[] = {
                        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
                                    offsetof(struct xdp_md, data_end)),
                        BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
-                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6),
                        BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1),
                        BPF_JMP_IMM(BPF_JA, 0, 0, 1),
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -7494,10 +7494,10 @@ static struct bpf_test tests[] = {
                        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
                                    offsetof(struct xdp_md, data_end)),
                        BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
-                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6),
                        BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1),
                        BPF_JMP_IMM(BPF_JA, 0, 0, 1),
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -7603,9 +7603,9 @@ static struct bpf_test tests[] = {
                        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
                                    offsetof(struct xdp_md, data_end)),
                        BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
-                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6),
                        BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1),
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -7770,9 +7770,9 @@ static struct bpf_test tests[] = {
                        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
                                    offsetof(struct xdp_md, data_end)),
                        BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
-                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6),
                        BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1),
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },