[PATCH net] ipv6: fix out-of-bound access in ip6_parse_tlv()

Subsystems: networking [general], networking [ipv4/ipv6], the rest

STALE1900d

4 messages, 4 authors, 2021-06-24 · open the first message on its own page

[PATCH net] ipv6: fix out-of-bound access in ip6_parse_tlv()

From: Eric Dumazet <hidden>
Date: 2021-06-23 19:44:00

From: Eric Dumazet <edumazet@google.com>

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: c1412fce7ecc ("net/ipv6/exthdrs.c: Strict PadN option checking")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Tom Herbert <redacted>
---

Only compiled, I would appreciate a solid review of this patch before merging it, thanks !

 net/ipv6/exthdrs.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 6f7da8f3e2e5849f917853984c69bf02a0f1e27c..007959d4d3748f1e21f83946024a9967d08b25b6 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -135,18 +135,24 @@ 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:
+		if (nh[off] == IPV6_TLV_PAD1) {
 			optlen = 1;
 			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 +169,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 +189,6 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
 				return false;
 
 			padlen = 0;
-			break;
 		}
 		off += optlen;
 		len -= optlen;
-- 
2.32.0.288.g62a8d224e6-goog

Re: [PATCH net] ipv6: fix out-of-bound access in ip6_parse_tlv()

From: Jakub Kicinski <kuba@kernel.org>
Date: 2021-06-23 22:07:25

On Wed, 23 Jun 2021 12:43:53 -0700 Eric Dumazet wrote:
From: Eric Dumazet <edumazet@google.com>

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: c1412fce7ecc ("net/ipv6/exthdrs.c: Strict PadN option checking")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Tom Herbert <redacted>
---

Only compiled, I would appreciate a solid review of this patch before merging it, thanks !
Reviewed-by: Jakub Kicinski <kuba@kernel.org>

for what that's worth

Re: [PATCH net] ipv6: fix out-of-bound access in ip6_parse_tlv()

From: Paolo Abeni <pabeni@redhat.com>
Date: 2021-06-24 09:49:37

On Wed, 2021-06-23 at 12:43 -0700, Eric Dumazet wrote:
From: Eric Dumazet <edumazet@google.com>

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: c1412fce7ecc ("net/ipv6/exthdrs.c: Strict PadN option checking")
Perhaps even:

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")

for the first issue?
quoted hunk
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Tom Herbert <redacted>
---

Only compiled, I would appreciate a solid review of this patch before merging it, thanks !

 net/ipv6/exthdrs.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 6f7da8f3e2e5849f917853984c69bf02a0f1e27c..007959d4d3748f1e21f83946024a9967d08b25b6 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -135,18 +135,24 @@ 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:
+		if (nh[off] == IPV6_TLV_PAD1) {
 			optlen = 1;
It looks like the above assignment is not needed anymore.

Other than that LGTM,

Thanks!

Paolo

Re: [PATCH net] ipv6: fix out-of-bound access in ip6_parse_tlv()

From: Eric Dumazet <edumazet@google.com>
Date: 2021-06-24 10:08:21

On Thu, Jun 24, 2021 at 11:49 AM Paolo Abeni [off-list ref] wrote:
On Wed, 2021-06-23 at 12:43 -0700, Eric Dumazet wrote:
quoted
From: Eric Dumazet <edumazet@google.com>

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: c1412fce7ecc ("net/ipv6/exthdrs.c: Strict PadN option checking")
Perhaps even:

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")

for the first issue?
+             if (nh[off] == IPV6_TLV_PAD1) {
quoted
                      optlen = 1;
It looks like the above assignment is not needed anymore.

Other than that LGTM,
Thanks for the review, I am sending the v2.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help