accept(),accept4(): Don't set *addrlen = 0 on [ECONNABORTED].

If the underlying protocol reported an error (e.g. because a connection was
closed while waiting in the queue), this error was also indicated by
returning a zero-length address. For all other kinds of errors (e.g.
[EAGAIN], [ENFILE], [EMFILE]), *addrlen is unmodified and there are
successful cases where a zero-length address is returned (e.g. a connection
from an unbound Unix-domain socket), so this error indication is not
reliable.

As reported in Austin Group bug #836, modifying *addrlen on error may cause
subtle bugs if applications retry the call without resetting *addrlen.
This commit is contained in:
Jilles Tjoelker 2014-05-11 21:21:14 +00:00
parent eb941910ca
commit 857ce8a246

View File

@ -414,14 +414,8 @@ accept1(td, s, uname, anamelen, flags)
error = kern_accept4(td, s, &name, &namelen, flags, &fp);
/*
* return a namelen of zero for older code which might
* ignore the return value from accept.
*/
if (error != 0) {
(void) copyout(&namelen, anamelen, sizeof(*anamelen));
if (error != 0)
return (error);
}
if (error == 0 && uname != NULL) {
#ifdef COMPAT_OLDSOCK
@ -555,15 +549,8 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name,
(void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
sa = 0;
error = soaccept(so, &sa);
if (error != 0) {
/*
* return a namelen of zero for older code which might
* ignore the return value from accept.
*/
if (name)
*namelen = 0;
if (error != 0)
goto noconnection;
}
if (sa == NULL) {
if (name)
*namelen = 0;