svn commit: r302148 - head/sys/netinet
Michael Tuexen
tuexen at FreeBSD.org
Thu Jun 23 19:27:31 UTC 2016
Author: tuexen
Date: Thu Jun 23 19:27:29 2016
New Revision: 302148
URL: https://svnweb.freebsd.org/changeset/base/302148
Log:
Fix a bug in the handling of non-blocking SCTP 1-to-1 sockets. When using
this code in the userland stack, it could result in a loop. This happened on iOS.
However, I was not able to reproduce this when using the code in the kernel.
Thanks to Eugen-Andrei Gavriloaie for reporting the issue and proving detailed
information to find the root of the problem.
Approved by: re (gjb)
MFC after: 1 week
Modified:
head/sys/netinet/sctputil.c
Modified: head/sys/netinet/sctputil.c
==============================================================================
--- head/sys/netinet/sctputil.c Thu Jun 23 19:24:38 2016 (r302147)
+++ head/sys/netinet/sctputil.c Thu Jun 23 19:27:29 2016 (r302148)
@@ -5274,8 +5274,14 @@ restart_nosblocks:
}
}
}
- if ((so->so_rcv.sb_cc <= held_length) && block_allowed) {
- /* we need to wait for data */
+ if (so->so_rcv.sb_cc <= held_length) {
+ if (so->so_error) {
+ error = so->so_error;
+ if ((in_flags & MSG_PEEK) == 0) {
+ so->so_error = 0;
+ }
+ goto out;
+ }
if ((so->so_rcv.sb_cc == 0) &&
((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
@@ -5306,51 +5312,18 @@ restart_nosblocks:
goto out;
}
}
- error = sbwait(&so->so_rcv);
- if (error) {
- goto out;
- }
- held_length = 0;
- goto restart_nosblocks;
- } else if (so->so_rcv.sb_cc == 0) {
- if (so->so_error) {
- error = so->so_error;
- if ((in_flags & MSG_PEEK) == 0)
- so->so_error = 0;
- } else {
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
- (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
- /*
- * For active open side clear flags
- * for re-use passive open is
- * blocked by connect.
- */
- if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) {
- /*
- * You were aborted, passive
- * side always hits here
- */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
- error = ECONNRESET;
- }
- so->so_state &= ~(SS_ISCONNECTING |
- SS_ISDISCONNECTING |
- SS_ISCONFIRMING |
- SS_ISCONNECTED);
- if (error == 0) {
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
- error = ENOTCONN;
- }
- }
- goto out;
- }
+ if (block_allowed) {
+ error = sbwait(&so->so_rcv);
+ if (error) {
+ goto out;
}
+ held_length = 0;
+ goto restart_nosblocks;
+ } else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EWOULDBLOCK);
error = EWOULDBLOCK;
+ goto out;
}
- goto out;
}
if (hold_sblock == 1) {
SOCKBUF_UNLOCK(&so->so_rcv);
More information about the svn-src-head
mailing list