Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 May 1999 07:06:05 -0700
From:      Don Lewis <Don.Lewis@tsc.tdk.com>
To:        Don Lewis <Don.Lewis@tsc.tdk.com>, Wes Peters <wes@softweyr.com>
Cc:        Kevin Day <toasty@HOME.DRAGONDATA.COM>, security@FreeBSD.ORG
Subject:   Re: KKIS.05051999.003b
Message-ID:  <199905101406.HAA23383@salsa.gv.tsc.tdk.com>
In-Reply-To: Don Lewis <Don.Lewis@tsc.tdk.com> "Re: KKIS.05051999.003b" (May  9,  5:40am)

next in thread | previous in thread | raw e-mail | index | archive | help
On May 9,  5:40am, Don Lewis wrote:
} Subject: Re: KKIS.05051999.003b
} On May 8, 10:21pm, Wes Peters wrote:
} } Subject: Re: KKIS.05051999.003b
} } Don Lewis wrote:
} 
} } > I don't see any obvious descriptor leaks, but the fact that FreeBSD < 3.1
} } > panics (probably in unp_gc(), which Matt fixed) indicates that I'm missing
} } > something.  The exploit code should not result in any calls to unp_gc(),
} } > because the client receives all the descriptors that are sent by the server.
} }
} } Actually it doesn't.  If you look up the first message I posted on this
} } subject, I listed the error messages it produces, many of which indicated
} } the client didn't get a descriptor from the server IIRC.

] On my 3.1-RELEASE system it reports numerous sendmsg ECONNREFUSED and
] ENOENTs, then eventually dives into repeats of:
] 
]         unlink error 2
]         bind error 9
]         sento error 9
]         recvmsg error 9
]         socket error 23

Steinar Haug noticed something odd in the exploit code - the client
process doesn't block in recvmsg() like one would expect.  If a message
is waiting, the client process will receive it, but if not, the client
will fall through the recvmsg() without getting an error indication.
This means that the client and server don't run in lockstep.  With
the default UFS mount options for /tmp, the client process will block
for short periods of time while it executes bind() and  unlink().  If
/tmp is MFS or is mounted async or with softupdates, the client process
will probably only block when its scheduling quantum expires.  This oddity
may allow multiple requests to accumulate for the server process, and
allows the server process to attempt to send responses at possibly
inconvenient times for the client.

If the server calls sendmsg() between the client's bind() and
recvmsg() syscalls, then everything works normally.

If the server calls sendmsg() between the client's recvmsg() and
close(sockfd) syscalls, or if the server manages to do more than
one sendmsg() call during one iteration of the client, which might
happen if the client exhausts its scheduling time quantum, one or
more messages will be outstanding when the client executes
close(sockfd).  This will result in unp_gc() being called to garbage
collect the descriptors that are in flight.  In FreeBSD < 3.1-RELEASE,
this will result in a panic due to sorflush() being improperly called
on a non-socket descriptor.

If the server calls sendmsg() after the client's close(sockfd) and
before the client unlinks the socket, the sendmsg() call will fail
with ECONNREFUSED.  If the server calls sendmsg() after the client
unlinks the socket and before the client calls bind(), then the
sendmsg() will fail with ENOENT.  Either of these failures will
cause the descriptor being sent to be permanently leaked away.
The rate at which descriptors are leaked depends on how the client
and server processes are scheduled.

Once enough descriptors have been leaked away, the client's socket()
syscall will fail with ENFILE, the bind(), sendto(), and recvmsg()
syscalls will fail with EBADF because the socket was not created,
and unlink() will fail because the socket name was not created by
bind().

The following patch appears to fix the descriptor leak.  I hope to
commit it later today.

Index: uipc_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.43
diff -u -u -r1.43 uipc_usrreq.c
--- uipc_usrreq.c	1999/04/28 11:37:07	1.43
+++ uipc_usrreq.c	1999/05/09 23:50:45
@@ -367,6 +367,9 @@
 		unp_shutdown(unp);
 	}
 
+	if (control && error != 0)
+		unp_dispose(control);
+
 release:
 	if (control)
 		m_freem(control);


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199905101406.HAA23383>