Subject: Re: NetBSD Security Advisory 1999-001
To: None <tech-net@netbsd.org>
From: Jun Xie <jun@qnx.com>
List: tech-net
Date: 04/06/1999 16:20:38
> Synopsis: Fixes select(2)/accept(2) race condition which permits DoS.
> NetBSD versions: 1.0 - 1.3.3.
> 
> Index: kern/uipc_socket.c
> ===================================================================
> RCS file: /cvsroot/src/sys/kern/uipc_socket.c,v
> retrieving revision 1.29.4.1
> diff -c -2 -r1.29.4.1 uipc_socket.c
> *** uipc_socket.c	1998/01/30 19:24:12	1.29.4.1
> --- uipc_socket.c	1999/01/21 22:09:56
> ***************
[...]
> *** 165,176 ****
>   	register struct socket *so;
>   {
>   	int s = splsoftnet();		/* conservative */
>   	int error = 0;
>   
>   	if (so->so_options & SO_ACCEPTCONN) {
> ! 		while (so->so_q0.tqh_first)
> ! 			(void) soabort(so->so_q0.tqh_first);
> ! 		while (so->so_q.tqh_first)
> ! 			(void) soabort(so->so_q.tqh_first);
>   	}
>   	if (so->so_pcb == 0)
> --- 169,185 ----
>   	register struct socket *so;
>   {
> + 	struct socket *so2;
>   	int s = splsoftnet();		/* conservative */
>   	int error = 0;
>   
>   	if (so->so_options & SO_ACCEPTCONN) {
> ! 		while ((so2 = so->so_q0.tqh_first) != 0) {
> ! 			(void) soqremque(so2, 0);
> ! 			(void) soabort(so2);
> ! 		}
> ! 		while ((so2 = so->so_q.tqh_first) != 0) {
> ! 			(void) soqremque(so2, 1);
> ! 			(void) soabort(so2);
> ! 		}
>   	}
>   	if (so->so_pcb == 0)
> ***************
[...]

This patch works fine with INET domain but it seems to introduce a bug
in UNIX domain sockets.

unp_drop() calls sofree() and frees the unpcb structure only if so_head
is not NULL.  Since soclose() now calls soqremque() before soabort(),
so_head is NULL in unp_drop(). So those sockets and their unpcb's in a
UNIX stream socket's incoming connections queues will never get released
after the listening socket is closed.

-Jun