bpf: Add selftests to cover packet access corner cases
authorMaxim Mikityanskiy <maximmi@nvidia.com>
Tue, 7 Dec 2021 08:15:21 +0000 (10:15 +0200)
committerDaniel Borkmann <daniel@iogearbox.net>
Wed, 8 Dec 2021 14:42:26 +0000 (15:42 +0100)
This commit adds BPF verifier selftests that cover all corner cases by
packet boundary checks. Specifically, 8-byte packet reads are tested at
the beginning of data and at the beginning of data_meta, using all kinds
of boundary checks (all comparison operators: <, >, <=, >=; both
permutations of operands: data + length compared to end, end compared to
data + length). For each case there are three tests:

1. Length is just enough for an 8-byte read. Length is either 7 or 8,
   depending on the comparison.

2. Length is increased by 1 - should still pass the verifier. These
   cases are useful, because they failed before commit 2fa7d94afc1a
   ("bpf: Fix the off-by-two error in range markings").

3. Length is decreased by 1 - should be rejected by the verifier.

Some existing tests are just renamed to avoid duplication.

Signed-off-by: Maxim Mikityanskiy <maximmi@nvidia.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20211207081521.41923-1-maximmi@nvidia.com
tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c

index de172a5..b4ec228 100644 (file)
@@ -35,7 +35,7 @@
        .prog_type = BPF_PROG_TYPE_XDP,
 },
 {
-       "XDP pkt read, pkt_data' > pkt_end, good access",
+       "XDP pkt read, pkt_data' > pkt_end, corner case, good access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "XDP pkt read, pkt_data' > pkt_end, corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 9),
+       BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data' > pkt_end, corner case -1, bad access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 7),
+       BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "R1 offset is outside of the packet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
 {
        "XDP pkt read, pkt_end > pkt_data', good access",
        .insns = {
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_end > pkt_data', bad access 1",
+       "XDP pkt read, pkt_end > pkt_data', corner case -1, bad access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "XDP pkt read, pkt_end > pkt_data', corner case, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 7),
+       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, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_end > pkt_data', corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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_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_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
 {
        "XDP pkt read, pkt_data' < pkt_end, good access",
        .insns = {
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_data' < pkt_end, bad access 1",
+       "XDP pkt read, pkt_data' < pkt_end, corner case -1, bad access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_end < pkt_data', good access",
+       "XDP pkt read, pkt_data' < pkt_end, corner case, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 7),
+       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, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data' < pkt_end, corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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_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_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_end < pkt_data', corner case, good access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "XDP pkt read, pkt_end < pkt_data', corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 9),
+       BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_end < pkt_data', corner case -1, bad access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 7),
+       BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "R1 offset is outside of the packet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
 {
        "XDP pkt read, pkt_data' >= pkt_end, good access",
        .insns = {
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_data' >= pkt_end, bad access 1",
+       "XDP pkt read, pkt_data' >= pkt_end, corner case -1, bad access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_end >= pkt_data', good access",
+       "XDP pkt read, pkt_data' >= pkt_end, corner case, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 7),
+       BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data' >= pkt_end, corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_end >= pkt_data', corner case, good access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_data' <= pkt_end, good access",
+       "XDP pkt read, pkt_end >= pkt_data', corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 9),
+       BPF_JMP_REG(BPF_JGE, 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, -9),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_end >= pkt_data', corner case -1, bad access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 7),
+       BPF_JMP_REG(BPF_JGE, 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, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "R1 offset is outside of the packet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data' <= pkt_end, corner case, good access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "XDP pkt read, pkt_data' <= pkt_end, corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 9),
+       BPF_JMP_REG(BPF_JLE, 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, -9),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data' <= pkt_end, corner case -1, bad access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 7),
+       BPF_JMP_REG(BPF_JLE, 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, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "R1 offset is outside of the packet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
 {
        "XDP pkt read, pkt_end <= pkt_data', good access",
        .insns = {
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_end <= pkt_data', bad access 1",
+       "XDP pkt read, pkt_end <= pkt_data', corner case -1, bad access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
        BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_meta' > pkt_data, good access",
+       "XDP pkt read, pkt_end <= pkt_data', corner case, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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, 7),
+       BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_end <= pkt_data', corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)),
+       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_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_meta' > pkt_data, corner case, good access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                    offsetof(struct xdp_md, data_meta)),
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "XDP pkt read, pkt_meta' > pkt_data, corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 9),
+       BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_meta' > pkt_data, corner case -1, bad access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 7),
+       BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "R1 offset is outside of the packet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
 {
        "XDP pkt read, pkt_data > pkt_meta', good access",
        .insns = {
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_data > pkt_meta', bad access 1",
+       "XDP pkt read, pkt_data > pkt_meta', corner case -1, bad access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                    offsetof(struct xdp_md, data_meta)),
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "XDP pkt read, pkt_data > pkt_meta', corner case, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 7),
+       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, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data > pkt_meta', corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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_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_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
 {
        "XDP pkt read, pkt_meta' < pkt_data, good access",
        .insns = {
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_meta' < pkt_data, bad access 1",
+       "XDP pkt read, pkt_meta' < pkt_data, corner case -1, bad access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                    offsetof(struct xdp_md, data_meta)),
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_data < pkt_meta', good access",
+       "XDP pkt read, pkt_meta' < pkt_data, corner case, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 7),
+       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, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_meta' < pkt_data, corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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_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_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data < pkt_meta', corner case, good access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                    offsetof(struct xdp_md, data_meta)),
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "XDP pkt read, pkt_data < pkt_meta', corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 9),
+       BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data < pkt_meta', corner case -1, bad access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 7),
+       BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "R1 offset is outside of the packet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
 {
        "XDP pkt read, pkt_meta' >= pkt_data, good access",
        .insns = {
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_meta' >= pkt_data, bad access 1",
+       "XDP pkt read, pkt_meta' >= pkt_data, corner case -1, bad access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                    offsetof(struct xdp_md, data_meta)),
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_data >= pkt_meta', good access",
+       "XDP pkt read, pkt_meta' >= pkt_data, corner case, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 7),
+       BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_meta' >= pkt_data, corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data >= pkt_meta', corner case, good access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                    offsetof(struct xdp_md, data_meta)),
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_meta' <= pkt_data, good access",
+       "XDP pkt read, pkt_data >= pkt_meta', corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 9),
+       BPF_JMP_REG(BPF_JGE, 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, -9),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data >= pkt_meta', corner case -1, bad access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 7),
+       BPF_JMP_REG(BPF_JGE, 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, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "R1 offset is outside of the packet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_meta' <= pkt_data, corner case, good access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                    offsetof(struct xdp_md, data_meta)),
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "XDP pkt read, pkt_meta' <= pkt_data, corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 9),
+       BPF_JMP_REG(BPF_JLE, 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, -9),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_meta' <= pkt_data, corner case -1, bad access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 7),
+       BPF_JMP_REG(BPF_JLE, 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, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "R1 offset is outside of the packet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
 {
        "XDP pkt read, pkt_data <= pkt_meta', good access",
        .insns = {
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
 {
-       "XDP pkt read, pkt_data <= pkt_meta', bad access 1",
+       "XDP pkt read, pkt_data <= pkt_meta', corner case -1, bad access",
        .insns = {
        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                    offsetof(struct xdp_md, data_meta)),
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "XDP pkt read, pkt_data <= pkt_meta', corner case, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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, 7),
+       BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},
+{
+       "XDP pkt read, pkt_data <= pkt_meta', corner case +1, good access",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                   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_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+},