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
>----------------------------------------------------------------------
>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
>
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
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));
> [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.
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
>