diff options
author | rrs <rrs@FreeBSD.org> | 2010-06-06 19:24:32 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2010-06-06 19:24:32 +0000 |
commit | 6bf375889db714097da8272c8ad55ea17dc466ae (patch) | |
tree | 58e7f19bab4f9e4af9f486fa1a747f48b15f5ffa | |
parent | 7efcd15461d6e9902d80b62ffc8b447ddd83ea08 (diff) | |
download | FreeBSD-src-6bf375889db714097da8272c8ad55ea17dc466ae.zip FreeBSD-src-6bf375889db714097da8272c8ad55ea17dc466ae.tar.gz |
Ok, yet another bug in killing off all the hundreds
of apitesters.. Basically we end up with attempting
to destroy a lock thats contended on. A cookie echo
arrives at the same time that the close is happening.
The close gets the lock but the cookie echo has already
passed the check for the gone flag and is then locked
waiting on the create lock.. when we go to destroy it
bam. For now we do the timer destroy for all calls
to close.. We can probably optimize this later so that
we check whats being contended on and if there is contention
then do the timer thing. but this is probably safest since
the inp has been removed from all lists and references and
only the timer can find it.. once the locks are released all
other places will instantly see the GONE flag and bail (thats
what the change in sctp_input is one place that was lacking
the bail code).
MFC after: 1 week
-rw-r--r-- | sys/netinet/sctp_constants.h | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_input.c | 6 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 4 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 2 |
4 files changed, 11 insertions, 3 deletions
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h index 271e197..abf5826 100644 --- a/sys/netinet/sctp_constants.h +++ b/sys/netinet/sctp_constants.h @@ -894,7 +894,7 @@ __FBSDID("$FreeBSD$"); /* third argument */ #define SCTP_CALLED_DIRECTLY_NOCMPSET 0 #define SCTP_CALLED_AFTER_CMPSET_OFCLOSE 1 - +#define SCTP_CALLED_FROM_INPKILL_TIMER 2 /* second argument */ #define SCTP_FREE_SHOULD_USE_ABORT 1 #define SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE 0 diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 95114cc..8b2a9d5 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -4862,6 +4862,7 @@ process_control_chunks: } else { if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { /* We are not interested anymore */ + abend: if (stcb) { SCTP_TCB_UNLOCK(stcb); } @@ -4912,6 +4913,11 @@ process_control_chunks: if (linp) { SCTP_ASOC_CREATE_LOCK(linp); + if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { + SCTP_ASOC_CREATE_UNLOCK(linp); + goto abend; + } } if (netp) { ret_buf = diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 0ef5383..f9e029a 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -3423,7 +3423,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) #endif return; } - if ((inp->refcount) || (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP)) { + if ((inp->refcount) || + (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP) || + (from != SCTP_CALLED_FROM_INPKILL_TIMER)) { (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); sctp_timer_start(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL); SCTP_INP_WUNLOCK(inp); diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index a6fb7b3..dea9036 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1898,7 +1898,7 @@ sctp_timeout_handler(void *t) SCTP_INP_DECR_REF(inp); sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_3); sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, - SCTP_CALLED_DIRECTLY_NOCMPSET); + SCTP_CALLED_FROM_INPKILL_TIMER); inp = NULL; goto out_no_decr; default: |