aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey V. Elsukov <ae@FreeBSD.org>2021-02-11 08:55:39 +0000
committerAndrey V. Elsukov <ae@FreeBSD.org>2021-02-15 10:48:10 +0000
commit9f46322cad4797932c70da1b9aa96a93cc8491ba (patch)
tree9b3659fc3e997ac177d3704e5d2fcd7b437b2645
parent76702e90d0072452da5105033931532ae013dbf1 (diff)
downloadsrc-9f46322cad4797932c70da1b9aa96a93cc8491ba.tar.gz
src-9f46322cad4797932c70da1b9aa96a93cc8491ba.zip
[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 Sponsored by: Yandex LLC (cherry picked from commit c6ded47d0bae801589b564dbe01dccd474edaed0)
-rw-r--r--sys/netinet/udp_usrreq.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 52304ddd6584..c2ad9381850e 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -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);
}