From 0d89301c51585d3e0e49ac4e19d93b7a4675d168 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Fri, 18 Feb 2005 00:52:17 +0000 Subject: [PATCH] In solisten(), unconditionally set the SO_ACCEPTCONN option in so->so_options when solisten() will succeed, rather than setting it conditionally based on there not being queued sockets in the completed socket queue. Otherwise, if the protocol exposes new sockets via the completed queue before solisten() completes, the listen() system call will succeed, but the socket and protocol state will be out of sync. For TCP, this didn't happen in practice, as the TCP code will panic if a new connection comes in after the tcpcb has been transitioned to a listening state but the socket doesn't have SO_ACCEPTCONN set. This is historical behavior resulting from bitrot since 4.3BSD, in which that line of code was associated with the conditional NULL'ing of the connection queue pointers (one-time initialization to be performed during the transition to a listening socket), which are now initialized separately. Discussed with: fenner, gnn MFC after: 3 days --- sys/kern/uipc_socket.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index a6bf3a19794f..cb02026d44c0 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2004 The FreeBSD Foundation - * Copyright (c) 2004 Robert Watson + * Copyright (c) 2004-2005 Robert Watson * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * @@ -295,11 +295,9 @@ solisten(so, backlog, td) if (error) return (error); ACCEPT_LOCK(); - if (TAILQ_EMPTY(&so->so_comp)) { - SOCK_LOCK(so); - so->so_options |= SO_ACCEPTCONN; - SOCK_UNLOCK(so); - } + SOCK_LOCK(so); + so->so_options |= SO_ACCEPTCONN; + SOCK_UNLOCK(so); if (backlog < 0 || backlog > somaxconn) backlog = somaxconn; so->so_qlimit = backlog;