Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1714955 > unrolled thread

[PATCH 3.16 129/134] ipv6: avoid overflow of offset in ip6_find_1stfragopt

Started byBen Hutchings <ben@decadent.org.uk>
First post2017-08-18 15:30 +0200
Last post2017-08-18 15:30 +0200
Articles 1 — 1 participant

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 3.16 129/134] ipv6: avoid overflow of offset in  ip6_find_1stfragopt Ben Hutchings <ben@decadent.org.uk> - 2017-08-18 15:30 +0200

#1714955 — [PATCH 3.16 129/134] ipv6: avoid overflow of offset in ip6_find_1stfragopt

FromBen Hutchings <ben@decadent.org.uk>
Date2017-08-18 15:30 +0200
Subject[PATCH 3.16 129/134] ipv6: avoid overflow of offset in ip6_find_1stfragopt
Message-ID<ufPvB-4h9-29@gated-at.bofh.it>
3.16.47-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Sabrina Dubroca <sd@queasysnail.net>

commit 6399f1fae4ec29fab5ec76070435555e256ca3a6 upstream.

In some cases, offset can overflow and can cause an infinite loop in
ip6_find_1stfragopt(). Make it unsigned int to prevent the overflow, and
cap it at IPV6_MAXPLEN, since packets larger than that should be invalid.

This problem has been here since before the beginning of git history.

Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/ipv6/output_core.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -44,7 +44,7 @@ EXPORT_SYMBOL_GPL(ipv6_proxy_select_iden
 
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 {
-	u16 offset = sizeof(struct ipv6hdr);
+	unsigned int offset = sizeof(struct ipv6hdr);
 	unsigned int packet_len = skb_tail_pointer(skb) -
 		skb_network_header(skb);
 	int found_rhdr = 0;
@@ -52,6 +52,7 @@ int ip6_find_1stfragopt(struct sk_buff *
 
 	while (offset <= packet_len) {
 		struct ipv6_opt_hdr *exthdr;
+		unsigned int len;
 
 		switch (**nexthdr) {
 
@@ -77,7 +78,10 @@ int ip6_find_1stfragopt(struct sk_buff *
 
 		exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
 						 offset);
-		offset += ipv6_optlen(exthdr);
+		len = ipv6_optlen(exthdr);
+		if (len + offset >= IPV6_MAXPLEN)
+			return -EINVAL;
+		offset += len;
 		*nexthdr = &exthdr->nexthdr;
 	}
 

[toc] | [standalone]


Back to top | Article view | linux.kernel


csiph-web