Date: Fri, 29 May 2015 13:18:11 +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-10@freebsd.org Subject: svn commit: r283732 - stable/10/sys/netinet Message-ID: <201505291318.t4TDIBH0054005@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tuexen Date: Fri May 29 13:18:10 2015 New Revision: 283732 URL: https://svnweb.freebsd.org/changeset/base/283732 Log: MFC r280459: Fix two bugs which resulted in a screwed up end point list: * Use a save way to walk throught a list while manipulting it. * Have to appropiate locks in place. Joint work with rrs@ Modified: stable/10/sys/netinet/sctp_pcb.c stable/10/sys/netinet/sctp_usrreq.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/netinet/sctp_pcb.c ============================================================================== --- stable/10/sys/netinet/sctp_pcb.c Fri May 29 13:13:12 2015 (r283731) +++ stable/10/sys/netinet/sctp_pcb.c Fri May 29 13:18:10 2015 (r283732) @@ -1867,7 +1867,7 @@ sctp_swap_inpcb_for_listen(struct sctp_i { /* For 1-2-1 with port reuse */ struct sctppcbhead *head; - struct sctp_inpcb *tinp; + struct sctp_inpcb *tinp, *ninp; if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE)) { /* only works with port reuse on */ @@ -1877,10 +1877,11 @@ sctp_swap_inpcb_for_listen(struct sctp_i return (0); } SCTP_INP_RUNLOCK(inp); + SCTP_INP_INFO_WLOCK(); head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(inp->sctp_lport, SCTP_BASE_INFO(hashmark))]; /* Kick out all non-listeners to the TCP hash */ - LIST_FOREACH(tinp, head, sctp_hash) { + LIST_FOREACH_SAFE(tinp, head, sctp_hash, ninp) { if (tinp->sctp_lport != inp->sctp_lport) { continue; } @@ -1908,6 +1909,7 @@ sctp_swap_inpcb_for_listen(struct sctp_i LIST_INSERT_HEAD(head, inp, sctp_hash); SCTP_INP_WUNLOCK(inp); SCTP_INP_RLOCK(inp); + SCTP_INP_INFO_WUNLOCK(); return (0); } Modified: stable/10/sys/netinet/sctp_usrreq.c ============================================================================== --- stable/10/sys/netinet/sctp_usrreq.c Fri May 29 13:13:12 2015 (r283731) +++ stable/10/sys/netinet/sctp_usrreq.c Fri May 29 13:18:10 2015 (r283732) @@ -6965,8 +6965,8 @@ sctp_listen(struct socket *so, int backl #endif SOCK_LOCK(so); error = solisten_proto_check(so); + SOCK_UNLOCK(so); if (error) { - SOCK_UNLOCK(so); SCTP_INP_RUNLOCK(inp); return (error); } @@ -6979,28 +6979,27 @@ sctp_listen(struct socket *so, int backl * move the guy that was listener to the TCP Pool. */ if (sctp_swap_inpcb_for_listen(inp)) { - goto in_use; + SCTP_INP_RUNLOCK(inp); + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE); + return (EADDRINUSE); } } if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) { /* We are already connected AND the TCP model */ -in_use: SCTP_INP_RUNLOCK(inp); - SOCK_UNLOCK(so); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE); return (EADDRINUSE); } SCTP_INP_RUNLOCK(inp); if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { /* We must do a bind. */ - SOCK_UNLOCK(so); if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) { /* bind error, probably perm */ return (error); } - SOCK_LOCK(so); } + SOCK_LOCK(so); /* It appears for 7.0 and on, we must always call this. */ solisten_proto(so, backlog); if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505291318.t4TDIBH0054005>