]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/bpf: Add test for stale pkt range after scalar arithmetic
authorDaniel Borkmann <daniel@iogearbox.net>
Thu, 9 Apr 2026 15:50:16 +0000 (17:50 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 9 Apr 2026 20:11:31 +0000 (13:11 -0700)
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>
tools/testing/selftests/bpf/progs/verifier_direct_packet_access.c

index 4ee3b7a708f7a47b9305139eed8e5ab733687b50..915a9707298b0da3e9fc21d2cfb6b04efac7e7de 100644 (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";