Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163131542
D17230.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D17230.id.diff
View Options
Index: head/sys/netinet6/udp6_usrreq.c
===================================================================
--- head/sys/netinet6/udp6_usrreq.c
+++ head/sys/netinet6/udp6_usrreq.c
@@ -698,7 +698,7 @@
u_int32_t ulen, plen;
uint16_t cscov;
u_short fport;
- uint8_t nxt, unlock_udbinfo;
+ uint8_t nxt, unlock_inp, unlock_udbinfo;
/* addr6 has been validated in udp6_send(). */
sin6 = (struct sockaddr_in6 *)addr6;
@@ -734,7 +734,22 @@
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
- INP_RLOCK(inp);
+ /*
+ * In the following cases we want a write lock on the inp for either
+ * local operations or for possible route cache updates in the IPv6
+ * output path:
+ * - on connected sockets (sin6 is NULL) for route cache updates,
+ * - when we are not bound to an address and source port (it is
+ * in6_pcbsetport() which will require the write lock).
+ */
+ if (sin6 == NULL || (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
+ inp->inp_lport == 0)) {
+ INP_WLOCK(inp);
+ unlock_inp = UH_WLOCKED;
+ } else {
+ INP_RLOCK(inp);
+ unlock_inp = UH_RLOCKED;
+ }
nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ?
IPPROTO_UDP : IPPROTO_UDPLITE;
@@ -758,7 +773,10 @@
* potential race in which the factors causing us to
* select the UDPv4 output routine are invalidated?
*/
- INP_RUNLOCK(inp);
+ if (unlock_inp == UH_WLOCKED)
+ INP_WUNLOCK(inp);
+ else
+ INP_RUNLOCK(inp);
if (sin6)
in6_sin6_2_sin_in_sock((struct sockaddr *)sin6);
pru = inetsw[ip_protox[nxt]].pr_usrreqs;
@@ -772,7 +790,10 @@
if (control) {
if ((error = ip6_setpktopts(control, &opt,
inp->in6p_outputopts, td->td_ucred, nxt)) != 0) {
- INP_RUNLOCK(inp);
+ if (unlock_inp == UH_WLOCKED)
+ INP_WUNLOCK(inp);
+ else
+ INP_RUNLOCK(inp);
ip6_clearpktopts(&opt, -1);
if (control)
m_freem(control);
@@ -786,12 +807,6 @@
pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
if (sin6 != NULL &&
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) && inp->inp_lport == 0) {
- INP_RUNLOCK(inp);
- /*
- * XXX there is a short window here which could lead to a race;
- * should we re-check that what got us here is still valid?
- */
- INP_WLOCK(inp);
INP_HASH_WLOCK(pcbinfo);
unlock_udbinfo = UH_WLOCKED;
} else if (sin6 != NULL &&
@@ -972,9 +987,10 @@
UDPLITE_PROBE(send, NULL, inp, ip6, inp, udp6);
else
UDP_PROBE(send, NULL, inp, ip6, inp, udp6);
- error = ip6_output(m, optp, &inp->inp_route6, flags,
+ error = ip6_output(m, optp,
+ (unlock_inp == UH_WLOCKED) ? &inp->inp_route6 : NULL, flags,
inp->in6p_moptions, NULL, inp);
- if (unlock_udbinfo == UH_WLOCKED)
+ if (unlock_inp == UH_WLOCKED)
INP_WUNLOCK(inp);
else
INP_RUNLOCK(inp);
@@ -987,12 +1003,20 @@
release:
if (unlock_udbinfo == UH_WLOCKED) {
+ KASSERT(unlock_inp == UH_WLOCKED, ("%s: excl udbinfo lock, "
+ "non-excl inp lock: pcbinfo %p %#x inp %p %#x",
+ __func__, pcbinfo, unlock_udbinfo, inp, unlock_inp));
INP_HASH_WUNLOCK(pcbinfo);
INP_WUNLOCK(inp);
} else if (unlock_udbinfo == UH_RLOCKED) {
+ KASSERT(unlock_inp == UH_RLOCKED, ("%s: non-excl udbinfo lock, "
+ "excl inp lock: pcbinfo %p %#x inp %p %#x",
+ __func__, pcbinfo, unlock_udbinfo, inp, unlock_inp));
INP_HASH_RUNLOCK_ET(pcbinfo, et);
INP_RUNLOCK(inp);
- } else
+ } else if (unlock_inp == UH_WLOCKED)
+ INP_WUNLOCK(inp);
+ else
INP_RUNLOCK(inp);
if (control) {
ip6_clearpktopts(&opt, -1);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jul 21, 9:04 AM (25 m, 54 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35311228
Default Alt Text
D17230.id.diff (3 KB)
Attached To
Mode
D17230: Update udp6_output() inp locking to avoid concurrency issues with route cache updates
Attached
Detach File
Event Timeline
Log In to Comment