Skip to contentSkip to conversation

net: qdisc_pkt_len_init() should be more robust

PATCH In review Eric Dumazet 3 participants 3 messages Jan 19, 2018 – Jan 22, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 net: qdisc_pkt_len_init() should be more robust

From: Eric Dumazet <[email protected]>

Without proper validation of DODGY packets, we might very well feed qdisc_pkt_len_init() with invalid GSO packets.

tcp_hdrlen() might access out-of-bound data, so let's use skb_header_pointer() and proper checks.

Whole story is described in commit d0c081b49137 ("flow_dissector:
properly cap thoff field")

We have the goal of validating DODGY packets earlier in the stack, so we might very well revert this fix in the future.

Cc Willem de Bruijn <[email protected]>
Cc Jason Wang <[email protected]>
Reported-by [email protected]

---
 net/core/dev.c |   19 +++++++++++++++----

 1 file changed, 15 insertions(+), 4 deletions(-)
net/core/dev.c +15 -4
index 0e0ba36eeac9852b8df5ddd398dbc66ad6c83760..613fb4066be7bedbd3cd59ea9cf6eb7ef3100bd0 100644
@@ -3151,10 +3151,21 @@ static void qdisc_pkt_len_init(struct sk_buff *skb)
 		hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
 
 		/* + transport layer */
-		if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
-			hdr_len += tcp_hdrlen(skb);
-		else
-			hdr_len += sizeof(struct udphdr);
+		if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) {
+			const struct tcphdr *th;
+			struct tcphdr _tcphdr;
+
+			th = skb_header_pointer(skb, skb_transport_offset(skb),
+						sizeof(_tcphdr), &_tcphdr);
+			if (likely(th))
+				hdr_len += __tcp_hdrlen(th);
+		} else {
+			struct udphdr _udphdr;
+
+			if (skb_header_pointer(skb, skb_transport_offset(skb),
+					       sizeof(_udphdr), &_udphdr))
+				hdr_len += sizeof(struct udphdr);
+		}
 
 		if (shinfo->gso_type & SKB_GSO_DODGY)
 			gso_segs = DIV_ROUND_UP(skb->len - hdr_len,
Acked-by on v1 1/1
#1 lore raw
Quoted 43 lines · Eric Dumazet

From: Eric Dumazet <[email protected]>

Without proper validation of DODGY packets, we might very well feed qdisc_pkt_len_init() with invalid GSO packets.

tcp_hdrlen() might access out-of-bound data, so let's use skb_header_pointer() and proper checks.

Whole story is described in commit d0c081b49137 ("flow_dissector:
properly cap thoff field")

We have the goal of validating DODGY packets earlier in the stack, so we might very well revert this fix in the future.

Cc Willem de Bruijn <[email protected]>
Cc Jason Wang <[email protected]>
Reported-by [email protected]
---
  net/core/dev.c |   19 +++++++++++++++----
  1 file changed, 15 insertions(+), 4 deletions(-)
net/core/dev.c +8 -4
index 0e0ba36eeac9852b8df5ddd398dbc66ad6c83760..613fb4066be7bedbd3cd59ea9cf6eb7ef3100bd0 100644
@@ -3151,10 +3151,21 @@ static void qdisc_pkt_len_init(struct sk_buff *skb)
  		hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
 
  		/* + transport layer */
-		if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
-			hdr_len += tcp_hdrlen(skb);
-		else
-			hdr_len += sizeof(struct udphdr);
+		if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) {
+			const struct tcphdr *th;
+			struct tcphdr _tcphdr;
+
+			th = skb_header_pointer(skb, skb_transport_offset(skb),
+						sizeof(_tcphdr), &_tcphdr);
+			if (likely(th))
+				hdr_len += __tcp_hdrlen(th);

net/core/dev.c static void qdisc_pkt_len_init(struct sk_buff *skb) · line 3171

Quoted 10 lines
net/core/dev.c +7 -0
+		} else {
+			struct udphdr _udphdr;
+
+			if (skb_header_pointer(skb, skb_transport_offset(skb),
+					       sizeof(_udphdr), &_udphdr))
+				hdr_len += sizeof(struct udphdr);
+		}
 
  		if (shinfo->gso_type & SKB_GSO_DODGY)
  			gso_segs = DIV_ROUND_UP(skb->len - hdr_len,
maintainer
#2 lore raw
In reply to Eric Dumazet

From: Eric Dumazet <[email protected]>
Date: Thu, 18 Jan 2018 19:59:19 -0800

Quoted 11 lines

From: Eric Dumazet <[email protected]>

Without proper validation of DODGY packets, we might very well feed qdisc_pkt_len_init() with invalid GSO packets.

tcp_hdrlen() might access out-of-bound data, so let's use skb_header_pointer() and proper checks.

Whole story is described in commit d0c081b49137 ("flow_dissector:
properly cap thoff field")

Quoted 7 lines

We have the goal of validating DODGY packets earlier in the stack, so we might very well revert this fix in the future.

Cc Willem de Bruijn <[email protected]>
Cc Jason Wang <[email protected]>
Reported-by [email protected]

Applied and queued up for -stable, thanks Eric.