Author: tuexen
Date: Tue Aug  6 10:29:19 2019
New Revision: 350626
URL: https://svnweb.freebsd.org/changeset/base/350626

Log:
  Fix a locking issue in sctp_accept.
  
  PR:                   238520
  Reported by:          pho@
  MFC after:            1 week

Modified:
  head/sys/netinet/sctp_usrreq.c

Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c      Tue Aug  6 08:33:21 2019        
(r350625)
+++ head/sys/netinet/sctp_usrreq.c      Tue Aug  6 10:29:19 2019        
(r350626)
@@ -7226,28 +7226,56 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, 
EINVAL);
                return (ECONNRESET);
        }
-       SCTP_INP_RLOCK(inp);
+       SCTP_INP_WLOCK(inp);
        if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
-               SCTP_INP_RUNLOCK(inp);
+               SCTP_INP_WUNLOCK(inp);
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, 
EOPNOTSUPP);
                return (EOPNOTSUPP);
        }
        if (so->so_state & SS_ISDISCONNECTED) {
-               SCTP_INP_RUNLOCK(inp);
+               SCTP_INP_WUNLOCK(inp);
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, 
ECONNABORTED);
                return (ECONNABORTED);
        }
        stcb = LIST_FIRST(&inp->sctp_asoc_list);
        if (stcb == NULL) {
-               SCTP_INP_RUNLOCK(inp);
+               SCTP_INP_WUNLOCK(inp);
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, 
EINVAL);
                return (ECONNRESET);
        }
        SCTP_TCB_LOCK(stcb);
-       SCTP_INP_RUNLOCK(inp);
        store = stcb->asoc.primary_destination->ro._l_addr;
        SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
-       SCTP_TCB_UNLOCK(stcb);
+       /* Wake any delayed sleep action */
+       if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
+               inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
+               if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
+                       inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
+                       SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
+                       if (sowriteable(inp->sctp_socket)) {
+                               sowwakeup_locked(inp->sctp_socket);
+                       } else {
+                               SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
+                       }
+               }
+               if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
+                       inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
+                       SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
+                       if (soreadable(inp->sctp_socket)) {
+                               sctp_defered_wakeup_cnt++;
+                               sorwakeup_locked(inp->sctp_socket);
+                       } else {
+                               SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
+                       }
+               }
+       }
+       SCTP_INP_WUNLOCK(inp);
+       if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+               sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
+                   SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19);
+       } else {
+               SCTP_TCB_UNLOCK(stcb);
+       }
        switch (store.sa.sa_family) {
 #ifdef INET
        case AF_INET:
@@ -7288,40 +7316,6 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
        default:
                /* TSNH */
                break;
-       }
-       /* Wake any delayed sleep action */
-       if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
-               SCTP_INP_WLOCK(inp);
-               inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
-               if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
-                       inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
-                       SCTP_INP_WUNLOCK(inp);
-                       SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
-                       if (sowriteable(inp->sctp_socket)) {
-                               sowwakeup_locked(inp->sctp_socket);
-                       } else {
-                               SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
-                       }
-                       SCTP_INP_WLOCK(inp);
-               }
-               if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
-                       inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
-                       SCTP_INP_WUNLOCK(inp);
-                       SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
-                       if (soreadable(inp->sctp_socket)) {
-                               sctp_defered_wakeup_cnt++;
-                               sorwakeup_locked(inp->sctp_socket);
-                       } else {
-                               SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
-                       }
-                       SCTP_INP_WLOCK(inp);
-               }
-               SCTP_INP_WUNLOCK(inp);
-       }
-       if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
-               SCTP_TCB_LOCK(stcb);
-               sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
-                   SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19);
        }
        return (0);
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to