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