diff options
author | rrs <rrs@FreeBSD.org> | 2011-02-13 14:48:11 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2011-02-13 14:48:11 +0000 |
commit | abb9537f13f6654ace6780f8eb39100c4d4edd5b (patch) | |
tree | e3594b8cc57ed50ac8da620d0307c2c5c8d2aeef | |
parent | 333b3f42778aa1fe4ba3cbb94f4f84383fc7a34b (diff) | |
download | FreeBSD-src-abb9537f13f6654ace6780f8eb39100c4d4edd5b.zip FreeBSD-src-abb9537f13f6654ace6780f8eb39100c4d4edd5b.tar.gz |
Fix a bug reported by Jonathan Leighton in his web-sctp testing
at the Univ-of-Del. Basically when a 1-to-1 socket did a
socket/bind/send(data)/close. If the timing was right
we would dereference a socket that is NULL.
MFC after: 1 month
-rw-r--r-- | sys/netinet/sctp_input.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 016218b..39c9aa7 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -2865,24 +2865,31 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp, SCTP_SOCKET_LOCK(so, 1); SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); - if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { - SCTP_SOCKET_UNLOCK(so, 1); - return; - } #endif - soisconnected(stcb->sctp_socket); + if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) { + soisconnected(stcb->sctp_socket); + } #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif } - sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, - stcb, net); /* * since we did not send a HB make sure we don't double * things */ net->hb_responded = 1; + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { + /* + * We don't need to do the asconf thing, nor hb or + * autoclose if the socket is closed. + */ + goto closed_socket; + } + sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, + stcb, net); + + if (stcb->asoc.sctp_autoclose_ticks && sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) { sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, @@ -2906,6 +2913,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp, #endif } } +closed_socket: /* Toss the cookie if I can */ sctp_toss_old_cookies(stcb, asoc); if (!TAILQ_EMPTY(&asoc->sent_queue)) { |