Skip to content

Commit fa7b83b

Browse files
DongseokYiborkmann
authored andcommitted
bpf: Check for BPF_F_ADJ_ROOM_FIXED_GSO when bpf_skb_change_proto
In the forwarding path GRO -> BPF 6 to 4 -> GSO for TCP traffic, the coalesced packet payload can be > MSS, but < MSS + 20. bpf_skb_proto_6_to_4() will upgrade the MSS and it can be > the payload length. After then tcp_gso_segment checks for the payload length if it is <= MSS. The condition is causing the packet to be dropped. tcp_gso_segment(): [...] mss = skb_shinfo(skb)->gso_size; if (unlikely(skb->len <= mss)) goto out; [...] Allow to upgrade/downgrade MSS only when BPF_F_ADJ_ROOM_FIXED_GSO is not set. Signed-off-by: Dongseok Yi <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Willem de Bruijn <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent c49661a commit fa7b83b

File tree

1 file changed

+13
-9
lines changed

1 file changed

+13
-9
lines changed

net/core/filter.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3235,7 +3235,7 @@ static int bpf_skb_net_hdr_pop(struct sk_buff *skb, u32 off, u32 len)
32353235
return ret;
32363236
}
32373237

3238-
static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
3238+
static int bpf_skb_proto_4_to_6(struct sk_buff *skb, u64 flags)
32393239
{
32403240
const u32 len_diff = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
32413241
u32 off = skb_mac_header_len(skb);
@@ -3264,7 +3264,9 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
32643264
}
32653265

32663266
/* Due to IPv6 header, MSS needs to be downgraded. */
3267-
skb_decrease_gso_size(shinfo, len_diff);
3267+
if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
3268+
skb_decrease_gso_size(shinfo, len_diff);
3269+
32683270
/* Header must be checked, and gso_segs recomputed. */
32693271
shinfo->gso_type |= SKB_GSO_DODGY;
32703272
shinfo->gso_segs = 0;
@@ -3276,7 +3278,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
32763278
return 0;
32773279
}
32783280

3279-
static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
3281+
static int bpf_skb_proto_6_to_4(struct sk_buff *skb, u64 flags)
32803282
{
32813283
const u32 len_diff = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
32823284
u32 off = skb_mac_header_len(skb);
@@ -3305,7 +3307,9 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
33053307
}
33063308

33073309
/* Due to IPv4 header, MSS can be upgraded. */
3308-
skb_increase_gso_size(shinfo, len_diff);
3310+
if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
3311+
skb_increase_gso_size(shinfo, len_diff);
3312+
33093313
/* Header must be checked, and gso_segs recomputed. */
33103314
shinfo->gso_type |= SKB_GSO_DODGY;
33113315
shinfo->gso_segs = 0;
@@ -3317,17 +3321,17 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
33173321
return 0;
33183322
}
33193323

3320-
static int bpf_skb_proto_xlat(struct sk_buff *skb, __be16 to_proto)
3324+
static int bpf_skb_proto_xlat(struct sk_buff *skb, __be16 to_proto, u64 flags)
33213325
{
33223326
__be16 from_proto = skb->protocol;
33233327

33243328
if (from_proto == htons(ETH_P_IP) &&
33253329
to_proto == htons(ETH_P_IPV6))
3326-
return bpf_skb_proto_4_to_6(skb);
3330+
return bpf_skb_proto_4_to_6(skb, flags);
33273331

33283332
if (from_proto == htons(ETH_P_IPV6) &&
33293333
to_proto == htons(ETH_P_IP))
3330-
return bpf_skb_proto_6_to_4(skb);
3334+
return bpf_skb_proto_6_to_4(skb, flags);
33313335

33323336
return -ENOTSUPP;
33333337
}
@@ -3337,7 +3341,7 @@ BPF_CALL_3(bpf_skb_change_proto, struct sk_buff *, skb, __be16, proto,
33373341
{
33383342
int ret;
33393343

3340-
if (unlikely(flags))
3344+
if (unlikely(flags & ~(BPF_F_ADJ_ROOM_FIXED_GSO)))
33413345
return -EINVAL;
33423346

33433347
/* General idea is that this helper does the basic groundwork
@@ -3357,7 +3361,7 @@ BPF_CALL_3(bpf_skb_change_proto, struct sk_buff *, skb, __be16, proto,
33573361
* that. For offloads, we mark packet as dodgy, so that headers
33583362
* need to be verified first.
33593363
*/
3360-
ret = bpf_skb_proto_xlat(skb, proto);
3364+
ret = bpf_skb_proto_xlat(skb, proto, flags);
33613365
bpf_compute_data_pointers(skb);
33623366
return ret;
33633367
}

0 commit comments

Comments
 (0)