Date: Thu, 28 Oct 2010 17:50:50 +0000 (UTC) From: Michael Tuexen <tuexen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r214467 - stable/8/sys/netinet Message-ID: <201010281750.o9SHoor1020139@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tuexen Date: Thu Oct 28 17:50:50 2010 New Revision: 214467 URL: http://svn.freebsd.org/changeset/base/214467 Log: MFC 209289: Fix a rece condition in the shutdown handling. The race condition resulted in a panic. Modified: stable/8/sys/netinet/sctp.h stable/8/sys/netinet/sctp_usrreq.c stable/8/sys/netinet/sctputil.c Modified: stable/8/sys/netinet/sctp.h ============================================================================== --- stable/8/sys/netinet/sctp.h Thu Oct 28 17:17:45 2010 (r214466) +++ stable/8/sys/netinet/sctp.h Thu Oct 28 17:50:50 2010 (r214467) @@ -440,6 +440,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|\ Modified: stable/8/sys/netinet/sctp_usrreq.c ============================================================================== --- stable/8/sys/netinet/sctp_usrreq.c Thu Oct 28 17:17:45 2010 (r214466) +++ stable/8/sys/netinet/sctp_usrreq.c Thu Oct 28 17:50:50 2010 (r214467) @@ -948,11 +948,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; Modified: stable/8/sys/netinet/sctputil.c ============================================================================== --- stable/8/sys/netinet/sctputil.c Thu Oct 28 17:17:45 2010 (r214466) +++ stable/8/sys/netinet/sctputil.c Thu Oct 28 17:50:50 2010 (r214467) @@ -3183,6 +3183,9 @@ sctp_notify_partial_delivery_indication( /* 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 */ @@ -4369,6 +4372,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) { @@ -4409,6 +4423,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; @@ -4481,6 +4497,10 @@ get_out: } 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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010281750.o9SHoor1020139>