On Tue, 2016-06-14 at 22:15 -0700, Eric Dumazet wrote: > From: Eric Dumazet <eduma...@google.com> > > 1) gre_parse_header() can be called from gre_err() > > At this point transport header points to ICMP header, not the inner > header. > > 2) We can not really change transport header as ipgre_err() will later > assume transport header still points to ICMP header. > > 3) pskb_may_pull() logic in gre_parse_header() really works > if we are interested at zone pointed by skb->data > > So this fix : > > A) changes gre_parse_header() to use skb->data instead of > skb_transport_header() > > B) changes gre_err() to pull the IPv4 header immediately following > the ICMP header that was already pulled earlier. > > C) remove obsolete IPV6 includes > > Signed-off-by: Eric Dumazet <eduma...@google.com> > Cc: Tom Herbert <t...@herbertland.com> > Cc: Maciej Żenczykowski <m...@google.com> > --- > net/ipv4/gre_demux.c | 4 ++-- > net/ipv4/ip_gre.c | 9 +++------ > 2 files changed, 5 insertions(+), 8 deletions(-) > > diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c > index 4c39f4fd332a..0ba26ad9809d 100644 > --- a/net/ipv4/gre_demux.c > +++ b/net/ipv4/gre_demux.c > @@ -71,7 +71,7 @@ int gre_parse_header(struct sk_buff *skb, struct > tnl_ptk_info *tpi, > if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr)))) > return -EINVAL; > > - greh = (struct gre_base_hdr *)skb_transport_header(skb); > + greh = (struct gre_base_hdr *)skb->data; > if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) > return -EINVAL; > > @@ -81,7 +81,7 @@ int gre_parse_header(struct sk_buff *skb, struct > tnl_ptk_info *tpi, > if (!pskb_may_pull(skb, hdr_len)) > return -EINVAL; > > - greh = (struct gre_base_hdr *)skb_transport_header(skb); > + greh = (struct gre_base_hdr *)skb->data; > tpi->proto = greh->protocol; > > options = (__be32 *)(greh + 1); > diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c > index 4d2025f7ec57..454832bc2897 100644 > --- a/net/ipv4/ip_gre.c > +++ b/net/ipv4/ip_gre.c > @@ -49,12 +49,6 @@ > #include <net/gre.h> > #include <net/dst_metadata.h> > > -#if IS_ENABLED(CONFIG_IPV6) > -#include <net/ipv6.h> > -#include <net/ip6_fib.h> > -#include <net/ip6_route.h> > -#endif > - > /* > Problems & solutions > -------------------- > @@ -217,11 +211,14 @@ static void gre_err(struct sk_buff *skb, u32 info) > * by themselves??? > */ > > + const struct iphdr *iph = (struct iphdr *)skb->data; > const int type = icmp_hdr(skb)->type; > const int code = icmp_hdr(skb)->code; > struct tnl_ptk_info tpi; > bool csum_err = false; > > + pskb_pull(skb, iph->ihl * 4); > + > if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP)) < 0) { > if (!csum_err) /* ignore csum errors. */ > return; >
Hmm... I read this prior commit. It looks like we need something else. commit b7f8fe251e4609e2a437bd2c2dea01e61db6849c Author: Jiri Benc <jb...@redhat.com> Date: Fri Apr 29 23:31:32 2016 +0200 gre: do not pull header in ICMP error processing iptunnel_pull_header expects that IP header was already pulled; with this expectation, it pulls the tunnel header. This is not true in gre_err. Furthermore, ipv4_update_pmtu and ipv4_redirect expect that skb->data points to the IP header. We cannot pull the tunnel header in this path. It's just a matter of not calling iptunnel_pull_header - we don't need any of its effects. Fixes: bda7bb463436 ("gre: Allow multiple protocol listener for gre protocol.") Signed-off-by: Jiri Benc <jb...@redhat.com> Signed-off-by: David S. Miller <da...@davemloft.net>