Skip site navigation (1)Skip section navigation (2)
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>