summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2016-08-25 09:16:25 +0000
committertuexen <tuexen@FreeBSD.org>2016-08-25 09:16:25 +0000
commit986f593e4573a0f751ae6fa39b49e0a0dcbefbf8 (patch)
tree25759e0b096af49993553ae7b0f639f532d85b19
parentc62215e47d6d0ba8dd0a1dc4547b25667475245e (diff)
downloadFreeBSD-src-986f593e4573a0f751ae6fa39b49e0a0dcbefbf8.zip
FreeBSD-src-986f593e4573a0f751ae6fa39b49e0a0dcbefbf8.tar.gz
MFC r304543:
Unbreak sctp_connectx(). MFC r304573: Remove duplicate code, which is not protected by the appropriate locks. MFC r304579: Improve the locking when sending user messages. First, keep a ref count on the stcb after looking it up, as done in the other lookup cases. Second, before looking again at sp, ensure that it is not freed, because the assoc is about to be freed.
-rw-r--r--sys/netinet/sctp_output.c9
-rw-r--r--sys/netinet/sctp_usrreq.c5
-rw-r--r--sys/netinet/sctputil.c6
3 files changed, 11 insertions, 9 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 621b25e..88c0895 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -12639,7 +12639,10 @@ sctp_lower_sosend(struct socket *so,
}
SCTP_INP_RUNLOCK(inp);
} else if (sinfo_assoc_id) {
- stcb = sctp_findassociation_ep_asocid(inp, sinfo_assoc_id, 0);
+ stcb = sctp_findassociation_ep_asocid(inp, sinfo_assoc_id, 1);
+ if (stcb != NULL) {
+ hold_tcblock = 1;
+ }
} else if (addr) {
/*-
* Since we did not use findep we must
@@ -13404,6 +13407,10 @@ skip_preblock:
}
}
SCTP_TCB_SEND_LOCK(stcb);
+ if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ SCTP_TCB_SEND_UNLOCK(stcb);
+ goto out_unlocked;
+ }
if (sp) {
if (sp->msg_is_complete == 0) {
strm->last_msg_incomplete = 1;
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index fc2b9bb..77dd634 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -1506,11 +1506,6 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
}
SCTP_TCB_UNLOCK(stcb);
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
- stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
- /* Set the connected flag so we can queue data */
- soisconnecting(so);
- }
out_now:
if (creat_lock_on) {
SCTP_ASOC_CREATE_UNLOCK(inp);
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 6d263ed..4d5d497 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -6356,7 +6356,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
struct sctp_tcb *stcb = NULL;
unsigned int incr, at, i;
- at = incr = 0;
+ at = 0;
sa = addr;
*error = *num_v6 = *num_v4 = 0;
/* account and validate addresses */
@@ -6364,6 +6364,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
switch (sa->sa_family) {
#ifdef INET
case AF_INET:
+ incr = (unsigned int)sizeof(struct sockaddr_in);
if (sa->sa_len != incr) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
@@ -6371,7 +6372,6 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
return (NULL);
}
(*num_v4) += 1;
- incr = (unsigned int)sizeof(struct sockaddr_in);
break;
#endif
#ifdef INET6
@@ -6387,6 +6387,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
*bad_addr = 1;
return (NULL);
}
+ incr = (unsigned int)sizeof(struct sockaddr_in6);
if (sa->sa_len != incr) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
@@ -6394,7 +6395,6 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
return (NULL);
}
(*num_v6) += 1;
- incr = (unsigned int)sizeof(struct sockaddr_in6);
break;
}
#endif
OpenPOWER on IntegriCloud