[udp] fix possible mbuf and lock leak in udp_input().

In error case we can leave `inp' locked, also we need to free
mbuf chain `m' in the same case. Release the lock and use `badunlocked'
label to exit with freed mbuf. Also modify UDP error statistic to
match the IPv6 code.

Remove redundant INP_RUNLOCK() from the `if (last == NULL)' block,
there are no ways to reach this point with locked `inp'.

Obtained from:	Yandex LLC
MFC after:	3 days
Sponsored by:	Yandex LLC
This commit is contained in:
Andrey V. Elsukov 2021-02-11 11:55:39 +03:00
parent 3c782d9c91
commit c6ded47d0b

View File

@ -610,9 +610,11 @@ udp_input(struct mbuf **mp, int *offp, int proto)
uh);
if (udp_append(last, ip, n, iphlen,
udp_in)) {
goto inp_lost;
INP_RUNLOCK(inp);
goto badunlocked;
}
}
/* Release PCB lock taken on previous pass. */
INP_RUNLOCK(last);
}
last = inp;
@ -635,9 +637,11 @@ udp_input(struct mbuf **mp, int *offp, int proto)
* to send an ICMP Port Unreachable for a broadcast
* or multicast datgram.)
*/
UDPSTAT_INC(udps_noportbcast);
if (inp)
INP_RUNLOCK(inp);
UDPSTAT_INC(udps_noport);
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)))
UDPSTAT_INC(udps_noportmcast);
else
UDPSTAT_INC(udps_noportbcast);
goto badunlocked;
}
if (proto == IPPROTO_UDPLITE)
@ -646,7 +650,6 @@ udp_input(struct mbuf **mp, int *offp, int proto)
UDP_PROBE(receive, NULL, last, ip, last, uh);
if (udp_append(last, ip, m, iphlen, udp_in) == 0)
INP_RUNLOCK(last);
inp_lost:
return (IPPROTO_DONE);
}