Author: tuexen
Date: Thu Jun 17 19:17:50 2010
New Revision: 209264
URL: http://svn.freebsd.org/changeset/base/209264

Log:
  MFC 209178
   * Fix a bug where the length of the ASCONF-ACK was calculated wrong due
     to using an uninitialized variable.
   * Fix a bug where a NULL pointer was dereferenced when interfaces
     come and go at a high rate.
   * Fix a bug where inps where not deregistered from iterators.
   * Fix a race condition in freeing an association.
   * Fix a refcount problem related to the iterator.
   Each of the above bug results in a panic. It shows up when
   interfaces come and go at a high rate.

Modified:
  stable/8/sys/netinet/sctp_asconf.c
  stable/8/sys/netinet/sctp_pcb.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/geom/sched/   (props changed)

Modified: stable/8/sys/netinet/sctp_asconf.c
==============================================================================
--- stable/8/sys/netinet/sctp_asconf.c  Thu Jun 17 19:17:31 2010        
(r209263)
+++ stable/8/sys/netinet/sctp_asconf.c  Thu Jun 17 19:17:50 2010        
(r209264)
@@ -826,6 +826,7 @@ send_reply:
        ack->serial_number = serial_num;
        ack->last_sent_to = NULL;
        ack->data = m_ack;
+       ack->len = 0;
        n = m_ack;
        while (n) {
                ack->len += SCTP_BUF_LEN(n);
@@ -1025,7 +1026,8 @@ sctp_asconf_nets_cleanup(struct sctp_tcb
                 * address.
                 */
                if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) &&
-                   SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index) {
+                   ((ifn == NULL) ||
+                   (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != 
ifn->ifn_index))) {
                        /* clear any cached route */
                        RTFREE(net->ro.ro_rt);
                        net->ro.ro_rt = NULL;

Modified: stable/8/sys/netinet/sctp_pcb.c
==============================================================================
--- stable/8/sys/netinet/sctp_pcb.c     Thu Jun 17 19:17:31 2010        
(r209263)
+++ stable/8/sys/netinet/sctp_pcb.c     Thu Jun 17 19:17:50 2010        
(r209264)
@@ -3074,6 +3074,9 @@ sctp_iterator_inp_being_freed(struct sct
                                SCTP_FREE(it, SCTP_M_ITER);
                        } else {
                                it->inp = LIST_NEXT(it->inp, sctp_list);
+                               if (it->inp) {
+                                       SCTP_INP_INCR_REF(it->inp);
+                               }
                        }
                        /*
                         * When its put in the refcnt is incremented so decr
@@ -3114,17 +3117,10 @@ sctp_inpcb_free(struct sctp_inpcb *inp, 
 #ifdef SCTP_LOG_CLOSING
        sctp_log_closing(inp, NULL, 0);
 #endif
-       if (from == SCTP_CALLED_AFTER_CMPSET_OFCLOSE) {
-               /*
-                * Once we are in we can remove the flag from = 1 is only
-                * passed from the actual closing routines that are called
-                * via the sockets layer.
-                */
-               SCTP_ITERATOR_LOCK();
-               /* mark any iterators on the list or being processed */
-               sctp_iterator_inp_being_freed(inp);
-               SCTP_ITERATOR_UNLOCK();
-       }
+       SCTP_ITERATOR_LOCK();
+       /* mark any iterators on the list or being processed */
+       sctp_iterator_inp_being_freed(inp);
+       SCTP_ITERATOR_UNLOCK();
        so = inp->sctp_socket;
        if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
                /* been here before.. eeks.. get out of here */
@@ -4637,7 +4633,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, 
                atomic_add_int(&stcb->asoc.refcnt, 1);
 
                SCTP_TCB_UNLOCK(stcb);
-
                SCTP_INP_INFO_WLOCK();
                SCTP_INP_WLOCK(inp);
                SCTP_TCB_LOCK(stcb);
@@ -4680,6 +4675,16 @@ sctp_free_assoc(struct sctp_inpcb *inp, 
        if (from_inpcbfree == SCTP_NORMAL_PROC) {
                atomic_add_int(&stcb->asoc.refcnt, -1);
        }
+       if (stcb->asoc.refcnt) {
+               stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
+               sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
+               if (from_inpcbfree == SCTP_NORMAL_PROC) {
+                       SCTP_INP_INFO_WUNLOCK();
+                       SCTP_INP_WUNLOCK(inp);
+               }
+               SCTP_TCB_UNLOCK(stcb);
+               return (0);
+       }
        asoc->state = 0;
        if (inp->sctp_tcbhash) {
                LIST_REMOVE(stcb, sctp_tcbhash);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to