Fix a rece condition in the shutdown handling.
The race condition resulted in a panic. MFC after: 3 days
This commit is contained in:
parent
998ef62e74
commit
cd1386ab50
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=209289
@ -442,6 +442,7 @@ struct sctp_error_unrecognized_chunk {
|
||||
#define SCTP_PCB_FLAGS_BLOCKING_IO 0x08000000
|
||||
#define SCTP_PCB_FLAGS_SOCKET_GONE 0x10000000
|
||||
#define SCTP_PCB_FLAGS_SOCKET_ALLGONE 0x20000000
|
||||
#define SCTP_PCB_FLAGS_SOCKET_CANT_READ 0x40000000
|
||||
/* flags to copy to new PCB */
|
||||
#define SCTP_PCB_COPY_FLAGS (SCTP_PCB_FLAGS_BOUNDALL|\
|
||||
SCTP_PCB_FLAGS_WAKEINPUT|\
|
||||
|
@ -947,11 +947,30 @@ sctp_flush(struct socket *so, int how)
|
||||
* they will not be able to read the data, the socket will block
|
||||
* that from happening.
|
||||
*/
|
||||
struct sctp_inpcb *inp;
|
||||
|
||||
inp = (struct sctp_inpcb *)so->so_pcb;
|
||||
if (inp == NULL) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
SCTP_INP_RLOCK(inp);
|
||||
/* For the 1 to many model this does nothing */
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
return (0);
|
||||
}
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
|
||||
/*
|
||||
* First make sure the sb will be happy, we don't use these
|
||||
* except maybe the count
|
||||
*/
|
||||
SCTP_INP_WLOCK(inp);
|
||||
SCTP_INP_READ_LOCK(inp);
|
||||
inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
so->so_rcv.sb_cc = 0;
|
||||
so->so_rcv.sb_mbcnt = 0;
|
||||
so->so_rcv.sb_mb = NULL;
|
||||
|
@ -3185,6 +3185,9 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
|
||||
/* event not enabled */
|
||||
return;
|
||||
}
|
||||
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
|
||||
return;
|
||||
}
|
||||
m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_DONTWAIT, 1, MT_DATA);
|
||||
if (m_notify == NULL)
|
||||
/* no space left */
|
||||
@ -4365,6 +4368,17 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
}
|
||||
if (inp_read_lock_held == 0)
|
||||
SCTP_INP_READ_LOCK(inp);
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
|
||||
sctp_free_remote_addr(control->whoFrom);
|
||||
if (control->data) {
|
||||
sctp_m_freem(control->data);
|
||||
control->data = NULL;
|
||||
}
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
|
||||
if (inp_read_lock_held == 0)
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
return;
|
||||
}
|
||||
if (!(control->spec_flags & M_NOTIFICATION)) {
|
||||
atomic_add_int(&inp->total_recvs, 1);
|
||||
if (!control->do_not_ref_stcb) {
|
||||
@ -4405,6 +4419,8 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
control->tail_mbuf = prev;
|
||||
} else {
|
||||
/* Everything got collapsed out?? */
|
||||
sctp_free_remote_addr(control->whoFrom);
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
|
||||
if (inp_read_lock_held == 0)
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
return;
|
||||
@ -4477,6 +4493,10 @@ sctp_append_to_readq(struct sctp_inpcb *inp,
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) {
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
return 0;
|
||||
}
|
||||
if (control->end_added) {
|
||||
/* huh this one is complete? */
|
||||
goto get_out;
|
||||
|
Loading…
Reference in New Issue
Block a user