Skip to content

Commit b90efd2

Browse files
wdebruijAlexei Starovoitov
authored andcommitted
bpf: only adjust gso_size on bytestream protocols
bpf_skb_change_proto and bpf_skb_adjust_room change skb header length. For GSO packets they adjust gso_size to maintain the same MTU. The gso size can only be safely adjusted on bytestream protocols. Commit d02f51c ("bpf: fix bpf_skb_adjust_net/bpf_skb_proto_xlat to deal with gso sctp skbs") excluded SKB_GSO_SCTP. Since then type SKB_GSO_UDP_L4 has been added, whose contents are one gso_size unit per datagram. Also exclude these. Move from a blacklist to a whitelist check to future proof against additional such new GSO types, e.g., for fraglist based GRO. Fixes: bec1f6f ("udp: generate gso with UDP_SEGMENT") Signed-off-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent d623876 commit b90efd2

File tree

2 files changed

+10
-8
lines changed

2 files changed

+10
-8
lines changed

include/linux/skbuff.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4212,6 +4212,12 @@ static inline bool skb_is_gso_sctp(const struct sk_buff *skb)
42124212
return skb_shinfo(skb)->gso_type & SKB_GSO_SCTP;
42134213
}
42144214

4215+
static inline bool skb_is_gso_tcp(const struct sk_buff *skb)
4216+
{
4217+
return skb_is_gso(skb) &&
4218+
skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6);
4219+
}
4220+
42154221
static inline void skb_gso_reset(struct sk_buff *skb)
42164222
{
42174223
skb_shinfo(skb)->gso_size = 0;

net/core/filter.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,8 +2789,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
27892789
u32 off = skb_mac_header_len(skb);
27902790
int ret;
27912791

2792-
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
2793-
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
2792+
if (!skb_is_gso_tcp(skb))
27942793
return -ENOTSUPP;
27952794

27962795
ret = skb_cow(skb, len_diff);
@@ -2831,8 +2830,7 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
28312830
u32 off = skb_mac_header_len(skb);
28322831
int ret;
28332832

2834-
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
2835-
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
2833+
if (!skb_is_gso_tcp(skb))
28362834
return -ENOTSUPP;
28372835

28382836
ret = skb_unclone(skb, GFP_ATOMIC);
@@ -2957,8 +2955,7 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 len_diff)
29572955
u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb);
29582956
int ret;
29592957

2960-
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
2961-
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
2958+
if (!skb_is_gso_tcp(skb))
29622959
return -ENOTSUPP;
29632960

29642961
ret = skb_cow(skb, len_diff);
@@ -2987,8 +2984,7 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 len_diff)
29872984
u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb);
29882985
int ret;
29892986

2990-
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
2991-
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
2987+
if (!skb_is_gso_tcp(skb))
29922988
return -ENOTSUPP;
29932989

29942990
ret = skb_unclone(skb, GFP_ATOMIC);

0 commit comments

Comments
 (0)