From owner-svn-src-all@FreeBSD.ORG Thu Oct 28 17:50:50 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 693561065694; Thu, 28 Oct 2010 17:50:50 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 5650A8FC20; Thu, 28 Oct 2010 17:50:50 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o9SHooN9020143; Thu, 28 Oct 2010 17:50:50 GMT (envelope-from tuexen@svn.freebsd.org) Received: (from tuexen@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o9SHoor1020139; Thu, 28 Oct 2010 17:50:50 GMT (envelope-from tuexen@svn.freebsd.org) Message-Id: <201010281750.o9SHoor1020139@svn.freebsd.org> From: Michael Tuexen Date: Thu, 28 Oct 2010 17:50:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214467 - stable/8/sys/netinet X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Oct 2010 17:50:50 -0000 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;