diff options
| author | Alexei Starovoitov <ast@kernel.org> | 2026-04-12 15:42:57 -0700 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-04-12 15:42:57 -0700 |
| commit | 71b500afd2f7336f5b6c6026f2af546fc079be26 (patch) | |
| tree | ea85eea33e93b218bbc7c04a87fd9f2d47fcd296 /net | |
| parent | 47687a29b2c3acc9aa553737d482645813878aed (diff) | |
| parent | f1cc94665df907a85589ddb5fe74d7768ff61533 (diff) | |
Merge branch 'bpf-fix-short-ipv4-ipv6-handling-in-test_run_skb'
Sun Jian says:
====================
bpf: fix short IPv4/IPv6 handling in test_run_skb
bpf_prog_test_run_skb() may access IPv4/IPv6 network headers based on
skb->protocol even when the provided test input only contains an
Ethernet header.
Fix it by rejecting such short IPv4/IPv6 inputs before accessing the
L3 headers, and add a selftest that exercises the reported
bpf_skb_adjust_room() path on ETH_HLEN-sized IPv4/IPv6 EtherType
inputs.
Changes in v4:
- Split the selftests into a separate patch.
- Rework the selftest to actually execute a BPF program calling
bpf_skb_adjust_room().
- Reuse a single struct ethhdr eth_hlen and initialize h_proto from
the test case table.
- Add the Fixes tag to the test_run.c patch.
Link: https://lore.kernel.org/bpf/CABFUUZF_CWQZrRk=L9cNxO=8Z4iSgGfXi3J=hpzeyTKDbfE2-w@mail.gmail.com/T/#mfabfe7e86bb30c0141fbc9f751b8b1cb07767f01
====================
Link: https://patch.msgid.link/20260408034623.180320-1-sun.jian.kdev@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'net')
| -rw-r--r-- | net/bpf/test_run.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 4cd6b3ea1815..2bc04feadfab 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -1137,19 +1137,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: |
