diff options
-rw-r--r-- | sys/netinet/sctp_pcb.c | 16 | ||||
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 31 |
2 files changed, 17 insertions, 30 deletions
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 3e517889d171..85ea5a3f8a53 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -3321,19 +3321,15 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) /* 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 */ - SCTP_PRINTF("This conflict in free SHOULD not be happening! from %d, imm %d\n", from, immediate); -#ifdef SCTP_LOG_CLOSING - sctp_log_closing(inp, NULL, 1); -#endif - return; - } + SCTP_ASOC_CREATE_LOCK(inp); SCTP_INP_INFO_WLOCK(); - SCTP_INP_WLOCK(inp); + so = inp->sctp_socket; + KASSERT((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) != 0, + ("%s: inp %p still has socket", __func__, inp)); + KASSERT((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0, + ("%s: double free of inp %p", __func__, inp)); if (from == SCTP_CALLED_AFTER_CMPSET_OFCLOSE) { inp->sctp_flags &= ~SCTP_PCB_FLAGS_CLOSE_IP; /* socket is gone, so no more wakeups allowed */ diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 822a8ffb534f..62d6996ab60d 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -416,24 +416,23 @@ sctp_abort(struct socket *so) { struct epoch_tracker et; struct sctp_inpcb *inp; - uint32_t flags; inp = (struct sctp_inpcb *)so->so_pcb; if (inp == NULL) { return; } + SCTP_INP_WLOCK(inp); NET_EPOCH_ENTER(et); -sctp_must_try_again: - flags = inp->sctp_flags; #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 17); #endif - if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) { + if (((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)) { + inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP; #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 16); #endif + SCTP_INP_WUNLOCK(inp); sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, SCTP_CALLED_AFTER_CMPSET_OFCLOSE); SOCK_LOCK(so); @@ -448,13 +447,9 @@ sctp_must_try_again: so->so_pcb = NULL; SOCK_UNLOCK(so); } else { - flags = inp->sctp_flags; - if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { - goto sctp_must_try_again; - } + SCTP_INP_WUNLOCK(inp); } NET_EPOCH_EXIT(et); - return; } static int @@ -516,7 +511,6 @@ sctp_close(struct socket *so) { struct epoch_tracker et; struct sctp_inpcb *inp; - uint32_t flags; inp = (struct sctp_inpcb *)so->so_pcb; if (inp == NULL) @@ -525,25 +519,26 @@ sctp_close(struct socket *so) /* * Inform all the lower layer assoc that we are done. */ + SCTP_INP_WLOCK(inp); NET_EPOCH_ENTER(et); -sctp_must_try_again: - flags = inp->sctp_flags; #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 17); #endif - if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { + inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP; if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) || (so->so_rcv.sb_cc > 0)) { #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 13); #endif + SCTP_INP_WUNLOCK(inp); sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, SCTP_CALLED_AFTER_CMPSET_OFCLOSE); } else { #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 14); #endif + SCTP_INP_WUNLOCK(inp); sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE, SCTP_CALLED_AFTER_CMPSET_OFCLOSE); } @@ -563,13 +558,9 @@ sctp_must_try_again: so->so_pcb = NULL; SOCK_UNLOCK(so); } else { - flags = inp->sctp_flags; - if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { - goto sctp_must_try_again; - } + SCTP_INP_WUNLOCK(inp); } NET_EPOCH_EXIT(et); - return; } int |