[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-bugs
Subject:    kernel/1840: broken behaviour of accept() on a disconnected Unix-domain socket
From:       rguyom () pobox ! com
Date:       2001-05-24 13:56:59
[Download RAW message or body]


>Number:         1840
>Category:       kernel
>Synopsis:       broken behaviour of accept() on a disconnected Unix-domain socket
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu May 24 08:00:02 MDT 2001
>Last-Modified:
>Originator:     Rémi Guyomarch
>Organization:
net
>Release:        2.9
>Environment:
	
	System      : OpenBSD 2.9
	Architecture: OpenBSD.i386
	Machine     : i386
	Port        : postfix-20010228.pl02-pcre
>Description:
The behaviour of accept() on a disconnected socket has changed since
2.8. Unfortunately, this change breaks Unix-domain sockets in a subtle
way, and postfix have problems with that :

postfix/flush[28969]: fatal: accept connection: Software caused connection abort
postfix/master[24048]: warning: process /usr/local/libexec/postfix/flush pid 28969 exit status 1
postfix/master[24048]: warning: /usr/local/libexec/postfix/flush: bad command startup -- throttling

Note that this bug may or may not bite you, depending on the load
and/or speed of your machine.

A few months ago a fix was commited in NetBSD :
http://mail-index.netbsd.org/source-changes/2001/03/21/0061.html
FreeBSD people commited a similiar fix :
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=265947+0+archive/2001/freebsd-net/20010311.freebsd-net

>How-To-Repeat:
Install the postfix port on 2.9 and wait for 'flush' to log the error
mentionned above. Or write a few lines of code so that a client does
connect() write() and close() on a Unix-domain socket before the server
accept() the connection. The accept() call will fail with ECONNABORTED.

>Fix:

This is just a quick hack. It doesn't deal with protocols other than INET.
A fix a la NetBSD would probably be better (adding a protosw flag).

Index: sys/kern/uipc_socket.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.33
diff -u -r1.33 uipc_socket.c
--- sys/kern/uipc_socket.c	2001/03/06 19:42:43	1.33
+++ sys/kern/uipc_socket.c	2001/05/23 06:37:42
@@ -266,11 +266,7 @@
 	if ((so->so_state & SS_NOFDREF) == 0)
 		panic("soaccept: !NOFDREF");
 	so->so_state &= ~SS_NOFDREF;
-	if ((so->so_state & SS_ISDISCONNECTED) == 0)
-		error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, NULL,
-		    nam, NULL);
-	else
-		error = ECONNABORTED;
+	error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, NULL, nam, NULL);
 	splx(s);
 	return (error);
 }
Index: sys/netinet/tcp_usrreq.c
===================================================================
RCS file: /usr/cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.50
diff -u -r1.50 tcp_usrreq.c
--- sys/netinet/tcp_usrreq.c	2000/12/13 09:47:08	1.50
+++ sys/netinet/tcp_usrreq.c	2001/05/23 06:36:34
@@ -351,6 +351,10 @@
 	 * of the peer, storing through addr.
 	 */
 	case PRU_ACCEPT:
+		if (so->so_state & SS_ISDISCONNECTED) {
+			error = ECONNABORTED;
+			break;
+		}
 #ifdef INET6
 		if (inp->inp_flags & INP_IPV6)
 			in6_setpeeraddr(inp, nam);

>Audit-Trail:
>Unformatted:

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic