]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/uipc_socket2.c
xnu-792.6.61.tar.gz
[apple/xnu.git] / bsd / kern / uipc_socket2.c
index 2fb59d20f6333a4d999895138e36770d6b3df4ad..30750607ff19d67fc046f0e5df052b17bde6bf15 100644 (file)
@@ -142,18 +142,22 @@ soisconnected(so)
        sflt_notify(so, sock_evt_connected, NULL);
        
        if (head && (so->so_state & SS_INCOMP)) {
-               if (head->so_proto->pr_getlock != NULL) 
+               so->so_state &= ~SS_INCOMP;
+               so->so_state |= SS_COMP;
+               if (head->so_proto->pr_getlock != NULL) {
+                       socket_unlock(so, 0);
                        socket_lock(head, 1);
+               }
                postevent(head, 0, EV_RCONN);
                TAILQ_REMOVE(&head->so_incomp, so, so_list);
                head->so_incqlen--;
-               so->so_state &= ~SS_INCOMP;
                TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
-               so->so_state |= SS_COMP;
                sorwakeup(head);
                wakeup_one((caddr_t)&head->so_timeo);
-               if (head->so_proto->pr_getlock != NULL) 
+               if (head->so_proto->pr_getlock != NULL) {
                        socket_unlock(head, 1);
+                       socket_lock(so, 0);
+               }
        } else {
                postevent(so, 0, EV_WCONN);
                wakeup((caddr_t)&so->so_timeo);
@@ -291,16 +295,19 @@ sonewconn_internal(head, connstatus)
        }
 
        /*
-        * Must be done with head unlocked to avoid deadlock with pcb list
+        * Must be done with head unlocked to avoid deadlock for protocol with per socket mutexes.
         */
-       socket_unlock(head, 0);
+       if (head->so_proto->pr_unlock)
+               socket_unlock(head, 0);
        if (((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL) != 0) || error) {
                sflt_termsock(so);
                sodealloc(so);
-               socket_lock(head, 0);
+               if (head->so_proto->pr_unlock)
+                       socket_lock(head, 0);
                return ((struct socket *)0);
        }
-       socket_lock(head, 0);
+       if (head->so_proto->pr_unlock)
+               socket_lock(head, 0);
 #ifdef __APPLE__
        so->so_proto->pr_domain->dom_refs++;
 #endif
@@ -641,12 +648,15 @@ sbappend(sb, m)
        register struct mbuf *n, *sb_first;
        int result = 0;
        int error = 0;
+       int     filtered = 0;
 
 
        KERNEL_DEBUG((DBG_FNC_SBAPPEND | DBG_FUNC_START), sb, m->m_len, 0, 0, 0);
 
        if (m == 0)
                return 0;
+       
+again:
        sb_first = n = sb->sb_mb;
        if (n) {
                while (n->m_nextpkt)
@@ -660,21 +670,22 @@ sbappend(sb, m)
                } while (n->m_next && (n = n->m_next));
        }
        
-       if ((sb->sb_flags & SB_RECV) != 0) {
-               error = sflt_data_in(sb->sb_so, NULL, &m, NULL, 0);
+       if (!filtered && (sb->sb_flags & SB_RECV) != 0) {
+               error = sflt_data_in(sb->sb_so, NULL, &m, NULL, 0, &filtered);
                if (error) {
                        /* no data was appended, caller should not call sowakeup */
                        return 0;
                }
-       }
-       
-       /* 3962537 - sflt_data_in may drop the lock, need to validate state again */
-       if (sb_first != sb->sb_mb) {
-               n = sb->sb_mb;
-               if (n) {
-                       while (n->m_nextpkt)
-                               n = n->m_nextpkt;
-               }
+               
+               /*
+                 If we any filters, the socket lock was dropped. n and sb_first
+                 cached data from the socket buffer. This cache is not valid
+                 since we dropped the lock. We must start over. Since filtered
+                 is set we won't run through the filters a second time. We just
+                 set n and sb_start again.
+               */
+               if (filtered)
+                       goto again;
        }
 
        result = sbcompress(sb, m, n);
@@ -736,7 +747,7 @@ sbappendrecord(sb, m0)
                return 0;
     
        if ((sb->sb_flags & SB_RECV) != 0) {
-               int error = sflt_data_in(sb->sb_so, NULL, &m0, NULL, sock_data_filt_flag_record);
+               int error = sflt_data_in(sb->sb_so, NULL, &m0, NULL, sock_data_filt_flag_record, NULL);
                if (error != 0) {
                        if (error != EJUSTRETURN)
                                m_freem(m0);
@@ -784,7 +795,7 @@ sbinsertoob(sb, m0)
        
        if ((sb->sb_flags & SB_RECV) != 0) {
                int error = sflt_data_in(sb->sb_so, NULL, &m0, NULL,
-                                                                sock_data_filt_flag_oob);
+                                                                sock_data_filt_flag_oob, NULL);
                
                if (error) {
                        if (error != EJUSTRETURN) {
@@ -895,7 +906,7 @@ sbappendaddr(
        /* Call socket data in filters */
        if ((sb->sb_flags & SB_RECV) != 0) {
                int error;
-               error = sflt_data_in(sb->sb_so, asa, &m0, &control, 0);
+               error = sflt_data_in(sb->sb_so, asa, &m0, &control, 0, NULL);
                if (error) {
                        if (error != EJUSTRETURN) {
                                if (m0) m_freem(m0);
@@ -964,7 +975,7 @@ sbappendcontrol(
        
        if (sb->sb_flags & SB_RECV) {
                int error;
-               error = sflt_data_in(sb->sb_so, NULL, &m0, &control, 0);
+               error = sflt_data_in(sb->sb_so, NULL, &m0, &control, 0, NULL);
                if (error) {
                        if (error != EJUSTRETURN) {
                                if (m0) m_freem(m0);