Commit 2475f59c authored by Peter Oskolkov's avatar Peter Oskolkov Committed by David S. Miller
Browse files

ipv6: discard IP frag queue on more errors



This is similar to how ipv4 now behaves:
commit 0ff89efb ("ip: fail fast on IP defrag errors").

Signed-off-by: default avatarPeter Oskolkov <posk@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 075e264f
Loading
Loading
Loading
Loading
+6 −5
Original line number Original line Diff line number Diff line
@@ -145,7 +145,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
		 */
		 */
		if (end < fq->q.len ||
		if (end < fq->q.len ||
		    ((fq->q.flags & INET_FRAG_LAST_IN) && 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.flags |= INET_FRAG_LAST_IN;
		fq->q.len = end;
		fq->q.len = end;
	} else {
	} else {
@@ -162,20 +162,20 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
		if (end > fq->q.len) {
		if (end > fq->q.len) {
			/* Some bits beyond end -> corruption. */
			/* Some bits beyond end -> corruption. */
			if (fq->q.flags & INET_FRAG_LAST_IN)
			if (fq->q.flags & INET_FRAG_LAST_IN)
				goto err;
				goto discard_fq;
			fq->q.len = end;
			fq->q.len = end;
		}
		}
	}
	}


	if (end == offset)
	if (end == offset)
		goto err;
		goto discard_fq;


	/* Point into the IP datagram 'data' part. */
	/* Point into the IP datagram 'data' part. */
	if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data))
	if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data))
		goto err;
		goto discard_fq;


	if (pskb_trim_rcsum(skb, end - offset))
	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
	/* 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
	 * in the chain of fragments so far.  We must know where to put
@@ -418,6 +418,7 @@ out_fail:
	rcu_read_lock();
	rcu_read_lock();
	__IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
	__IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
	rcu_read_unlock();
	rcu_read_unlock();
	inet_frag_kill(&fq->q);
	return -1;
	return -1;
}
}