Message ID | 20201201090507.4137906-1-eric.dumazet@gmail.com |
---|---|
State | New |
Headers | show |
Series | [net] geneve: pull IP header before ECN decapsulation | expand |
On Tue, 1 Dec 2020 01:05:07 -0800 Eric Dumazet wrote: > From: Eric Dumazet <edumazet@google.com> > > IP_ECN_decapsulate() and IP6_ECN_decapsulate() assume > IP header is already pulled. > > geneve does not ensure this yet. > > Fixing this generically in IP_ECN_decapsulate() and > IP6_ECN_decapsulate() is not possible, since callers > pass a pointer that might be freed by pskb_may_pull() > > syzbot reported : > > BUG: KMSAN: uninit-value in __INET_ECN_decapsulate include/net/inet_ecn.h:238 [inline] > BUG: KMSAN: uninit-value in INET_ECN_decapsulate+0x345/0x1db0 include/net/inet_ecn.h:260 > > Fixes: 2d07dc79fe04 ("geneve: add initial netdev driver for GENEVE tunnels") > Signed-off-by: Eric Dumazet <edumazet@google.com> > Reported-by: syzbot <syzkaller@googlegroups.com> Applied, thanks!
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 1426bfc009bc39a61e2cf039c57b56e48abc3fdc..8ae9ce2014a4a3ba7b962a209e28d1f65d4a83bd 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -257,11 +257,21 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs, skb_dst_set(skb, &tun_dst->dst); /* Ignore packet loops (and multicast echo) */ - if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr)) { - geneve->dev->stats.rx_errors++; - goto drop; - } + if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr)) + goto rx_error; + switch (skb_protocol(skb, true)) { + case htons(ETH_P_IP): + if (pskb_may_pull(skb, sizeof(struct iphdr))) + goto rx_error; + break; + case htons(ETH_P_IPV6): + if (pskb_may_pull(skb, sizeof(struct ipv6hdr))) + goto rx_error; + break; + default: + goto rx_error; + } oiph = skb_network_header(skb); skb_reset_network_header(skb); @@ -298,6 +308,8 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs, dev_sw_netstats_rx_add(geneve->dev, len); return; +rx_error: + geneve->dev->stats.rx_errors++; drop: /* Consume bad packet */ kfree_skb(skb);