mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
bpf: Don't let bpf_skb_adjust_room() raise gso_size to GSO_BY_FRAGS
When bpf_skb_adjust_room() shrinks a TCP GSO skb, it adds the number of
removed bytes to gso_size. gso_size has 16 bits, and nothing checks the
sum. Thus gso_size can wrap to 0 or to a small size, or it can be
GSO_BY_FRAGS. GSO_BY_FRAGS is not a size. It tells skb_segment() to read
the length of each segment from the frag_list. If the TCP GSO skb has no
frag_list, skb_segment() dereferences a NULL pointer.
Return -ENOTSUPP and do not change the skb if the sum is GSO_BY_FRAGS or
larger. With BPF_F_ADJ_ROOM_FIXED_GSO the helper does not change gso_size,
so it shrinks the skb as before.
Fixes: 2be7e212d5 ("bpf: add bpf_skb_adjust_room helper")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-16-alexei.starovoitov@gmail.com
This commit is contained in:
parent
3f9780d62d
commit
6d8118937b
|
|
@ -3762,6 +3762,14 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff,
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
/*
|
||||
* The MSS is raised by len_diff. It has 16 bits, and GSO_BY_FRAGS is
|
||||
* not a size.
|
||||
*/
|
||||
if (skb_is_gso(skb) && !(flags & BPF_F_ADJ_ROOM_FIXED_GSO) &&
|
||||
skb_shinfo(skb)->gso_size + len_diff >= GSO_BY_FRAGS)
|
||||
return -ENOTSUPP;
|
||||
|
||||
ret = skb_unclone(skb, GFP_ATOMIC);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user