ipv6: discard IP frag queue on more errors
authorPeter Oskolkov <posk@google.com>
Fri, 21 Sep 2018 18:17:15 +0000 (11:17 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 22 Sep 2018 02:45:52 +0000 (19:45 -0700)
This is similar to how ipv4 now behaves:
commit 0ff89efb5246 ("ip: fail fast on IP defrag errors").

Signed-off-by: Peter Oskolkov <posk@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/reassembly.c

index f1b1ff30fe5bc36cc415358c0c92354a68e4268c..536c1d172cbab66432cdfd32501a81238cef5b5e 100644 (file)
@@ -145,7 +145,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
                 */
                if (end < fq->q.len ||
                    ((fq->q.flags & INET_FRAG_LAST_IN) && end != fq->q.len))
-                       goto err;
+                       goto discard_fq;
                fq->q.flags |= INET_FRAG_LAST_IN;
                fq->q.len = end;
        } else {
@@ -162,20 +162,20 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
                if (end > fq->q.len) {
                        /* Some bits beyond end -> corruption. */
                        if (fq->q.flags & INET_FRAG_LAST_IN)
-                               goto err;
+                               goto discard_fq;
                        fq->q.len = end;
                }
        }
 
        if (end == offset)
-               goto err;
+               goto discard_fq;
 
        /* Point into the IP datagram 'data' part. */
        if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data))
-               goto err;
+               goto discard_fq;
 
        if (pskb_trim_rcsum(skb, end - offset))
-               goto err;
+               goto discard_fq;
 
        /* Find out which fragments are in front and at the back of us
         * in the chain of fragments so far.  We must know where to put
@@ -418,6 +418,7 @@ out_fail:
        rcu_read_lock();
        __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
        rcu_read_unlock();
+       inet_frag_kill(&fq->q);
        return -1;
 }