frag6.c: do not leak packet queue entry in error case

When we are checking for the maximum reassembled packet size of the
fragmentable part and run into the error case (packet too big),
we are leaking the packet queue enntry if this was a first fragment
to arrive.
Properly cleanup, removing the queue entry from the bucket, decrementing
counters, and freeing the memory.

MFC after:	3 weeks
Sponsored by:	Netflix
This commit is contained in:
Bjoern A. Zeeb 2019-10-24 19:47:32 +00:00
parent 7792f70137
commit e5fffe9a69
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354037

View file

@ -572,17 +572,35 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
if (q6->ip6q_unfrglen >= 0) {
/* The 1st fragment has already arrived. */
if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) {
if (only_frag) {
TAILQ_REMOVE(head, q6, ip6q_tq);
V_ip6qb[bucket].count--;
atomic_subtract_int(&V_frag6_nfragpackets, 1);
#ifdef MAC
mac_ip6q_destroy(q6);
#endif
free(q6, M_FRAG6);
}
IP6QB_UNLOCK(bucket);
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
offset - sizeof(struct ip6_frag) +
offsetof(struct ip6_frag, ip6f_offlg));
IP6QB_UNLOCK(bucket);
return (IPPROTO_DONE);
}
} else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
if (only_frag) {
TAILQ_REMOVE(head, q6, ip6q_tq);
V_ip6qb[bucket].count--;
atomic_subtract_int(&V_frag6_nfragpackets, 1);
#ifdef MAC
mac_ip6q_destroy(q6);
#endif
free(q6, M_FRAG6);
}
IP6QB_UNLOCK(bucket);
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
offset - sizeof(struct ip6_frag) +
offsetof(struct ip6_frag, ip6f_offlg));
IP6QB_UNLOCK(bucket);
return (IPPROTO_DONE);
}