[PATCH bpf v4 1/2] bpf: reject short IPv4/IPv6 inputs in bpf_prog_test_run_skb

From: Sun Jian

Date: Tue Apr 07 2026 - 23:47:10 EST


bpf_prog_test_run_skb() calls eth_type_trans() first and then uses
skb->protocol to initialize sk family and address fields for the test
run.

For IPv4 and IPv6 packets, it may access ip_hdr(skb) or ipv6_hdr(skb)
even when the provided test input only contains an Ethernet header.

Reject the input earlier if the Ethernet frame carries IPv4/IPv6
EtherType but the L3 header is too short.

Fold the IPv4/IPv6 header length checks into the existing protocol
switch and return -EINVAL before accessing the network headers.

Fixes: fa5cb548ced6 ("bpf: Setup socket family and addresses in bpf_prog_test_run_skb")
Reported-by: syzbot+619b9ef527f510a57cfc@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=619b9ef527f510a57cfc
Signed-off-by: Sun Jian <sun.jian.kdev@xxxxxxxxx>
---
net/bpf/test_run.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index 178c4738e63b..300e2bfc5a62 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -1120,19 +1120,23 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,

switch (skb->protocol) {
case htons(ETH_P_IP):
- sk->sk_family = AF_INET;
- if (sizeof(struct iphdr) <= skb_headlen(skb)) {
- sk->sk_rcv_saddr = ip_hdr(skb)->saddr;
- sk->sk_daddr = ip_hdr(skb)->daddr;
+ if (skb_headlen(skb) < sizeof(struct iphdr)) {
+ ret = -EINVAL;
+ goto out;
}
+ sk->sk_family = AF_INET;
+ sk->sk_rcv_saddr = ip_hdr(skb)->saddr;
+ sk->sk_daddr = ip_hdr(skb)->daddr;
break;
#if IS_ENABLED(CONFIG_IPV6)
case htons(ETH_P_IPV6):
- sk->sk_family = AF_INET6;
- if (sizeof(struct ipv6hdr) <= skb_headlen(skb)) {
- sk->sk_v6_rcv_saddr = ipv6_hdr(skb)->saddr;
- sk->sk_v6_daddr = ipv6_hdr(skb)->daddr;
+ if (skb_headlen(skb) < sizeof(struct ipv6hdr)) {
+ ret = -EINVAL;
+ goto out;
}
+ sk->sk_family = AF_INET6;
+ sk->sk_v6_rcv_saddr = ipv6_hdr(skb)->saddr;
+ sk->sk_v6_daddr = ipv6_hdr(skb)->daddr;
break;
#endif
default:
--
2.43.0