Index: sys/netinet6/udp6_usrreq.c =================================================================== --- sys/netinet6/udp6_usrreq.c +++ sys/netinet6/udp6_usrreq.c @@ -315,6 +315,7 @@ struct inpcb *last; struct inpcbhead *pcblist; struct ip6_moptions *imo; + bool inp_locked = false; /* * In the event that laddr should be set to the link-local @@ -392,8 +393,7 @@ INP_RUNLOCK(inp); /* XXX */ continue; } - - INP_RUNLOCK(inp); + inp_locked = true; } if (last != NULL) { struct mbuf *n; @@ -409,6 +409,8 @@ UDP_PROBE(receive, NULL, last, ip6, last, uh); if (udp6_append(last, n, off, fromsa)) { + if (inp_locked) + INP_RUNLOCK(inp); /* XXX-BZ do we leak m here? */ *mp = NULL; return (IPPROTO_DONE); @@ -429,6 +431,11 @@ if ((last->inp_socket->so_options & (SO_REUSEPORT|SO_REUSEPORT_LB|SO_REUSEADDR)) == 0) break; + + if (inp_locked) { + INP_RUNLOCK(inp); + inp_locked = false; + } } if (last == NULL) { @@ -441,7 +448,10 @@ UDPSTAT_INC(udps_noportmcast); goto badunlocked; } - INP_RLOCK(last); + + if (!inp_locked) + INP_RLOCK(last); + if (__predict_true(last->inp_flags2 & INP_FREED) == 0) { if (nxt == IPPROTO_UDPLITE) UDPLITE_PROBE(receive, NULL, last, ip6, last, uh);