Skip to contentSkip to conversation

Patch "ipv6: fix ip6_tnl_parse_tlv_enc_lim()" has been added to the 4.4-stable tree

PATCH [email protected] 1 participant 1 message Feb 15, 2017

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

    ipv6: fix ip6_tnl_parse_tlv_enc_lim()

to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
ipv6-fix-ip6_tnl_parse_tlv_enc_lim.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From foo@baz Tue Feb 14 16:29:59 PST 2017

From: Eric Dumazet <[email protected]>
Date: Mon, 23 Jan 2017 16:43:06 -0800
Subject: ipv6: fix ip6_tnl_parse_tlv_enc_lim()

From: Eric Dumazet <[email protected]>

[ Upstream commit fbfa743a9d2a0ffa24251764f10afc13eb21e739 ]

This function suffers from multiple issues.

First one is that pskb_may_pull() may reallocate skb->head, so the 'raw' pointer needs either to be reloaded or not used at all.

Second issue is that NEXTHDR_DEST handling does not validate that the options are present in skb->data, so we might read garbage or access non existent memory.

With help from Willem de Bruijn.

---
 net/ipv6/ip6_tunnel.c |   34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)
net/ipv6/ip6_tunnel.c +22 -12
@@ -479,18 +479,19 @@ ip6_tnl_dev_uninit(struct net_device *de
 
 __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
 {
-	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw;
-	__u8 nexthdr = ipv6h->nexthdr;
-	__u16 off = sizeof(*ipv6h);
+	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw;
+	unsigned int nhoff = raw - skb->data;
+	unsigned int off = nhoff + sizeof(*ipv6h);
+	u8 next, nexthdr = ipv6h->nexthdr;
 
 	while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
-		__u16 optlen = 0;
 		struct ipv6_opt_hdr *hdr;
-		if (raw + off + sizeof(*hdr) > skb->data &&
-		    !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr)))
+		u16 optlen;
+
+		if (!pskb_may_pull(skb, off + sizeof(*hdr)))
 			break;
 
-		hdr = (struct ipv6_opt_hdr *) (raw + off);
+		hdr = (struct ipv6_opt_hdr *)(skb->data + off);
 		if (nexthdr == NEXTHDR_FRAGMENT) {
 			struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
 			if (frag_hdr->frag_off)
@@ -501,20 +502,29 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct s
 		} else {
 			optlen = ipv6_optlen(hdr);
 		}
+		/* cache hdr->nexthdr, since pskb_may_pull() might
+		 * invalidate hdr
+		 */
+		next = hdr->nexthdr;
 		if (nexthdr == NEXTHDR_DEST) {
-			__u16 i = off + 2;
+			u16 i = 2;
+
+			/* Remember : hdr is no longer valid at this point. */
+			if (!pskb_may_pull(skb, off + optlen))
+				break;
+
 			while (1) {
 				struct ipv6_tlv_tnl_enc_lim *tel;
 
 				/* No more room for encapsulation limit */
-				if (i + sizeof (*tel) > off + optlen)
+				if (i + sizeof(*tel) > optlen)
 					break;
 
-				tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i];
+				tel = (struct ipv6_tlv_tnl_enc_lim *) skb->data + off + i;
 				/* return index of option if found and valid */
 				if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
 				    tel->length == 1)
-					return i;
+					return i + off - nhoff;
 				/* else jump to next option */
 				if (tel->type)
 					i += tel->length + 2;
@@ -522,7 +532,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct s
 					i++;
 			}
 		}
-		nexthdr = hdr->nexthdr;
+		nexthdr = next;
 		off += optlen;
 	}
 	return 0;

Patches currently in stable-queue which might be from [email protected] are

queue-4.4/ipv6-pointer-math-error-in-ip6_tnl_parse_tlv_enc_lim.patch queue-4.4/netlabel-out-of-bound-access-in-cipso_v4_validate.patch queue-4.4/packet-round-up-linear-to-header-len.patch queue-4.4/tun-read-vnet_hdr_sz-once.patch queue-4.4/ipv6-fix-ip6_tnl_parse_tlv_enc_lim.patch queue-4.4/l2tp-do-not-use-udp_ioctl.patch queue-4.4/tcp-fix-0-divide-in-__tcp_select_window.patch queue-4.4/can-fix-kernel-panic-at-security_sock_rcv_skb.patch queue-4.4/net-introduce-device-min_header_len.patch queue-4.4/macvtap-read-vnet_hdr_size-once.patch queue-4.4/tcp-avoid-infinite-loop-in-tcp_splice_read.patch queue-4.4/mlx4-invoke-softirqs-after-napi_reschedule.patch queue-4.4/ipv6-tcp-add-a-missing-tcp_v6_restore_cb.patch queue-4.4/ipv4-keep-skb-dst-around-in-presence-of-ip-options.patch queue-4.4/net-use-a-work-queue-to-defer-net_disable_timestamp-work.patch queue-4.4/ip6_gre-fix-ip6gre_err-invalid-reads.patch