mirror of https://github.com/torvalds/linux.git
bpf: Do not let BPF test infra emit invalid GSO types to stack
Yinhao et al. reported that their fuzzer tool was able to trigger a skb_warn_bad_offload() from netif_skb_features() -> gso_features_check(). When a BPF program - triggered via BPF test infra - pushes the packet to the loopback device via bpf_clone_redirect() then mentioned offload warning can be seen. GSO-related features are then rightfully disabled. We get into this situation due to convert___skb_to_skb() setting gso_segs and gso_size but not gso_type. Technically, it makes sense that this warning triggers since the GSO properties are malformed due to the gso_type. Potentially, the gso_type could be marked non-trustworthy through setting it at least to SKB_GSO_DODGY without any other specific assumptions, but that also feels wrong given we should not go further into the GSO engine in the first place. The checks were added in121d57af30("gso: validate gso_type in GSO handlers") because there were malicious (syzbot) senders that combine a protocol with a non-matching gso_type. If we would want to drop such packets, gso_features_check() currently only returns feature flags via netif_skb_features(), so one location for potentially dropping such skbs could be validate_xmit_unreadable_skb(), but then otoh it would be an additional check in the fast-path for a very corner case. Given bpf_clone_redirect() is the only place where BPF test infra could emit such packets, lets reject them right there. Fixes:850a88cc40("bpf: Expose __sk_buff wire_len/gso_segs to BPF_PROG_TEST_RUN") Fixes:cf62089b0e("bpf: Add gso_size to __sk_buff") Reported-by: Yinhao Hu <dddddd@hust.edu.cn> Reported-by: Kaiyan Mei <M202472210@hust.edu.cn> Reported-by: Dongliang Mu <dzm91@hust.edu.cn> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Link: https://patch.msgid.link/20251020075441.127980-1-daniel@iogearbox.net
This commit is contained in:
parent
7361c86485
commit
04a899573f
|
|
@ -945,6 +945,11 @@ static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb)
|
||||||
|
|
||||||
if (__skb->gso_segs > GSO_MAX_SEGS)
|
if (__skb->gso_segs > GSO_MAX_SEGS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Currently GSO type is zero/unset. If this gets extended with
|
||||||
|
* a small list of accepted GSO types in future, the filter for
|
||||||
|
* an unset GSO type in bpf_clone_redirect() can be lifted.
|
||||||
|
*/
|
||||||
skb_shinfo(skb)->gso_segs = __skb->gso_segs;
|
skb_shinfo(skb)->gso_segs = __skb->gso_segs;
|
||||||
skb_shinfo(skb)->gso_size = __skb->gso_size;
|
skb_shinfo(skb)->gso_size = __skb->gso_size;
|
||||||
skb_shinfo(skb)->hwtstamps.hwtstamp = __skb->hwtstamp;
|
skb_shinfo(skb)->hwtstamps.hwtstamp = __skb->hwtstamp;
|
||||||
|
|
|
||||||
|
|
@ -2458,6 +2458,13 @@ BPF_CALL_3(bpf_clone_redirect, struct sk_buff *, skb, u32, ifindex, u64, flags)
|
||||||
if (unlikely(flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL)))
|
if (unlikely(flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* BPF test infra's convert___skb_to_skb() can create type-less
|
||||||
|
* GSO packets. gso_features_check() will detect this as a bad
|
||||||
|
* offload. However, lets not leak them out in the first place.
|
||||||
|
*/
|
||||||
|
if (unlikely(skb_is_gso(skb) && !skb_shinfo(skb)->gso_type))
|
||||||
|
return -EBADMSG;
|
||||||
|
|
||||||
dev = dev_get_by_index_rcu(dev_net(skb->dev), ifindex);
|
dev = dev_get_by_index_rcu(dev_net(skb->dev), ifindex);
|
||||||
if (unlikely(!dev))
|
if (unlikely(!dev))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue