selftests/bpf: Test direct packet access on non-linear skbs

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
This commit is contained in:
Paul Chaignon 2025-10-09 22:12:18 +02:00 committed by Martin KaFai Lau
parent 8d45d0398d
commit bc3eeb4259

View 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";