Message ID | 20240523141434.1752483-1-willemdebruijn.kernel@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | be008726d0ac338a6bb19c2da2853e3e2112b055 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net] net: gro: initialize network_offset in network layer | expand |
On Thu, May 23, 2024 at 4:14 PM Willem de Bruijn <willemdebruijn.kernel@gmail.com> wrote: > > From: Willem de Bruijn <willemb@google.com> > > Syzkaller was able to trigger > > kernel BUG at net/core/gro.c:424 ! > RIP: 0010:gro_pull_from_frag0 net/core/gro.c:424 [inline] > RIP: 0010:gro_try_pull_from_frag0 net/core/gro.c:446 [inline] > RIP: 0010:dev_gro_receive+0x242f/0x24b0 net/core/gro.c:571 > > Due to using an incorrect NAPI_GRO_CB(skb)->network_offset. > > The referenced commit sets this offset to 0 in skb_gro_reset_offset. > That matches the expected case in dev_gro_receive: > > pp = INDIRECT_CALL_INET(ptype->callbacks.gro_receive, > ipv6_gro_receive, inet_gro_receive, > &gro_list->list, skb); > > But syzkaller injected an skb with protocol ETH_P_TEB into an ip6gre > device (by writing the IP6GRE encapsulated version to a TAP device). > The result was a first call to eth_gro_receive, and thus an extra > ETH_HLEN in network_offset that should not be there. First issue hit > is when computing offset from network header in ipv6_gro_pull_exthdrs. > > Initialize both offsets in the network layer gro_receive. > > This pairs with all reads in gro_receive, which use > skb_gro_receive_network_offset(). > > Fixes: 186b1ea73ad8 ("net: gro: use cb instead of skb->network_header") > Reported-by: syzkaller <syzkaller@googlegroups.com> > Signed-off-by: Willem de Bruijn <willemb@google.com> > CC: Richard Gobert <richardbgobert@gmail.com> Reviewed-by: Eric Dumazet <edumazet@google.com>
Hello: This patch was applied to netdev/net.git (main) by Jakub Kicinski <kuba@kernel.org>: On Thu, 23 May 2024 10:13:45 -0400 you wrote: > From: Willem de Bruijn <willemb@google.com> > > Syzkaller was able to trigger > > kernel BUG at net/core/gro.c:424 ! > RIP: 0010:gro_pull_from_frag0 net/core/gro.c:424 [inline] > RIP: 0010:gro_try_pull_from_frag0 net/core/gro.c:446 [inline] > RIP: 0010:dev_gro_receive+0x242f/0x24b0 net/core/gro.c:571 > > [...] Here is the summary with links: - [net] net: gro: initialize network_offset in network layer https://git.kernel.org/netdev/net/c/be008726d0ac You are awesome, thank you!
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 86cce7e9c2d1..add3e291a301 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1532,7 +1532,7 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb) } NAPI_GRO_CB(skb)->flush |= flush; - NAPI_GRO_CB(skb)->inner_network_offset = off; + NAPI_GRO_CB(skb)->network_offsets[NAPI_GRO_CB(skb)->encap_mark] = off; /* Note : No need to call skb_gro_postpull_rcsum() here, * as we already checked checksum over ipv4 header was 0 diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index bd5aff97d8b1..9822163428b0 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -236,7 +236,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head, if (unlikely(!iph)) goto out; - NAPI_GRO_CB(skb)->inner_network_offset = off; + NAPI_GRO_CB(skb)->network_offsets[NAPI_GRO_CB(skb)->encap_mark] = off; flush += ntohs(iph->payload_len) != skb->len - hlen;