[linux] 08/08: ip6_gre: fix ip6gre_err() invalid reads (CVE-2017-5897)

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Tue Feb 21 03:08:33 UTC 2017


This is an automated email from the git hooks/post-receive script.

benh pushed a commit to branch jessie-security
in repository linux.

commit de459631510f327a132cd96bbb418b16c7cbdfec
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Tue Feb 21 02:13:54 2017 +0000

    ip6_gre: fix ip6gre_err() invalid reads (CVE-2017-5897)
---
 debian/changelog                                   |  1 +
 .../all/ip6_gre-fix-ip6gre_err-invalid-reads.patch | 88 ++++++++++++++++++++++
 debian/patches/series                              |  1 +
 3 files changed, 90 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index d7b76e7..0644e83 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -17,6 +17,7 @@ linux (3.16.39-1+deb8u1) UNRELEASED; urgency=medium
   * selinux: fix off-by-one in setprocattr (CVE-2017-2618)
   * USB: serial: kl5kusb105: fix line-state error handling (CVE-2017-5549)
   * tmpfs: clear S_ISGID when setting posix ACLs (CVE-2017-5551)
+  * ip6_gre: fix ip6gre_err() invalid reads (CVE-2017-5897)
 
  -- Salvatore Bonaccorso <carnil at debian.org>  Sat, 18 Feb 2017 18:26:58 +0100
 
diff --git a/debian/patches/bugfix/all/ip6_gre-fix-ip6gre_err-invalid-reads.patch b/debian/patches/bugfix/all/ip6_gre-fix-ip6gre_err-invalid-reads.patch
new file mode 100644
index 0000000..ae10529
--- /dev/null
+++ b/debian/patches/bugfix/all/ip6_gre-fix-ip6gre_err-invalid-reads.patch
@@ -0,0 +1,88 @@
+From: Eric Dumazet <edumazet at google.com>
+Date: Sat, 4 Feb 2017 23:18:55 -0800
+Subject: ip6_gre: fix ip6gre_err() invalid reads
+Origin: https://git.kernel.org/linus/7892032cfe67f4bde6fc2ee967e45a8fbaf33756
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-5897
+
+Andrey Konovalov reported out of bound accesses in ip6gre_err()
+
+If GRE flags contains GRE_KEY, the following expression
+*(((__be32 *)p) + (grehlen / 4) - 1)
+
+accesses data ~40 bytes after the expected point, since
+grehlen includes the size of IPv6 headers.
+
+Let's use a "struct gre_base_hdr *greh" pointer to make this
+code more readable.
+
+p[1] becomes greh->protocol.
+grhlen is the GRE header length.
+
+Fixes: c12b395a4664 ("gre: Support GRE over IPv6")
+Signed-off-by: Eric Dumazet <edumazet at google.com>
+Reported-by: Andrey Konovalov <andreyknvl at google.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+[bwh: Backported to 3.16: adjust context]
+---
+ net/ipv6/ip6_gre.c | 40 +++++++++++++++++++++-------------------
+ 1 file changed, 21 insertions(+), 19 deletions(-)
+
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -364,35 +364,37 @@ static void ip6gre_tunnel_uninit(struct
+ 
+ 
+ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+-		u8 type, u8 code, int offset, __be32 info)
++		       u8 type, u8 code, int offset, __be32 info)
+ {
+-	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data;
+-	__be16 *p = (__be16 *)(skb->data + offset);
+-	int grehlen = offset + 4;
++	const struct gre_base_hdr *greh;
++	const struct ipv6hdr *ipv6h;
++	int grehlen = sizeof(*greh);
+ 	struct ip6_tnl *t;
++	int key_off = 0;
+ 	__be16 flags;
++	__be32 key;
+ 
+-	flags = p[0];
+-	if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
+-		if (flags&(GRE_VERSION|GRE_ROUTING))
+-			return;
+-		if (flags&GRE_KEY) {
+-			grehlen += 4;
+-			if (flags&GRE_CSUM)
+-				grehlen += 4;
+-		}
++	if (!pskb_may_pull(skb, offset + grehlen))
++		return;
++	greh = (const struct gre_base_hdr *)(skb->data + offset);
++	flags = greh->flags;
++	if (flags & (GRE_VERSION | GRE_ROUTING))
++		return;
++	if (flags & GRE_CSUM)
++		grehlen += 4;
++	if (flags & GRE_KEY) {
++		key_off = grehlen + offset;
++		grehlen += 4;
+ 	}
+ 
+-	/* If only 8 bytes returned, keyed message will be dropped here */
+-	if (!pskb_may_pull(skb, grehlen))
++	if (!pskb_may_pull(skb, offset + grehlen))
+ 		return;
+ 	ipv6h = (const struct ipv6hdr *)skb->data;
+-	p = (__be16 *)(skb->data + offset);
++	greh = (const struct gre_base_hdr *)(skb->data + offset);
++	key = key_off ? *(__be32 *)(skb->data + key_off) : 0;
+ 
+ 	t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr,
+-				flags & GRE_KEY ?
+-				*(((__be32 *)p) + (grehlen / 4) - 1) : 0,
+-				p[1]);
++				 key, greh->protocol);
+ 	if (t == NULL)
+ 		return;
+ 
diff --git a/debian/patches/series b/debian/patches/series
index b1cc4da..10ca00b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -691,6 +691,7 @@ bugfix/x86/kvm-x86-introduce-segmented_write_std.patch
 bugfix/all/selinux-fix-off-by-one-in-setprocattr.patch
 bugfix/all/usb-serial-kl5kusb105-fix-line-state-error-handling.patch
 bugfix/all/tmpfs-clear-s_isgid-when-setting-posix-acls.patch
+bugfix/all/ip6_gre-fix-ip6gre_err-invalid-reads.patch
 
 # Fix ABI changes
 debian/of-fix-abi-changes.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list