fix sys_accept() to return EOPNOTSUPP for protocols which don't support

listen/accept (PR_LISTEN flag in protosw) and detect obvious faults in
parameters passed.  It is still possible for the address used for copying
the socket information to become invalid between that check and the copyout
so close the connection's allocated fd if the copyout fails so that we can
return EFAULT without allocating an fd and the application not knowing about
it.  Ideally we'd be able to queue the connection back up so a later accept
could retrieve it but unfortunately that's not possible.
This commit is contained in:
darrenr 1999-07-01 05:56:32 +00:00
parent 67cac86e57
commit cd92b615fa

View File

@ -1,4 +1,4 @@
/* $NetBSD: uipc_syscalls.c,v 1.43 1999/05/05 20:01:09 thorpej Exp $ */ /* $NetBSD: uipc_syscalls.c,v 1.44 1999/07/01 05:56:32 darrenr Exp $ */
/* /*
* Copyright (c) 1982, 1986, 1989, 1990, 1993 * Copyright (c) 1982, 1986, 1989, 1990, 1993
@ -69,6 +69,9 @@
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/syscallargs.h> #include <sys/syscallargs.h>
#include <vm/vm.h>
#include <uvm/uvm_extern.h>
/* /*
* System call interface to the socket abstraction. * System call interface to the socket abstraction.
*/ */
@ -183,12 +186,21 @@ sys_accept(p, v, retval)
if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen), if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
(caddr_t)&namelen, sizeof(namelen)))) (caddr_t)&namelen, sizeof(namelen))))
return (error); return (error);
if (SCARG(uap, name) != NULL &&
uvm_useracc((caddr_t)SCARG(uap, name), sizeof(struct sockaddr),
B_WRITE) == FALSE)
return (EFAULT);
/* getsock() will use the descriptor for us */ /* getsock() will use the descriptor for us */
if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
return (error); return (error);
s = splsoftnet(); s = splsoftnet();
so = (struct socket *)fp->f_data; so = (struct socket *)fp->f_data;
FILE_UNUSE(fp, p); FILE_UNUSE(fp, p);
if (!(so->so_proto->pr_flags & PR_LISTEN)) {
splx(s);
return (EOPNOTSUPP);
}
if ((so->so_options & SO_ACCEPTCONN) == 0) { if ((so->so_options & SO_ACCEPTCONN) == 0) {
splx(s); splx(s);
return (EINVAL); return (EINVAL);
@ -242,6 +254,8 @@ sys_accept(p, v, retval)
error = copyout((caddr_t)&namelen, error = copyout((caddr_t)&namelen,
(caddr_t)SCARG(uap, anamelen), (caddr_t)SCARG(uap, anamelen),
sizeof(*SCARG(uap, anamelen))); sizeof(*SCARG(uap, anamelen)));
if (error != 0)
(void) closef(fp, p);
} }
m_freem(nam); m_freem(nam);
splx(s); splx(s);