diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1999-02-19 15:06:53 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1999-02-19 15:06:53 +0000 |
commit | 880be7d33edac12068a585d74b52ab58bc84b8ed (patch) | |
tree | 7e8517a5960725eec2306761c1d4b099fd93238a | |
parent | 5db2e7cc355c30bdd86bb99682166df39a1572fd (diff) |
fixed patch for accept/select race; mycroft@netbsd.org
-rw-r--r-- | sys/kern/uipc_socket.c | 31 | ||||
-rw-r--r-- | sys/kern/uipc_socket2.c | 4 | ||||
-rw-r--r-- | sys/sys/socketvar.h | 3 |
3 files changed, 25 insertions, 13 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 82b63206f16..b5534ca0835 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.25 1999/02/18 22:56:58 deraadt Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.26 1999/02/19 15:06:52 millert Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -156,9 +156,13 @@ sofree(so) if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) return; if (so->so_head) { - if (!soqremque(so, 0) && !soqremque(so, 1)) - panic("sofree dq"); - so->so_head = 0; + /* + * We must not decommission a socket that's on the accept(2) + * queue. If we do, then accept(2) may hang after select(2) + * indicated that the listening socket was ready. + */ + if (!soqremque(so, 0)) + return; } sbrelease(&so->so_snd); sorflush(so); @@ -174,14 +178,19 @@ int soclose(so) register struct socket *so; { + struct socket *so2; int s = splsoftnet(); /* conservative */ int error = 0; if (so->so_options & SO_ACCEPTCONN) { - while (so->so_q0) - (void) soabort(so->so_q0); - while (so->so_q) - (void) soabort(so->so_q); + while ((so2 = so->so_q0) != NULL) { + (void) soqremque(so2, 0); + (void) soabort(so2); + } + while ((so2 = so->so_q) != NULL) { + (void) soqremque(so2, 1); + (void) soabort(so2); + } } if (so->so_pcb == 0) goto discard; @@ -237,12 +246,14 @@ soaccept(so, nam) struct mbuf *nam; { int s = splsoftnet(); - int error; + int error = 0; if ((so->so_state & SS_NOFDREF) == 0) panic("soaccept: !NOFDREF"); so->so_state &= ~SS_NOFDREF; - error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, NULL, nam, NULL); + if ((so->so_state & SS_ISDISCONNECTED) == 0) + error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, NULL, + nam, NULL); splx(s); return (error); } diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 7816894f6c9..e1ea890769f 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket2.c,v 1.9 1999/02/18 22:56:58 deraadt Exp $ */ +/* $OpenBSD: uipc_socket2.c,v 1.10 1999/02/19 15:06:52 millert Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* @@ -135,7 +135,7 @@ soisdisconnected(so) { so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); - so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); + so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED); wakeup((caddr_t)&so->so_timeo); sowwakeup(so); sorwakeup(so); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index e3d506b0bc3..421014f4b9d 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: socketvar.h,v 1.15 1999/02/18 22:56:57 deraadt Exp $ */ +/* $OpenBSD: socketvar.h,v 1.16 1999/02/19 15:06:52 millert Exp $ */ /* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */ /*- @@ -113,6 +113,7 @@ struct socket { #define SS_CANTSENDMORE 0x010 /* can't send more data to peer */ #define SS_CANTRCVMORE 0x020 /* can't receive more data from peer */ #define SS_RCVATMARK 0x040 /* at mark on input */ +#define SS_ISDISCONNECTED 0x800 /* socket disconnected from peer */ #define SS_PRIV 0x080 /* privileged for broadcast, raw... */ #define SS_NBIO 0x100 /* non-blocking ops */ |