]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/bpf: Test direct packet access on non-linear skbs
authorPaul Chaignon <paul.chaignon@gmail.com>
Thu, 9 Oct 2025 20:12:18 +0000 (22:12 +0200)
committerMartin KaFai Lau <martin.lau@kernel.org>
Fri, 10 Oct 2025 17:43:04 +0000 (10:43 -0700)
This patch adds new selftests in the direct packet access suite, to
cover the non-linear case. The first six tests cover the behavior of
the bounds check with a non-linear skb. The last test adds a call to
bpf_skb_pull_data() to be able to access the packet.

Note that the size of the linear area includes the L2 header, but for
some program types like cgroup_skb, ctx->data points to the L3 header.
Therefore, a linear area of 22 bytes will have only 8 bytes accessible
to the BPF program (22 - ETH_HLEN). For that reason, the cgroup_skb test
cases access the packet at an offset of 8 bytes.

Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://patch.msgid.link/ceedbfd719e58f0d49dcceb8592f5e6bd38ce5fe.1760037899.git.paul.chaignon@gmail.com
tools/testing/selftests/bpf/progs/verifier_direct_packet_access.c

index a61897e01a50de96c75ab65eee00cd3c13a4dc0b..911caa8fd1b759994177353afd6c79ad7eb6eba4 100644 (file)
@@ -801,4 +801,62 @@ l0_%=:     /* exit(0) */                                   \
        : __clobber_all);
 }
 
+#define access_test_non_linear(name, type, desc, retval, linear_sz, off)                       \
+       SEC(type)                                                                               \
+       __description("direct packet access: " #name " (non-linear, " type ", " desc ")")       \
+       __success __retval(retval)                                                              \
+       __linear_size(linear_sz)                                                                \
+       __naked void access_non_linear_##name(void)                                             \
+       {                                                                                       \
+               asm volatile ("                                                                 \
+               r2 = *(u32*)(r1 + %[skb_data]);                                                 \
+               r3 = *(u32*)(r1 + %[skb_data_end]);                                             \
+               r0 = r2;                                                                        \
+               r0 += %[offset];                                                                \
+               if r0 > r3 goto l0_%=;                                                          \
+               r0 = *(u8*)(r0 - 1);                                                            \
+               r0 = 0;                                                                         \
+               exit;                                                                           \
+       l0_%=:  r0 = 1;                                                                         \
+               exit;                                                                           \
+       "       :                                                                               \
+               : __imm_const(skb_data, offsetof(struct __sk_buff, data)),                      \
+                 __imm_const(skb_data_end, offsetof(struct __sk_buff, data_end)),              \
+                 __imm_const(offset, off)                                                      \
+               : __clobber_all);                                                               \
+       }
+
+access_test_non_linear(test31, "tc", "too short eth", 1, ETH_HLEN, 22);
+access_test_non_linear(test32, "tc", "too short 1", 1, 1, 22);
+access_test_non_linear(test33, "tc", "long enough", 0, 22, 22);
+access_test_non_linear(test34, "cgroup_skb/ingress", "too short eth", 1, ETH_HLEN, 8);
+access_test_non_linear(test35, "cgroup_skb/ingress", "too short 1", 1, 1, 8);
+access_test_non_linear(test36, "cgroup_skb/ingress", "long enough", 0, 22, 8);
+
+SEC("tc")
+__description("direct packet access: test37 (non-linear, linearized)")
+__success __retval(0)
+__linear_size(ETH_HLEN)
+__naked void access_non_linear_linearized(void)
+{
+       asm volatile ("                         \
+       r6 = r1;                                \
+       r2 = 22;                                \
+       call %[bpf_skb_pull_data];              \
+       r2 = *(u32*)(r6 + %[skb_data]);         \
+       r3 = *(u32*)(r6 + %[skb_data_end]);     \
+       r0 = r2;                                \
+       r0 += 22;                               \
+       if r0 > r3 goto l0_%=;                  \
+       r0 = *(u8*)(r0 - 1);                    \
+       exit;                                   \
+l0_%=: r0 = 1;                                 \
+       exit;                                   \
+"      :
+       : __imm(bpf_skb_pull_data),
+         __imm_const(skb_data, offsetof(struct __sk_buff, data)),
+         __imm_const(skb_data_end, offsetof(struct __sk_buff, data_end))
+       : __clobber_all);
+}
+
 char _license[] SEC("license") = "GPL";