Re: [PATCH] net: fix wrong network header length

From: Paolo Abeni
Date: Thu Feb 10 2022 - 11:03:07 EST


On Wed, 2022-02-09 at 18:25 +0800, lina.wang wrote:
> We use NETIF_F_GRO_FRAGLIST not for forwarding scenary, just for
> software udp gro. 
>
I'm wondering why don't you simply enable UDP_GRO on the relevant
socket?

> Whatever NETIF_F_GRO_FRAGLIST or NETIF_F_GRO_FWD,
> skb_segment_list should not have bugs.

The bug is arguably in bpf_skb_proto_6_to_4(), even if fixing it in
skb_segment_list() is possibly easier.

> We modify skb_segment_list, not in epbf. One point is traversing the
> segments costly, another is what @Maciej said, *other* helper may have
> the same problem. In skb_segment_list, it calls
> skb_headers_offset_update to update different headroom, which implys
> header maybe different.

> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 75dfbde8d2e6..f15bbb7449ce 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -3682,6 +3682,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
> struct sk_buff *tail = NULL;
> struct sk_buff *nskb, *tmp;
> int err;
> + unsigned int len_diff = 0;

Mintor nit: please respect the reverse x-mas tree order.

>
> skb_push(skb, -skb_network_offset(skb) + offset);

> @@ -3721,9 +3722,11 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
> skb_push(nskb, -skb_network_offset(nskb) + offset);
>
> skb_release_head_state(nskb);
> + len_diff = skb_network_header_len(nskb) - skb_network_header_len(skb);
> __copy_skb_header(nskb, skb);
>
> skb_headers_offset_update(nskb, skb_headroom(nskb) - skb_headroom(skb));
> + nskb->transport_header += len_diff;

This does not look correct ?!? the network hdr position for nskb will
still be uncorrect?!? and even the mac hdr likely?!? possibly you need
to change the offset in skb_headers_offset_update().

Paolo