net: qdisc_pkt_len_init() should be more robust
Subsystems (2)
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.
---
net/core/dev.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
net/core/dev.c +15 -4
@@ -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,
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 useskb_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.
Signed-off-by Eric Dumazet <[email protected]>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@@ -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,
David Miller
maintainerFrom: 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 useskb_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.
Signed-off-by Eric Dumazet <[email protected]>Cc Willem de Bruijn <[email protected]>Cc Jason Wang <[email protected]>Reported-by [email protected]
Applied and queued up for -stable, thanks Eric.