netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* re: gre: Support GRE over IPv6
@ 2012-09-13 16:01 Dan Carpenter
  2012-09-26 11:02 ` Dan Carpenter
  0 siblings, 1 reply; 6+ messages in thread
From: Dan Carpenter @ 2012-09-13 16:01 UTC (permalink / raw)
  To: xeb; +Cc: netdev

Hello Dmitry Kozlov,

The patch c12b395a4664: "gre: Support GRE over IPv6" from Aug 10, 
2012, leads to the following warning:
net/ipv6/ip6_gre.c:1299 ip6gre_header_parse()
	 error: memcpy() 'haddr' too small (8 vs 16)

net/ipv6/ip6_gre.c
  1296  static int ip6gre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
  1297  {
  1298          const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb_mac_header(skb);
  1299          memcpy(haddr, &ipv6h->saddr, sizeof(struct in6_addr));
                       ^^^^^
Smatch thinks this buffer is only 8 characters sometimes.

  1300          return sizeof(struct in6_addr);
  1301  }

One call tree where this would happen would be the
(struct sockaddr_ll *)sll->sll_addr[] in packet_rcv().

-> packet_rcv()
   -> dev_parse_header()
      -> ip6gre_header_parse()

I don't know the code well enough to say if this is a bug or not.  Could
you take a look?

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: gre: Support GRE over IPv6
  2012-09-13 16:01 gre: Support GRE over IPv6 Dan Carpenter
@ 2012-09-26 11:02 ` Dan Carpenter
  2012-09-26 11:39   ` Eric Dumazet
  0 siblings, 1 reply; 6+ messages in thread
From: Dan Carpenter @ 2012-09-26 11:02 UTC (permalink / raw)
  To: xeb; +Cc: netdev

Hi Dmitry,

I never heard back on this whether it was memory corruption bug or
not?

regards,
dan carpenter

On Thu, Sep 13, 2012 at 07:01:05PM +0300, Dan Carpenter wrote:
> Hello Dmitry Kozlov,
> 
> The patch c12b395a4664: "gre: Support GRE over IPv6" from Aug 10, 
> 2012, leads to the following warning:
> net/ipv6/ip6_gre.c:1299 ip6gre_header_parse()
> 	 error: memcpy() 'haddr' too small (8 vs 16)
> 
> net/ipv6/ip6_gre.c
>   1296  static int ip6gre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
>   1297  {
>   1298          const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb_mac_header(skb);
>   1299          memcpy(haddr, &ipv6h->saddr, sizeof(struct in6_addr));
>                        ^^^^^
> Smatch thinks this buffer is only 8 characters sometimes.
> 
>   1300          return sizeof(struct in6_addr);
>   1301  }
> 
> One call tree where this would happen would be the
> (struct sockaddr_ll *)sll->sll_addr[] in packet_rcv().
> 
> -> packet_rcv()
>    -> dev_parse_header()
>       -> ip6gre_header_parse()
> 
> I don't know the code well enough to say if this is a bug or not.  Could
> you take a look?
> 
> regards,
> dan carpenter

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: gre: Support GRE over IPv6
  2012-09-26 11:02 ` Dan Carpenter
@ 2012-09-26 11:39   ` Eric Dumazet
  2012-09-27 23:07     ` David Miller
  0 siblings, 1 reply; 6+ messages in thread
From: Eric Dumazet @ 2012-09-26 11:39 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: xeb, netdev

From: Eric Dumazet <edumazet@google.com>

On Wed, 2012-09-26 at 14:02 +0300, Dan Carpenter wrote:
> Hi Dmitry,
> 
> I never heard back on this whether it was memory corruption bug or
> not?
> 
> regards,
> dan carpenter
> 
> On Thu, Sep 13, 2012 at 07:01:05PM +0300, Dan Carpenter wrote:
> > Hello Dmitry Kozlov,
> > 
> > The patch c12b395a4664: "gre: Support GRE over IPv6" from Aug 10, 
> > 2012, leads to the following warning:
> > net/ipv6/ip6_gre.c:1299 ip6gre_header_parse()
> > 	 error: memcpy() 'haddr' too small (8 vs 16)
> > 
> > net/ipv6/ip6_gre.c
> >   1296  static int ip6gre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
> >   1297  {
> >   1298          const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb_mac_header(skb);
> >   1299          memcpy(haddr, &ipv6h->saddr, sizeof(struct in6_addr));
> >                        ^^^^^
> > Smatch thinks this buffer is only 8 characters sometimes.
> > 
> >   1300          return sizeof(struct in6_addr);
> >   1301  }
> > 
> > One call tree where this would happen would be the
> > (struct sockaddr_ll *)sll->sll_addr[] in packet_rcv().
> > 
> > -> packet_rcv()
> >    -> dev_parse_header()
> >       -> ip6gre_header_parse()
> > 
> > I don't know the code well enough to say if this is a bug or not.  Could
> > you take a look?


All dev_parse_header() callers provide 8 bytes of storage.

By the way net/netfilter/nfnetlink_log.c and
net/netfilter/nfnetlink_queue_core.c leaks the _pad field to userspace,
I will send a separate patch to netfilter guys.

I would just remove this stuff, as it was copied/pasted from
ipv4/ip_gre.c without thinking of its use.

Thanks

[PATCH net-next] ipv6: gre: remove ip6gre_header_parse()

dev_parse_header() callers provide 8 bytes of storage,
so it's not possible to store an IPv6 address.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
---
 net/ipv6/ip6_gre.c |    8 --------
 1 file changed, 8 deletions(-)

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 424d11a..796f5d5 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1293,16 +1293,8 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev,
 	return -t->hlen;
 }
 
-static int ip6gre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
-{
-	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb_mac_header(skb);
-	memcpy(haddr, &ipv6h->saddr, sizeof(struct in6_addr));
-	return sizeof(struct in6_addr);
-}
-
 static const struct header_ops ip6gre_header_ops = {
 	.create	= ip6gre_header,
-	.parse	= ip6gre_header_parse,
 };
 
 static const struct net_device_ops ip6gre_netdev_ops = {

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: gre: Support GRE over IPv6
  2012-09-26 11:39   ` Eric Dumazet
@ 2012-09-27 23:07     ` David Miller
  0 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2012-09-27 23:07 UTC (permalink / raw)
  To: eric.dumazet; +Cc: dan.carpenter, xeb, netdev

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 26 Sep 2012 13:39:20 +0200

> From: Eric Dumazet <edumazet@google.com>
 ...
> [PATCH net-next] ipv6: gre: remove ip6gre_header_parse()
> 
> dev_parse_header() callers provide 8 bytes of storage,
> so it's not possible to store an IPv6 address.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

Applied, thanks Eric.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: gre: Support GRE over IPv6
       [not found] <20121002205219.7C3BD340556@ra.kernel.org>
@ 2013-04-24 12:23 ` Geert Uytterhoeven
  2013-04-24 15:14   ` Eric Dumazet
  0 siblings, 1 reply; 6+ messages in thread
From: Geert Uytterhoeven @ 2013-04-24 12:23 UTC (permalink / raw)
  To: Dmitry Kozlov, David S. Miller; +Cc: netdev, Linux Kernel Development

On Tue, 2 Oct 2012, Linux Kernel Mailing List wrote:
> Gitweb:     http://git.kernel.org/linus/;a=commit;h=c12b395a46646bab69089ce7016ac78177f6001f
> Commit:     c12b395a46646bab69089ce7016ac78177f6001f
> Parent:     b7bc2a5b5bd99b216c3e5fe68c7f45c684ab5745
> Author:     xeb@mail.ru <xeb@mail.ru>
> AuthorDate: Fri Aug 10 00:51:50 2012 +0000
> Committer:  David S. Miller <davem@davemloft.net>
> CommitDate: Tue Aug 14 14:28:32 2012 -0700
> 
>     gre: Support GRE over IPv6
>     
>     GRE over IPv6 implementation.
>     
>     Signed-off-by: Dmitry Kozlov <xeb@mail.ru>
>     Signed-off-by: David S. Miller <davem@davemloft.net>

> --- /dev/null
> +++ b/net/ipv6/ip6_gre.c

> +static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
> +			 struct net_device *dev,
> +			 __u8 dsfield,
> +			 struct flowi6 *fl6,
> +			 int encap_limit,
> +			 __u32 *pmtu)
> +{
> +	struct net *net = dev_net(dev);
> +	struct ip6_tnl *tunnel = netdev_priv(dev);
> +	struct net_device *tdev;    /* Device to other host */
> +	struct ipv6hdr  *ipv6h;     /* Our new IP header */
> +	unsigned int max_headroom;  /* The extra header space needed */

max_headroom is not initialized

> +	mtu = dst_mtu(dst) - sizeof(*ipv6h);
> +	if (encap_limit >= 0) {
> +		max_headroom += 8;

Hence gcc (4.1.2) rightfully complains:

net/ipv6/ip6_gre.c: In function ‘ip6gre_xmit2’:
net/ipv6/ip6_gre.c:713: warning: ‘max_headroom’ is used uninitialized in this function

However, initializing max_headroom to zero at the top, or replacing the line
above by "max_headroom = 8" doesn't seem to be the right fix...

> +		mtu -= 8;
> +	}
> +	if (mtu < IPV6_MIN_MTU)
> +		mtu = IPV6_MIN_MTU;
> +	if (skb_dst(skb))
> +		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
> +	if (skb->len > mtu) {
> +		*pmtu = mtu;
> +		err = -EMSGSIZE;
> +		goto tx_err_dst_release;
> +	}
> +
> +	if (tunnel->err_count > 0) {
> +		if (time_before(jiffies,
> +				tunnel->err_time + IP6TUNNEL_ERR_TIMEO)) {
> +			tunnel->err_count--;
> +
> +			dst_link_failure(skb);
> +		} else
> +			tunnel->err_count = 0;
> +	}
> +
> +	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len;

... as max_headroom is overwritten here anyway?

So something is really wrong here. What is the right fix?

This issue is present in current mainline as of v3.7.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: gre: Support GRE over IPv6
  2013-04-24 12:23 ` Geert Uytterhoeven
@ 2013-04-24 15:14   ` Eric Dumazet
  0 siblings, 0 replies; 6+ messages in thread
From: Eric Dumazet @ 2013-04-24 15:14 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Dmitry Kozlov, David S. Miller, netdev, Linux Kernel Development

On Wed, 2013-04-24 at 14:23 +0200, Geert Uytterhoeven wrote:
> On Tue, 2 Oct 2012, Linux Kernel Mailing List wrote:
> > Gitweb:     http://git.kernel.org/linus/;a=commit;h=c12b395a46646bab69089ce7016ac78177f6001f
> > Commit:     c12b395a46646bab69089ce7016ac78177f6001f
> > Parent:     b7bc2a5b5bd99b216c3e5fe68c7f45c684ab5745
> > Author:     xeb@mail.ru <xeb@mail.ru>
> > AuthorDate: Fri Aug 10 00:51:50 2012 +0000
> > Committer:  David S. Miller <davem@davemloft.net>
> > CommitDate: Tue Aug 14 14:28:32 2012 -0700
> > 
> >     gre: Support GRE over IPv6
> >     
> >     GRE over IPv6 implementation.
> >     
> >     Signed-off-by: Dmitry Kozlov <xeb@mail.ru>
> >     Signed-off-by: David S. Miller <davem@davemloft.net>
> 
> > --- /dev/null
> > +++ b/net/ipv6/ip6_gre.c
> 
> > +static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
> > +			 struct net_device *dev,
> > +			 __u8 dsfield,
> > +			 struct flowi6 *fl6,
> > +			 int encap_limit,
> > +			 __u32 *pmtu)
> > +{
> > +	struct net *net = dev_net(dev);
> > +	struct ip6_tnl *tunnel = netdev_priv(dev);
> > +	struct net_device *tdev;    /* Device to other host */
> > +	struct ipv6hdr  *ipv6h;     /* Our new IP header */
> > +	unsigned int max_headroom;  /* The extra header space needed */
> 
> max_headroom is not initialized
> 
> > +	mtu = dst_mtu(dst) - sizeof(*ipv6h);
> > +	if (encap_limit >= 0) {
> > +		max_headroom += 8;
> 
> Hence gcc (4.1.2) rightfully complains:
> 
> net/ipv6/ip6_gre.c: In function ‘ip6gre_xmit2’:
> net/ipv6/ip6_gre.c:713: warning: ‘max_headroom’ is used uninitialized in this function
> 
> However, initializing max_headroom to zero at the top, or replacing the line
> above by "max_headroom = 8" doesn't seem to be the right fix...
> 
> > +		mtu -= 8;
> > +	}
> > +	if (mtu < IPV6_MIN_MTU)
> > +		mtu = IPV6_MIN_MTU;
> > +	if (skb_dst(skb))
> > +		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
> > +	if (skb->len > mtu) {
> > +		*pmtu = mtu;
> > +		err = -EMSGSIZE;
> > +		goto tx_err_dst_release;
> > +	}
> > +
> > +	if (tunnel->err_count > 0) {
> > +		if (time_before(jiffies,
> > +				tunnel->err_time + IP6TUNNEL_ERR_TIMEO)) {
> > +			tunnel->err_count--;
> > +
> > +			dst_link_failure(skb);
> > +		} else
> > +			tunnel->err_count = 0;
> > +	}
> > +
> > +	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len;
> 
> ... as max_headroom is overwritten here anyway?
> 
> So something is really wrong here. What is the right fix?
> 
> This issue is present in current mainline as of v3.7.

I would use following fix. Can you provide an official patch ?

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index d3ddd84..150d17d 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -620,7 +620,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
 	struct ip6_tnl *tunnel = netdev_priv(dev);
 	struct net_device *tdev;    /* Device to other host */
 	struct ipv6hdr  *ipv6h;     /* Our new IP header */
-	unsigned int max_headroom;  /* The extra header space needed */
+	unsigned int max_headroom = 0;  /* The extra header space needed */
 	int    gre_hlen;
 	struct ipv6_tel_txoption opt;
 	int    mtu;
@@ -693,7 +693,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
 			tunnel->err_count = 0;
 	}
 
-	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len;
+	max_headroom += LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len;
 
 	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
 	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-04-24 15:14 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-13 16:01 gre: Support GRE over IPv6 Dan Carpenter
2012-09-26 11:02 ` Dan Carpenter
2012-09-26 11:39   ` Eric Dumazet
2012-09-27 23:07     ` David Miller
     [not found] <20121002205219.7C3BD340556@ra.kernel.org>
2013-04-24 12:23 ` Geert Uytterhoeven
2013-04-24 15:14   ` Eric Dumazet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).