On Wed, 29 Aug 2007, Andrew Lunn wrote:

> >             } else if (so->so_state & SS_COMP) {
> > +                    if((so->so_error == ECONNRESET) ||
> > +                            (so->so_error == ECONNREFUSED)){ // forced 
> > drop if flagged
> > +                             TAILQ_REMOVE(&head->so_comp, so, so_list);
> > +                             head->so_qlen--;
> > +                    } else {
> >                     /*
> >                      * We must not decommission a socket that's
> >                      * on the accept(2) queue.  If we do, then
> > @@ -249,11 +258,13 @@
> >                      * that the listening socket was ready.
> >                      */
> 
> The full comment is:
> 
>                         /*
>                          * We must not decommission a socket that's
>                          * on the accept(2) queue.  If we do, then
>                          * accept(2) may hang after select(2) indicated
>                          * that the listening socket was ready.
>                          */
> 
> Are you sure the socket is not on the accept queue? I wounder if the
> accept code should free the socket?
> 
>        Andrew

Good question. I'm way beyond my 'threshold of incompetence' here and may 
have opened another vulnerability with my patch.

I looked where those error flags are set in 'tcp_input()' and found this,
suggesting that I could rely on testing ECONNREFUSED and ECONNRESET to
kill off the connection:

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        /*
         * States other than LISTEN or SYN_SENT.
         * First check the RST flag and sequence number since reset 
segments
         * are exempt from the timestamp and connection count tests.

 ...

         * If the RST bit is set, check the sequence number to see
         * if this is a valid reset segment.

 ...

         * If the reset segment passes the sequence number test examine
         * the state:
         *    SYN_RECEIVED STATE:
         *      If passive open, return to LISTEN state.
         *      If active open, inform user that connection was refused.
         *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
         *      Inform user that connection was reset, and close tcb.
         *    CLOSING, LAST_ACK STATES:
         *      Close the tcb.
         *    TIME_WAIT STATE:
         *      Drop the segment - see Stevens, vol. 2, p. 964 and
         *      RFC 1337.
         */
        if (thflags & TH_RST) {
                if (SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
                    SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) {
                        switch (tp->t_state) {

                        case TCPS_SYN_RECEIVED:
                                so->so_error = ECONNREFUSED;
                                goto close;

                        case TCPS_ESTABLISHED:
                        case TCPS_FIN_WAIT_1:
                        case TCPS_FIN_WAIT_2:
                        case TCPS_CLOSE_WAIT:
                                so->so_error = ECONNRESET;
                        close:
                                tp->t_state = TCPS_CLOSED;
                                tcpstat.tcps_drops++;
                                tp = tcp_close(tp);
                                break;

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Reply via email to