network - Protect so_rcv sockbuf in udp and unix domain protocols
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 15 Sep 2010 03:47:10 +0000 (20:47 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 15 Sep 2010 03:47:10 +0000 (20:47 -0700)
* The so_rcv sockbuf was not being locked against the user side
  when the unix and udp protocols appended to it, resulting in
  assertions.

sys/kern/uipc_usrreq.c
sys/netinet/udp_usrreq.c

index b374076..f19b716 100644 (file)
@@ -411,6 +411,8 @@ uipc_send(netmsg_t msg)
                        from = (struct sockaddr *)unp->unp_addr;
                else
                        from = &sun_noname;
+
+               lwkt_gettoken(&so2->so_rcv.ssb_token);
                if (ssb_appendaddr(&so2->so_rcv, from, m, control)) {
                        sorwakeup(so2);
                        m = NULL;
@@ -420,6 +422,7 @@ uipc_send(netmsg_t msg)
                }
                if (msg->send.nm_addr)
                        unp_disconnect(unp);
+               lwkt_reltoken(&so2->so_rcv.ssb_token);
                break;
        }
 
@@ -455,6 +458,7 @@ uipc_send(netmsg_t msg)
                 * send buffer hiwater marks to maintain backpressure.
                 * Wake up readers.
                 */
+               lwkt_gettoken(&so2->so_rcv.ssb_token);
                if (control) {
                        if (ssb_appendcontrol(&so2->so_rcv, m, control)) {
                                control = NULL;
@@ -478,6 +482,7 @@ uipc_send(netmsg_t msg)
                ) {
                        atomic_set_int(&so->so_snd.ssb_flags, SSB_STOP);
                }
+               lwkt_reltoken(&so2->so_rcv.ssb_token);
                sorwakeup(so2);
                break;
 
@@ -1610,9 +1615,11 @@ unp_gc_checkmarks(struct file *fp, void *data)
         * as accessible too.
         */
        info->locked_fp = fp;
+       lwkt_gettoken(&so->so_rcv.ssb_token);
 /*     spin_lock_wr(&so->so_rcv.sb_spin); */
        unp_scan(so->so_rcv.ssb_mb, unp_mark, info);
 /*     spin_unlock_wr(&so->so_rcv.sb_spin);*/
+       lwkt_reltoken(&so->so_rcv.ssb_token);
        return (0);
 }
 
@@ -1682,6 +1689,7 @@ unp_revoke_gc_check(struct file *fps, void *vinfo)
         * Scan the mbufs for control messages and replace any revoked
         * descriptors we find.
         */
+       lwkt_gettoken(&so->so_rcv.ssb_token);
        m0 = so->so_rcv.ssb_mb;
        while (m0) {
                for (m = m0; m; m = m->m_next) {
@@ -1716,6 +1724,7 @@ unp_revoke_gc_check(struct file *fps, void *vinfo)
                if (info->fcount == REVOKE_GC_MAXFILES)
                        break;
        }
+       lwkt_reltoken(&so->so_rcv.ssb_token);
 
        /*
         * Stop the scan if we filled up our array.
index 025f6bd..77bf95a 100644 (file)
@@ -509,10 +509,14 @@ udp_input(struct mbuf **mp, int *offp, int proto)
        } else
 #endif
                append_sa = (struct sockaddr *)&udp_in;
+
+       lwkt_gettoken(&inp->inp_socket->so_rcv.ssb_token);
        if (ssb_appendaddr(&inp->inp_socket->so_rcv, append_sa, m, opts) == 0) {
                udpstat.udps_fullsock++;
+               lwkt_reltoken(&inp->inp_socket->so_rcv.ssb_token);
                goto bad;
        }
+       lwkt_reltoken(&inp->inp_socket->so_rcv.ssb_token);
        sorwakeup(inp->inp_socket);
        return(IPPROTO_DONE);
 bad:
@@ -578,13 +582,16 @@ udp_append(struct inpcb *last, struct ip *ip, struct mbuf *n, int off)
 #endif
                append_sa = (struct sockaddr *)&udp_in;
        m_adj(n, off);
+       lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
        if (ssb_appendaddr(&last->inp_socket->so_rcv, append_sa, n, opts) == 0) {
                m_freem(n);
                if (opts)
                        m_freem(opts);
                udpstat.udps_fullsock++;
-       } else
+       } else {
                sorwakeup(last->inp_socket);
+       }
+       lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
 }
 
 /*