2024-05-07 09:48:59

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH net-next] net: add missing check for TCP fraglist GRO

It turns out that the existing checks do not guarantee that the skb can be
pulled up to the GRO offset. When using the usb r8152 network driver with
GRO fraglist, the BUG() in __skb_pull is often triggered.
Fix the crash by adding the missing check.

Fixes: 8d95dc474f85 ("net: add code for TCP fraglist GRO")
Signed-off-by: Felix Fietkau <[email protected]>
---
net/ipv4/tcp_offload.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index c90704befd7b..a71d2e623f0c 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -353,6 +353,7 @@ struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb,
flush |= (__force int)(flags ^ tcp_flag_word(th2));
flush |= skb->ip_summed != p->ip_summed;
flush |= skb->csum_level != p->csum_level;
+ flush |= !pskb_may_pull(skb, skb_gro_offset(skb));
flush |= NAPI_GRO_CB(p)->count >= 64;

if (flush || skb_gro_receive_list(p, skb))
--
2.44.0



2024-05-07 11:33:58

by Suman Ghosh

[permalink] [raw]
Subject: RE: [EXTERNAL] [PATCH net-next] net: add missing check for TCP fraglist GRO

>----------------------------------------------------------------------
>It turns out that the existing checks do not guarantee that the skb can be
>pulled up to the GRO offset. When using the usb r8152 network driver with
>GRO fraglist, the BUG() in __skb_pull is often triggered.
>Fix the crash by adding the missing check.
>
>Fixes: 8d95dc474f85 ("net: add code for TCP fraglist GRO")
[Suman] Since this is a fix, this should be pushed to "net".
>Signed-off-by: Felix Fietkau <[email protected]>
>---
> net/ipv4/tcp_offload.c | 1 +
> 1 file changed, 1 insertion(+)
>
>diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index
>c90704befd7b..a71d2e623f0c 100644
>--- a/net/ipv4/tcp_offload.c
>+++ b/net/ipv4/tcp_offload.c
>@@ -353,6 +353,7 @@ struct sk_buff *tcp_gro_receive(struct list_head *head,
>struct sk_buff *skb,
> flush |= (__force int)(flags ^ tcp_flag_word(th2));
> flush |= skb->ip_summed != p->ip_summed;
> flush |= skb->csum_level != p->csum_level;
>+ flush |= !pskb_may_pull(skb, skb_gro_offset(skb));
> flush |= NAPI_GRO_CB(p)->count >= 64;
>
> if (flush || skb_gro_receive_list(p, skb))
>--
>2.44.0
>


2024-05-07 11:43:46

by Felix Fietkau

[permalink] [raw]
Subject: Re: [EXTERNAL] [PATCH net-next] net: add missing check for TCP fraglist GRO

On 07.05.24 13:33, Suman Ghosh wrote:
>>----------------------------------------------------------------------
>>It turns out that the existing checks do not guarantee that the skb can be
>>pulled up to the GRO offset. When using the usb r8152 network driver with
>>GRO fraglist, the BUG() in __skb_pull is often triggered.
>>Fix the crash by adding the missing check.
>>
>>Fixes: 8d95dc474f85 ("net: add code for TCP fraglist GRO")
> [Suman] Since this is a fix, this should be pushed to "net".

No, it is fixing a commit that was just pulled into -next.

- Felix


2024-05-07 11:51:36

by Willem de Bruijn

[permalink] [raw]
Subject: RE: [EXTERNAL] [PATCH net-next] net: add missing check for TCP fraglist GRO

Suman Ghosh wrote:
> >----------------------------------------------------------------------
> >It turns out that the existing checks do not guarantee that the skb can be
> >pulled up to the GRO offset. When using the usb r8152 network driver with
> >GRO fraglist, the BUG() in __skb_pull is often triggered.
> >Fix the crash by adding the missing check.
> >
> >Fixes: 8d95dc474f85 ("net: add code for TCP fraglist GRO")

> [Suman] Since this is a fix, this should be pushed to "net".

The referenced patch has only landed in net-next yet.

> >Signed-off-by: Felix Fietkau <[email protected]>

Reviewed-by: Willem de Bruijn <[email protected]>

> >---
> > net/ipv4/tcp_offload.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> >diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index
> >c90704befd7b..a71d2e623f0c 100644
> >--- a/net/ipv4/tcp_offload.c
> >+++ b/net/ipv4/tcp_offload.c
> >@@ -353,6 +353,7 @@ struct sk_buff *tcp_gro_receive(struct list_head *head,
> >struct sk_buff *skb,
> > flush |= (__force int)(flags ^ tcp_flag_word(th2));
> > flush |= skb->ip_summed != p->ip_summed;
> > flush |= skb->csum_level != p->csum_level;
> >+ flush |= !pskb_may_pull(skb, skb_gro_offset(skb));
> > flush |= NAPI_GRO_CB(p)->count >= 64;

The same check already exists in udp_gro_receive, which has for longer
been calling skb_gro_receive_list:

if (!pskb_may_pull(skb, skb_gro_offset(skb))) {
NAPI_GRO_CB(skb)->flush = 1;
return NULL;
}

Alternatively it would make sense to deduplicate the check and move it
to skb_gro_receive_list itself, before

skb_pull(skb, skb_gro_offset(skb));


2024-05-07 12:07:21

by Suman Ghosh

[permalink] [raw]
Subject: RE: [EXTERNAL] [PATCH net-next] net: add missing check for TCP fraglist GRO

> [Suman] Since this is a fix, this should be pushed to "net".
>
>No, it is fixing a commit that was just pulled into -next.
>
>- Felix
[Suman] Got it. Thank you.

2024-05-07 12:09:23

by Eric Dumazet

[permalink] [raw]
Subject: Re: [PATCH net-next] net: add missing check for TCP fraglist GRO

On Tue, May 7, 2024 at 11:41 AM Felix Fietkau <[email protected]> wrote:
>
> It turns out that the existing checks do not guarantee that the skb can be
> pulled up to the GRO offset. When using the usb r8152 network driver with
> GRO fraglist, the BUG() in __skb_pull is often triggered.

Why is it crashing ? I would expect tcp_gro_pull_header() to perform this early.

Please include a stack trace.

> Fix the crash by adding the missing check.
>
> Fixes: 8d95dc474f85 ("net: add code for TCP fraglist GRO")
> Signed-off-by: Felix Fietkau <[email protected]>
> ---
> net/ipv4/tcp_offload.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
> index c90704befd7b..a71d2e623f0c 100644
> --- a/net/ipv4/tcp_offload.c
> +++ b/net/ipv4/tcp_offload.c
> @@ -353,6 +353,7 @@ struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb,
> flush |= (__force int)(flags ^ tcp_flag_word(th2));
> flush |= skb->ip_summed != p->ip_summed;
> flush |= skb->csum_level != p->csum_level;
> + flush |= !pskb_may_pull(skb, skb_gro_offset(skb));
> flush |= NAPI_GRO_CB(p)->count >= 64;
>
> if (flush || skb_gro_receive_list(p, skb))
> --
> 2.44.0
>