selftests/bpf: Add test for stale pkt range after scalar arithmetic

Extend the verifier_direct_packet_access BPF selftests to exercise the
verifier code paths which ensure that the pkt range is cleared after
add/sub alu with a known scalar. The tests reject the invalid access.

  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_direct
  [...]
  #592/35  verifier_direct_packet_access/direct packet access: pkt_range cleared after sub with known scalar:OK
  #592/36  verifier_direct_packet_access/direct packet access: pkt_range cleared after add with known scalar:OK
  #592/37  verifier_direct_packet_access/direct packet access: test3:OK
  #592/38  verifier_direct_packet_access/direct packet access: test3 @unpriv:OK
  #592/39  verifier_direct_packet_access/direct packet access: test34 (non-linear, cgroup_skb/ingress, too short eth):OK
  #592/40  verifier_direct_packet_access/direct packet access: test35 (non-linear, cgroup_skb/ingress, too short 1):OK
  #592/41  verifier_direct_packet_access/direct packet access: test36 (non-linear, cgroup_skb/ingress, long enough):OK
  #592     verifier_direct_packet_access:OK
  [...]
  Summary: 2/47 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20260409155016.536608-2-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Daniel Borkmann 2026-04-09 17:50:16 +02:00 committed by Alexei Starovoitov
parent 9f118095dd
commit 8697bdd67b

View File

@ -859,4 +859,65 @@ l0_%=: r0 = 1; \
: __clobber_all);
}
SEC("tc")
__description("direct packet access: pkt_range cleared after sub with known scalar")
__failure __msg("invalid access to packet")
__naked void pkt_range_clear_after_sub(void)
{
asm volatile (" \
r9 = *(u32*)(r1 + %[__sk_buff_data]); \
r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \
r9 += 256; \
if r9 >= r8 goto l0_%=; \
r0 = 0; \
exit; \
l0_%=: /* r9 has AT_PKT_END (pkt + 256 >= pkt_end) */ \
r9 -= 256; \
/* \
* AT_PKT_END must not survive the arithmetic. \
* is_pkt_ptr_branch_taken must validate both \
* branches when visiting the next condition. \
*/ \
if r9 < r8 goto l1_%=; \
r0 = 0; \
exit; \
l1_%=: r0 = *(u8*)(r9 + 0); \
r0 = 0; \
exit; \
" :
: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
__imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
: __clobber_all);
}
SEC("tc")
__description("direct packet access: pkt_range cleared after add with known scalar")
__failure __msg("invalid access to packet")
__naked void pkt_range_clear_after_add(void)
{
asm volatile (" \
r9 = *(u32*)(r1 + %[__sk_buff_data]); \
r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \
r9 += 256; \
if r9 >= r8 goto l0_%=; \
r0 = 0; \
exit; \
l0_%=: /* r9 has AT_PKT_END (pkt + 256 >= pkt_end) */ \
r9 += -256; \
/* \
* Same as sub, but goes through BPF_ADD path. \
* AT_PKT_END must not survive the arithmetic. \
*/ \
if r9 < r8 goto l1_%=; \
r0 = 0; \
exit; \
l1_%=: r0 = *(u8*)(r9 + 0); \
r0 = 0; \
exit; \
" :
: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
__imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
: __clobber_all);
}
char _license[] SEC("license") = "GPL";