From dda02192f9780167f9fb8fae4b26bc971d4d8fb2 Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Thu, 24 Oct 2019 19:57:18 +0000 Subject: [PATCH] frag6: fix counter leak in error case and optimise code In case the first fragmented part (off=0) arrives we check for the maximum packet size for each fragmented part we already queued with the addition of the unfragmentable part from the first one. For one we do not have to enter the loop at all if this is the first fragmented part to arrive, and we can skip the check. Should we encounter an error case we send an ICMPv6 message for any fragment exceeding the maximum length limit. While dequeueing the original packet and freeing it, statistics were not updated and leaked both the reassembly queue count for the fragment and the global fragment count. Found by code inspection and confirmed by tightening test cases checking more statistical and system counters. While here properly wrap a line. MFC after: 3 weeks Sponsored by: Netflix --- sys/netinet6/frag6.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c index ca8a8004fb3..cdcf153e2f4 100644 --- a/sys/netinet6/frag6.c +++ b/sys/netinet6/frag6.c @@ -608,11 +608,11 @@ frag6_input(struct mbuf **mp, int *offp, int proto) * If it is the first fragment, do the above check for each * fragment already stored in the reassembly queue. */ - if (fragoff == 0) { + if (fragoff == 0 && !only_frag) { TAILQ_FOREACH_SAFE(af6, &q6->ip6q_frags, ip6af_tq, af6tmp) { - if (q6->ip6q_unfrglen + af6->ip6af_off + af6->ip6af_frglen > - IPV6_MAXPACKET) { + if (q6->ip6q_unfrglen + af6->ip6af_off + + af6->ip6af_frglen > IPV6_MAXPACKET) { struct ip6_hdr *ip6err; struct mbuf *merr; int erroff; @@ -622,6 +622,8 @@ frag6_input(struct mbuf **mp, int *offp, int proto) /* Dequeue the fragment. */ TAILQ_REMOVE(&q6->ip6q_frags, af6, ip6af_tq); + q6->ip6q_nfrag--; + atomic_subtract_int(&frag6_nfrags, 1); free(af6, M_FRAG6); /* Set a valid receive interface pointer. */