Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111903797
D31734.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D31734.diff
View Options
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2818,6 +2818,7 @@
KASSERT(td != NULL, ("%s: null thread", __func__));
+ error = 0;
lport = 0;
bindall = 1;
inp = (struct sctp_inpcb *)so->so_pcb;
@@ -2830,10 +2831,13 @@
SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr);
}
#endif
+ SCTP_INP_INFO_WLOCK();
+ SCTP_INP_WLOCK(inp);
if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
+ error = EINVAL;
/* already did a bind, subsequent binds NOT allowed ! */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- return (EINVAL);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
if (addr != NULL) {
switch (addr->sa_family) {
@@ -2844,12 +2848,14 @@
/* IPV6_V6ONLY socket? */
if (SCTP_IPV6_V6ONLY(inp)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- return (EINVAL);
+ error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
if (addr->sa_len != sizeof(*sin)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- return (EINVAL);
+ error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
sin = (struct sockaddr_in *)addr;
@@ -2861,7 +2867,7 @@
*/
if ((error = prison_local_ip4(td->td_ucred, &sin->sin_addr)) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
- return (error);
+ goto out;
}
if (sin->sin_addr.s_addr != INADDR_ANY) {
bindall = 0;
@@ -2879,10 +2885,10 @@
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)addr;
-
if (addr->sa_len != sizeof(*sin6)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- return (EINVAL);
+ error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
lport = sin6->sin6_port;
/*
@@ -2893,14 +2899,15 @@
if ((error = prison_local_ip6(td->td_ucred, &sin6->sin6_addr,
(SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
- return (error);
+ goto out;
}
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
bindall = 0;
/* KAME hack: embed scopeid */
if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- return (EINVAL);
+ error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
}
/* this must be cleared for ifa_ifwithaddr() */
@@ -2909,12 +2916,11 @@
}
#endif
default:
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EAFNOSUPPORT);
- return (EAFNOSUPPORT);
+ error = EAFNOSUPPORT;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
}
- SCTP_INP_INFO_WLOCK();
- SCTP_INP_WLOCK(inp);
/* Setup a vrf_id to be the default for the non-bind-all case. */
vrf_id = inp->def_vrf_id;
@@ -2930,9 +2936,7 @@
if (ntohs(lport) < IPPORT_RESERVED) {
if ((error = priv_check(td, PRIV_NETINET_RESERVEDPORT)) != 0) {
SCTP_INP_DECR_REF(inp);
- SCTP_INP_WUNLOCK(inp);
- SCTP_INP_INFO_WUNLOCK();
- return (error);
+ goto out;
}
}
SCTP_INP_WUNLOCK(inp);
@@ -2959,9 +2963,9 @@
goto continue_anyway;
}
SCTP_INP_DECR_REF(inp);
- SCTP_INP_INFO_WUNLOCK();
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE);
- return (EADDRINUSE);
+ error = EADDRINUSE;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out_inp_unlocked;
}
} else {
inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id);
@@ -2985,9 +2989,9 @@
goto continue_anyway;
}
SCTP_INP_DECR_REF(inp);
- SCTP_INP_INFO_WUNLOCK();
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE);
- return (EADDRINUSE);
+ error = EADDRINUSE;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out_inp_unlocked;
}
}
continue_anyway:
@@ -3002,10 +3006,9 @@
(sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) {
port_reuse_active = 1;
} else {
- SCTP_INP_WUNLOCK(inp);
- SCTP_INP_INFO_WUNLOCK();
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE);
- return (EADDRINUSE);
+ error = EADDRINUSE;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
}
}
@@ -3018,10 +3021,8 @@
last = MODULE_GLOBAL(ipport_hilastauto);
} else if (ip_inp->inp_flags & INP_LOWPORT) {
if ((error = priv_check(td, PRIV_NETINET_RESERVEDPORT)) != 0) {
- SCTP_INP_WUNLOCK(inp);
- SCTP_INP_INFO_WUNLOCK();
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
- return (error);
+ goto out;
}
first = MODULE_GLOBAL(ipport_lowfirstauto);
last = MODULE_GLOBAL(ipport_lowlastauto);
@@ -3045,10 +3046,9 @@
break;
}
if (--count == 0) {
- SCTP_INP_WUNLOCK(inp);
- SCTP_INP_INFO_WUNLOCK();
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE);
- return (EADDRINUSE);
+ error = EADDRINUSE;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
if (candidate == last)
candidate = first;
@@ -3062,10 +3062,9 @@
* this really should not happen. The guy did a non-blocking
* bind and then did a close at the same time.
*/
- SCTP_INP_WUNLOCK(inp);
- SCTP_INP_INFO_WUNLOCK();
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- return (EINVAL);
+ error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
/* ok we look clear to give out this port, so lets setup the binding */
if (bindall) {
@@ -3153,21 +3152,19 @@
vrf_id, SCTP_ADDR_NOT_LOCKED);
}
if (ifa == NULL) {
+ error = EADDRNOTAVAIL;
/* Can't find an interface with that address */
- SCTP_INP_WUNLOCK(inp);
- SCTP_INP_INFO_WUNLOCK();
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRNOTAVAIL);
- return (EADDRNOTAVAIL);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
#ifdef INET6
if (addr->sa_family == AF_INET6) {
/* GAK, more FIXME IFA lock? */
if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
/* Can't bind a non-existent addr. */
- SCTP_INP_WUNLOCK(inp);
- SCTP_INP_INFO_WUNLOCK();
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- return (EINVAL);
+ error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+ goto out;
}
}
#endif
@@ -3180,11 +3177,8 @@
/* add this address to the endpoint list */
error = sctp_insert_laddr(&inp->sctp_addr_list, ifa, 0);
- if (error != 0) {
- SCTP_INP_WUNLOCK(inp);
- SCTP_INP_INFO_WUNLOCK();
- return (error);
- }
+ if (error != 0)
+ goto out;
inp->laddr_count++;
}
/* find the bucket */
@@ -3203,10 +3197,14 @@
inp->sctp_lport = lport;
/* turn off just the unbound flag */
+ KASSERT((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) != 0,
+ ("%s: inp %p is already bound", __func__, inp));
inp->sctp_flags &= ~SCTP_PCB_FLAGS_UNBOUND;
+out:
SCTP_INP_WUNLOCK(inp);
+out_inp_unlocked:
SCTP_INP_INFO_WUNLOCK();
- return (0);
+ return (error);
}
static void
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Mar 11, 1:30 AM (18 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17092489
Default Alt Text
D31734.diff (7 KB)
Attached To
Mode
D31734: sctp: Fix racy UNBOUND flag check in sctp_inpcb_bind()
Attached
Detach File
Event Timeline
Log In to Comment