diff options
author | rwatson <rwatson@FreeBSD.org> | 2008-09-22 06:44:03 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2008-09-22 06:44:03 +0000 |
commit | 12ddb86062ec9a98a39ff603770a010dc8852f59 (patch) | |
tree | 53e9ec42f885e05246545b8f8a2ec0aa6bfd08a1 /sys/netinet6/udp6_usrreq.c | |
parent | 514fd19ec3b25f4b0ae5633eb65c3edc1731f626 (diff) | |
download | FreeBSD-src-12ddb86062ec9a98a39ff603770a010dc8852f59.zip FreeBSD-src-12ddb86062ec9a98a39ff603770a010dc8852f59.tar.gz |
When invoking the udp_send() from udp6_send() due to use of a v6-mapped
IPv4 address, first drop the udbinfo and inpcb locks, which will otherwise
be recursed. This leads to a potential minor race, but is preferable to a
deadlock when acquiring a read lock after a write lock on the inpcb.
MFC after: 3 days
Reported by: Norbert Papke <fbsd-ml@scrapper.ca>, lioux
Diffstat (limited to 'sys/netinet6/udp6_usrreq.c')
-rw-r--r-- | sys/netinet6/udp6_usrreq.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index fa943d5..7d50c1b 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -976,13 +976,23 @@ udp6_send(struct socket *so, int flags, struct mbuf *m, error = EINVAL; goto out; } + + /* + * XXXRW: We release UDP-layer locks before calling + * udp_send() in order to avoid recursion. However, + * this does mean there is a short window where inp's + * fields are unstable. Could this lead to a + * potential race in which the factors causing us to + * select the UDPv4 output routine are invalidated? + */ + INP_WUNLOCK(inp); + INP_INFO_WUNLOCK(&V_udbinfo); if (sin6) in6_sin6_2_sin_in_sock(addr); pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; - error = ((*pru->pru_send)(so, flags, m, addr, control, - td)); /* addr will just be freed in sendit(). */ - goto out; + return ((*pru->pru_send)(so, flags, m, addr, control, + td)); } } #endif |