Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Paul Chaignon and committed by
Martin KaFai Lau
bc3eeb42 8d45d039

+58
+58
tools/testing/selftests/bpf/progs/verifier_direct_packet_access.c
··· 801 801 : __clobber_all); 802 802 } 803 803 804 + #define access_test_non_linear(name, type, desc, retval, linear_sz, off) \ 805 + SEC(type) \ 806 + __description("direct packet access: " #name " (non-linear, " type ", " desc ")") \ 807 + __success __retval(retval) \ 808 + __linear_size(linear_sz) \ 809 + __naked void access_non_linear_##name(void) \ 810 + { \ 811 + asm volatile (" \ 812 + r2 = *(u32*)(r1 + %[skb_data]); \ 813 + r3 = *(u32*)(r1 + %[skb_data_end]); \ 814 + r0 = r2; \ 815 + r0 += %[offset]; \ 816 + if r0 > r3 goto l0_%=; \ 817 + r0 = *(u8*)(r0 - 1); \ 818 + r0 = 0; \ 819 + exit; \ 820 + l0_%=: r0 = 1; \ 821 + exit; \ 822 + " : \ 823 + : __imm_const(skb_data, offsetof(struct __sk_buff, data)), \ 824 + __imm_const(skb_data_end, offsetof(struct __sk_buff, data_end)), \ 825 + __imm_const(offset, off) \ 826 + : __clobber_all); \ 827 + } 828 + 829 + access_test_non_linear(test31, "tc", "too short eth", 1, ETH_HLEN, 22); 830 + access_test_non_linear(test32, "tc", "too short 1", 1, 1, 22); 831 + access_test_non_linear(test33, "tc", "long enough", 0, 22, 22); 832 + access_test_non_linear(test34, "cgroup_skb/ingress", "too short eth", 1, ETH_HLEN, 8); 833 + access_test_non_linear(test35, "cgroup_skb/ingress", "too short 1", 1, 1, 8); 834 + access_test_non_linear(test36, "cgroup_skb/ingress", "long enough", 0, 22, 8); 835 + 836 + SEC("tc") 837 + __description("direct packet access: test37 (non-linear, linearized)") 838 + __success __retval(0) 839 + __linear_size(ETH_HLEN) 840 + __naked void access_non_linear_linearized(void) 841 + { 842 + asm volatile (" \ 843 + r6 = r1; \ 844 + r2 = 22; \ 845 + call %[bpf_skb_pull_data]; \ 846 + r2 = *(u32*)(r6 + %[skb_data]); \ 847 + r3 = *(u32*)(r6 + %[skb_data_end]); \ 848 + r0 = r2; \ 849 + r0 += 22; \ 850 + if r0 > r3 goto l0_%=; \ 851 + r0 = *(u8*)(r0 - 1); \ 852 + exit; \ 853 + l0_%=: r0 = 1; \ 854 + exit; \ 855 + " : 856 + : __imm(bpf_skb_pull_data), 857 + __imm_const(skb_data, offsetof(struct __sk_buff, data)), 858 + __imm_const(skb_data_end, offsetof(struct __sk_buff, data_end)) 859 + : __clobber_all); 860 + } 861 + 804 862 char _license[] SEC("license") = "GPL";