Commit 624085a3 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

ipv6: fix out-of-bound access in ip6_parse_tlv()

First problem is that optlen is fetched without checking
there is more than one byte to parse.

Fix this by taking care of IPV6_TLV_PAD1 before
fetching optlen (under appropriate sanity checks against len)

Second problem is that IPV6_TLV_PADN checks of zero
padding are performed before the check of remaining length.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Fixes: c1412fce ("net/ipv6/exthdrs.c: Strict PadN option checking")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Tom Herbert <tom@herbertland.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d9b6d26f
...@@ -135,18 +135,23 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs, ...@@ -135,18 +135,23 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
len -= 2; len -= 2;
while (len > 0) { while (len > 0) {
int optlen = nh[off + 1] + 2; int optlen, i;
int i;
switch (nh[off]) { if (nh[off] == IPV6_TLV_PAD1) {
case IPV6_TLV_PAD1:
optlen = 1;
padlen++; padlen++;
if (padlen > 7) if (padlen > 7)
goto bad; goto bad;
break; off++;
len--;
continue;
}
if (len < 2)
goto bad;
optlen = nh[off + 1] + 2;
if (optlen > len)
goto bad;
case IPV6_TLV_PADN: if (nh[off] == IPV6_TLV_PADN) {
/* RFC 2460 states that the purpose of PadN is /* RFC 2460 states that the purpose of PadN is
* to align the containing header to multiples * to align the containing header to multiples
* of 8. 7 is therefore the highest valid value. * of 8. 7 is therefore the highest valid value.
...@@ -163,12 +168,7 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs, ...@@ -163,12 +168,7 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
if (nh[off + i] != 0) if (nh[off + i] != 0)
goto bad; goto bad;
} }
break; } else {
default: /* Other TLV code so scan list */
if (optlen > len)
goto bad;
tlv_count++; tlv_count++;
if (tlv_count > max_count) if (tlv_count > max_count)
goto bad; goto bad;
...@@ -188,7 +188,6 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs, ...@@ -188,7 +188,6 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
return false; return false;
padlen = 0; padlen = 0;
break;
} }
off += optlen; off += optlen;
len -= optlen; len -= optlen;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment