]> git.ipfire.org Git - people/ms/linux.git/commitdiff
bpf: Fix the off-by-two error in range markings
authorMaxim Mikityanskiy <maximmi@nvidia.com>
Tue, 30 Nov 2021 18:16:07 +0000 (20:16 +0200)
committerDaniel Borkmann <daniel@iogearbox.net>
Fri, 3 Dec 2021 20:44:42 +0000 (21:44 +0100)
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
kernel/bpf/verifier.c
tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c

index 50efda51515b507b1b6e7949790e7ec78d70b93d..f3001937bbb931bba0990ad664847a07d25abc6b 100644 (file)
@@ -8422,7 +8422,7 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate,
 
        new_range = dst_reg->off;
        if (range_right_open)
-               new_range--;
+               new_range++;
 
        /* Examples for register markings:
         *
index bfb97383e6b5ae2c7e10c0e8294d4dd115b61954..de172a5b8754afcfc3d7c22e928efbea23604111 100644 (file)
        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(),
        },
        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(),
        },
        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(),
        },
        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(),
        },
                    offsetof(struct xdp_md, data_meta)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)),
        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(),
        },
                    offsetof(struct xdp_md, data_meta)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)),
        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(),
        },
                    offsetof(struct xdp_md, data_meta)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)),
        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(),
        },
                    offsetof(struct xdp_md, data_meta)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)),
        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(),
        },