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:
parent
67cac86e57
commit
cd92b615fa
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user