]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ipv6: defrag: drop non-last frags smaller than min mtu
authorFlorian Westphal <fw@strlen.de>
Thu, 13 Sep 2018 14:58:55 +0000 (07:58 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 19 Sep 2018 20:43:47 +0000 (22:43 +0200)
don't bother with pathological cases, they only waste cycles.
IPv6 requires a minimum MTU of 1280 so we should never see fragments
smaller than this (except last frag).

v3: don't use awkward "-offset + len"
v2: drop IPv4 part, which added same check w. IPV4_MIN_MTU (68).
    There were concerns that there could be even smaller frags
    generated by intermediate nodes, e.g. on radio networks.

Cc: Peter Oskolkov <posk@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 0ed4229b08c13c84a3c301a08defdc9e7f4467e6)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c

index a1dc0d6a5949863cdba3ac0003009f41e5114d12..1d2f07cde01a55ea900e111c2466c6d4e4242191 100644 (file)
@@ -565,6 +565,10 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
        hdr = ipv6_hdr(skb);
        fhdr = (struct frag_hdr *)skb_transport_header(skb);
 
+       if (skb->len - skb_network_offset(skb) < IPV6_MIN_MTU &&
+           fhdr->frag_off & htons(IP6_MF))
+               return -EINVAL;
+
        skb_orphan(skb);
        fq = fq_find(net, fhdr->identification, user, hdr,
                     skb->dev ? skb->dev->ifindex : 0);
index e1c5fa5e3873f81193fb129073851adfc89964ee..afaad60dc2ac1929439b6d410e7858959ae43dbe 100644 (file)
@@ -522,6 +522,10 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
                return 1;
        }
 
+       if (skb->len - skb_network_offset(skb) < IPV6_MIN_MTU &&
+           fhdr->frag_off & htons(IP6_MF))
+               goto fail_hdr;
+
        iif = skb->dev ? skb->dev->ifindex : 0;
        fq = fq_find(net, fhdr->identification, hdr, iif);
        if (fq) {