Advertisement






Linux ip6gre_err() invalid reads

CVE Category Price Severity
CVE-2019-16231 CWE-119 $5,000 High
Author Risk Exploitation Type Date
Qualys Security Advisory High Remote 2017-02-06
CPE
cpe:cpe:2.3:a:linux:linux_kernel:6.0:*:*:*:*:*:*:*
CVSS EPSS EPSSP
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2017020050

Below is a copy:

Linux ip6gre_err() invalid readsAndrey 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.

+++ 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;



Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum