Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gso: Ensure that the packet is long enough

When we get a GSO packet from an untrusted source, we need to
ensure that it is sufficiently long so that we don't end up
crashing.

Based on discovery and patch by Ian Campbell.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Herbert Xu and committed by
David S. Miller
4e704ee3 f5572068

+7 -6
+7 -6
net/ipv4/tcp.c
··· 2389 2389 unsigned int seq; 2390 2390 __be32 delta; 2391 2391 unsigned int oldlen; 2392 - unsigned int len; 2392 + unsigned int mss; 2393 2393 2394 2394 if (!pskb_may_pull(skb, sizeof(*th))) 2395 2395 goto out; ··· 2405 2405 oldlen = (u16)~skb->len; 2406 2406 __skb_pull(skb, thlen); 2407 2407 2408 + mss = skb_shinfo(skb)->gso_size; 2409 + if (unlikely(skb->len <= mss)) 2410 + goto out; 2411 + 2408 2412 if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { 2409 2413 /* Packet is from an untrusted source, reset gso_segs. */ 2410 2414 int type = skb_shinfo(skb)->gso_type; 2411 - int mss; 2412 2415 2413 2416 if (unlikely(type & 2414 2417 ~(SKB_GSO_TCPV4 | ··· 2422 2419 !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) 2423 2420 goto out; 2424 2421 2425 - mss = skb_shinfo(skb)->gso_size; 2426 2422 skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); 2427 2423 2428 2424 segs = NULL; ··· 2432 2430 if (IS_ERR(segs)) 2433 2431 goto out; 2434 2432 2435 - len = skb_shinfo(skb)->gso_size; 2436 - delta = htonl(oldlen + (thlen + len)); 2433 + delta = htonl(oldlen + (thlen + mss)); 2437 2434 2438 2435 skb = segs; 2439 2436 th = tcp_hdr(skb); ··· 2448 2447 csum_fold(csum_partial(skb_transport_header(skb), 2449 2448 thlen, skb->csum)); 2450 2449 2451 - seq += len; 2450 + seq += mss; 2452 2451 skb = skb->next; 2453 2452 th = tcp_hdr(skb); 2454 2453