Page MenuHomeFreeBSD

D38507.diff
No OneTemporary

D38507.diff

diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1345,10 +1345,14 @@
int error;
CURVNET_SET(so->so_vnet);
+
/*
* If protocol is connection-based, can only connect once.
* Otherwise, if connected, try to disconnect first. This allows
* user to disconnect by connecting to, e.g., a null address.
+ *
+ * Note, this check is racy and may need to be re-evaluated at the
+ * protocol layer.
*/
if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1401,6 +1401,10 @@
NET_EPOCH_ASSERT();
INP_WLOCK_ASSERT(inp);
+ if (__predict_false((so->so_state &
+ (SS_ISCONNECTING | SS_ISCONNECTED)) != 0))
+ return (EISCONN);
+
INP_HASH_WLOCK(&V_tcbinfo);
error = in_pcbconnect(inp, sin, td->td_ucred, true);
INP_HASH_WUNLOCK(&V_tcbinfo);
@@ -1433,11 +1437,16 @@
tcp6_connect(struct tcpcb *tp, struct sockaddr_in6 *sin6, struct thread *td)
{
struct inpcb *inp = tptoinpcb(tp);
+ struct socket *so = tptosocket(tp);
int error;
NET_EPOCH_ASSERT();
INP_WLOCK_ASSERT(inp);
+ if (__predict_false((so->so_state &
+ (SS_ISCONNECTING | SS_ISCONNECTED)) != 0))
+ return (EISCONN);
+
INP_HASH_WLOCK(&V_tcbinfo);
error = in6_pcbconnect(inp, sin6, td->td_ucred, true);
INP_HASH_WUNLOCK(&V_tcbinfo);
@@ -1449,7 +1458,7 @@
(TCP_MAXWIN << tp->request_r_scale) < sb_max)
tp->request_r_scale++;
- soisconnecting(inp->inp_socket);
+ soisconnecting(so);
TCPSTAT_INC(tcps_connattempt);
tcp_state_change(tp, TCPS_SYN_SENT);
tp->iss = tcp_new_isn(&inp->inp_inc);

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 19, 8:39 PM (22 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14723234
Default Alt Text
D38507.diff (1 KB)

Event Timeline