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

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
Loading
Loading
Loading
Loading
+13 −14
Original line number Diff line number Diff line
@@ -135,18 +135,23 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
	len -= 2;

	while (len > 0) {
		int optlen = nh[off + 1] + 2;
		int i;
		int optlen, i;

		switch (nh[off]) {
		case IPV6_TLV_PAD1:
			optlen = 1;
		if (nh[off] == IPV6_TLV_PAD1) {
			padlen++;
			if (padlen > 7)
				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
			 * to align the containing header to multiples
			 * of 8. 7 is therefore the highest valid value.
@@ -163,12 +168,7 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
				if (nh[off + i] != 0)
					goto bad;
			}
			break;

		default: /* Other TLV code so scan list */
			if (optlen > len)
				goto bad;

		} else {
			tlv_count++;
			if (tlv_count > max_count)
				goto bad;
@@ -188,7 +188,6 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
				return false;

			padlen = 0;
			break;
		}
		off += optlen;
		len -= optlen;