diff options
author | Thorsten Leemhuis <fedora@leemhuis.info> | 2017-02-07 17:39:29 +0100 |
---|---|---|
committer | Thorsten Leemhuis <fedora@leemhuis.info> | 2017-02-07 17:39:29 +0100 |
commit | 454e7e6cc8f6ec1ca49611972d9f024bb3128db8 (patch) | |
tree | becd5a1fa97b93f0b8788087a0acd2283b181c43 /ip6_gre-fix-ip6gre_err-invalid-reads.patch | |
parent | 721a7ba6a26425f5c9af350f92005d89155d09f1 (diff) | |
parent | cbf9a4853ae920d61ed056da9d90f6e679c74308 (diff) | |
download | kernel-454e7e6cc8f6ec1ca49611972d9f024bb3128db8.tar.gz kernel-454e7e6cc8f6ec1ca49611972d9f024bb3128db8.tar.xz kernel-454e7e6cc8f6ec1ca49611972d9f024bb3128db8.zip |
Merge remote-tracking branch 'origin/master'kernel-4.10.0-0.rc7.git1.1.vanilla.knurd.1.fc26kernel-4.10.0-0.rc7.git1.1.vanilla.knurd.1.fc25kernel-4.10.0-0.rc7.git1.1.vanilla.knurd.1.fc24
Diffstat (limited to 'ip6_gre-fix-ip6gre_err-invalid-reads.patch')
-rw-r--r-- | ip6_gre-fix-ip6gre_err-invalid-reads.patch | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/ip6_gre-fix-ip6gre_err-invalid-reads.patch b/ip6_gre-fix-ip6gre_err-invalid-reads.patch new file mode 100644 index 000000000..756663c11 --- /dev/null +++ b/ip6_gre-fix-ip6gre_err-invalid-reads.patch @@ -0,0 +1,91 @@ +From 7892032cfe67f4bde6fc2ee967e45a8fbaf33756 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet <edumazet@google.com> +Date: Sat, 4 Feb 2017 23:18:55 -0800 +Subject: ip6_gre: fix ip6gre_err() invalid reads + +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@google.com> +Reported-by: Andrey Konovalov <andreyknvl@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + net/ipv6/ip6_gre.c | 40 +++++++++++++++++++++------------------- + 1 file changed, 21 insertions(+), 19 deletions(-) + +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 5586318..630b73b 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -367,35 +367,37 @@ static void ip6gre_tunnel_uninit(struct net_device *dev) + + + 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) + return; + +-- +cgit v0.12 + |