- Split out kern_accept(), kern_getpeername(), and kern_getsockname() for

use by ABI emulators.
- Alter the interface of kern_recvit() somewhat.  Specifically, go ahead
  and hard code UIO_USERSPACE in the uio as that's what all the callers
  specify.  In place, add a new uioseg to indicate what type of pointer
  is in mp->msg_name.  Previously it was always a userland address, but
  ABI emulators may pass in kernel-side sockaddrs.  Also, remove the
  namelenp field and instead require the two places that used it to
  explicitly copy mp->msg_namelen out to userland.
- Use the patched kern_recvit() to replace svr4_recvit() and the stock
  kern_sendit() to replace svr4_sendit().
- Use kern_bind() instead of stackgap use in ti_bind().
- Use kern_getpeername() and kern_getsockname() instead of stackgap in
  svr4_stream_ti_ioctl().
- Use kern_connect() instead of stackgap in svr4_do_putmsg().
- Use kern_getpeername() and kern_accept() instead of stackgap in
  svr4_do_getmsg().
- Retire the stackgap from SVR4 compat as it is no longer used.
This commit is contained in:
jhb 2006-07-10 21:38:17 +00:00
parent ee41eea403
commit cfc179a934
5 changed files with 245 additions and 511 deletions

View File

@ -1009,7 +1009,7 @@ freebsd32_recvmsg(td, uap)
msg.msg_iov = iov;
controlp = (msg.msg_control != NULL) ? &control : NULL;
error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp);
error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
if (error == 0) {
msg.msg_iov = uiov;
@ -1149,8 +1149,10 @@ freebsd32_recvfrom(struct thread *td,
aiov.iov_len = uap->len;
msg.msg_control = NULL;
msg.msg_flags = uap->flags;
error = kern_recvit(td, uap->s, &msg, PTRIN(uap->fromlenaddr),
UIO_USERSPACE, NULL);
error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
if (error == 0 && uap->fromlenaddr)
error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
sizeof (msg.msg_namelen));
return (error);
}

View File

@ -133,245 +133,6 @@ static int ti_getinfo(struct file *, int, struct svr4_strioctl *,
struct thread *);
static int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
/* infrastructure */
static int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags);
static int svr4_recvit(struct thread *td, int s, struct msghdr *mp,
caddr_t namelenp);
/* <sigh> Ok, so we shouldn't use sendit() in uipc_syscalls.c because
* it isn't part of a "public" interface; We're supposed to use
* pru_sosend instead. Same goes for recvit()/pru_soreceive() for
* that matter. Solution: Suck sendit()/recvit() into here where we
* can do what we like.
*
* I hate code duplication.
*
* I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
*/
static int
svr4_sendit(td, s, mp, flags)
register struct thread *td;
int s;
register struct msghdr *mp;
int flags;
{
struct uio auio;
register struct iovec *iov;
register int i;
struct mbuf *control;
struct sockaddr *to;
int len, error;
struct socket *so;
#ifdef KTRACE
struct uio *ktruio = NULL;
#endif
/*
* XXXRW: Instead of using fgetsock(), just rely on the file
* descriptor reference.
*/
if ((error = fgetsock(td, s, &so, NULL)) != 0)
return (error);
#ifdef MAC
SOCK_LOCK(so);
error = mac_check_socket_send(td->td_ucred, so);
SOCK_UNLOCK(so);
if (error)
goto done1;
#endif
auio.uio_iov = mp->msg_iov;
auio.uio_iovcnt = mp->msg_iovlen;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_rw = UIO_WRITE;
auio.uio_td = td;
auio.uio_offset = 0; /* XXX */
auio.uio_resid = 0;
iov = mp->msg_iov;
for (i = 0; i < mp->msg_iovlen; i++, iov++) {
if ((auio.uio_resid += iov->iov_len) < 0) {
error = EINVAL;
goto done1;
}
}
if (mp->msg_name) {
error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
if (error)
goto done1;
} else {
to = 0;
}
if (mp->msg_control) {
if (mp->msg_controllen < sizeof(struct cmsghdr)) {
error = EINVAL;
goto bad;
}
error = sockargs(&control, mp->msg_control,
mp->msg_controllen, MT_CONTROL);
if (error)
goto bad;
} else {
control = 0;
}
#ifdef KTRACE
if (KTRPOINT(td, KTR_GENIO))
ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
flags, td);
if (error) {
if (auio.uio_resid != len && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
if (error == EPIPE) {
PROC_LOCK(td->td_proc);
psignal(td->td_proc, SIGPIPE);
PROC_UNLOCK(td->td_proc);
}
}
if (error == 0)
td->td_retval[0] = len - auio.uio_resid;
#ifdef KTRACE
if (ktruio != NULL) {
ktruio->uio_resid = td->td_retval[0];
ktrgenio(s, UIO_WRITE, ktruio, error);
}
#endif
bad:
if (to)
FREE(to, M_SONAME);
done1:
fputsock(so);
return (error);
}
static int
svr4_recvit(td, s, mp, namelenp)
register struct thread *td;
int s;
register struct msghdr *mp;
caddr_t namelenp;
{
struct uio auio;
register struct iovec *iov;
register int i;
int len, error;
struct mbuf *m, *control = 0;
caddr_t ctlbuf;
struct socket *so;
struct sockaddr *fromsa = 0;
#ifdef KTRACE
struct uio *ktruio = NULL;
#endif
/*
* XXXRW: Instead of using fgetsock(), just rely on the file
* descriptor reference.
*/
if ((error = fgetsock(td, s, &so, NULL)) != 0)
return (error);
#ifdef MAC
SOCK_LOCK(so);
error = mac_check_socket_receive(td->td_ucred, so);
SOCK_UNLOCK(so);
if (error)
goto done1;
#endif
auio.uio_iov = mp->msg_iov;
auio.uio_iovcnt = mp->msg_iovlen;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_rw = UIO_READ;
auio.uio_td = td;
auio.uio_offset = 0; /* XXX */
auio.uio_resid = 0;
iov = mp->msg_iov;
for (i = 0; i < mp->msg_iovlen; i++, iov++) {
if ((auio.uio_resid += iov->iov_len) < 0) {
error = EINVAL;
goto done1;
}
}
#ifdef KTRACE
if (KTRPOINT(td, KTR_GENIO))
ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
(struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
&mp->msg_flags);
if (error) {
if (auio.uio_resid != len && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
}
#ifdef KTRACE
if (ktruio != NULL) {
ktruio->uio_resid = len - auio.uio_resid;
ktrgenio(s, UIO_READ, ktruio, error);
}
#endif
if (error)
goto out;
td->td_retval[0] = len - auio.uio_resid;
if (mp->msg_name) {
len = mp->msg_namelen;
if (len <= 0 || fromsa == 0)
len = 0;
else {
/* save sa_len before it is destroyed by MSG_COMPAT */
len = MIN(len, fromsa->sa_len);
error = copyout(fromsa,
(caddr_t)mp->msg_name, (unsigned)len);
if (error)
goto out;
}
mp->msg_namelen = len;
if (namelenp &&
(error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
goto out;
}
}
if (mp->msg_control) {
len = mp->msg_controllen;
m = control;
mp->msg_controllen = 0;
ctlbuf = (caddr_t) mp->msg_control;
while (m && len > 0) {
unsigned int tocopy;
if (len >= m->m_len)
tocopy = m->m_len;
else {
mp->msg_flags |= MSG_CTRUNC;
tocopy = len;
}
if ((error = copyout((caddr_t)mtod(m, caddr_t),
ctlbuf, tocopy)) != 0)
goto out;
ctlbuf += tocopy;
len -= tocopy;
m = m->m_next;
}
mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
}
out:
if (fromsa)
FREE(fromsa, M_SONAME);
if (control)
m_freem(control);
done1:
fputsock(so);
return (error);
}
#ifdef DEBUG_SVR4
static void bufprint(u_char *, size_t);
static int show_ioc(const char *, struct svr4_strioctl *);
@ -989,11 +750,9 @@ ti_bind(fp, fd, ioc, td)
struct svr4_strm *st = svr4_stream_get(fp);
struct sockaddr_in sain;
struct sockaddr_un saun;
caddr_t sg;
void *skp, *sup = NULL;
struct sockaddr *skp;
int sasize;
struct svr4_strmcmd bnd;
struct bind_args ba;
if (st == NULL) {
DPRINTF(("ti_bind: bad file descriptor\n"));
@ -1013,11 +772,11 @@ ti_bind(fp, fd, ioc, td)
switch (st->s_family) {
case AF_INET:
skp = &sain;
skp = (struct sockaddr *)&sain;
sasize = sizeof(sain);
if (bnd.offs == 0)
goto reply;
goto error;
netaddr_to_sockaddr_in(&sain, &bnd);
@ -1027,15 +786,15 @@ ti_bind(fp, fd, ioc, td)
break;
case AF_LOCAL:
skp = &saun;
skp = (struct sockaddr *)&saun;
sasize = sizeof(saun);
if (bnd.offs == 0)
goto reply;
goto error;
netaddr_to_sockaddr_un(&saun, &bnd);
if (saun.sun_path[0] == '\0')
goto reply;
goto error;
DPRINTF(("TI_BIND: fam %d, path %s\n",
saun.sun_family, saun.sun_path));
@ -1052,29 +811,20 @@ ti_bind(fp, fd, ioc, td)
return ENOSYS;
}
sg = stackgap_init();
sup = stackgap_alloc(&sg, sasize);
if ((error = copyout(skp, sup, sasize)) != 0)
return error;
ba.s = fd;
DPRINTF(("TI_BIND: fileno %d\n", fd));
ba.name = (void *) sup;
ba.namelen = sasize;
if ((error = bind(td, &ba)) != 0) {
if ((error = kern_bind(td, fd, skp)) != 0) {
DPRINTF(("TI_BIND: bind failed %d\n", error));
return error;
}
goto reply;
error:
memset(&bnd, 0, sizeof(bnd));
bnd.len = sasize + 4;
bnd.offs = 0x10; /* XXX */
reply:
if (sup == NULL) {
memset(&bnd, 0, sizeof(bnd));
bnd.len = sasize + 4;
bnd.offs = 0x10; /* XXX */
}
bnd.cmd = SVR4_TI_BIND_REPLY;
if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
@ -1127,13 +877,9 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
struct svr4_strm *st = svr4_stream_get(fp);
int error;
void *skp, *sup;
struct sockaddr_in sain;
struct sockaddr_un saun;
struct sockaddr *sa;
socklen_t sasize, oldsasize;
struct svr4_strmcmd sc;
int sasize, oldsasize;
caddr_t sg;
int *lenp;
DPRINTF(("svr4_stream_ti_ioctl\n"));
@ -1149,13 +895,11 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
switch (st->s_family) {
case AF_INET:
skp = &sain;
sasize = sizeof(sain);
sasize = sizeof(struct sockaddr_in);
break;
case AF_LOCAL:
skp = &saun;
sasize = sizeof(saun);
sasize = sizeof(struct sockaddr_un);
break;
default:
@ -1163,25 +907,14 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
st->s_family));
return ENOSYS;
}
sg = stackgap_init();
sup = stackgap_alloc(&sg, sasize);
lenp = stackgap_alloc(&sg, sizeof(*lenp));
if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
DPRINTF(("ti_ioctl: error copying out lenp\n"));
return error;
}
oldsasize = sasize;
switch (cmd) {
case SVR4_TI_GETMYNAME:
DPRINTF(("TI_GETMYNAME\n"));
{
struct getsockname_args ap;
ap.fdes = fd;
ap.asa = sup;
ap.alen = lenp;
if ((error = getsockname(td, &ap)) != 0) {
error = kern_getsockname(td, fd, &sa, &sasize);
if (error) {
DPRINTF(("ti_ioctl: getsockname error\n"));
return error;
}
@ -1191,11 +924,8 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
case SVR4_TI_GETPEERNAME:
DPRINTF(("TI_GETPEERNAME\n"));
{
struct getpeername_args ap;
ap.fdes = fd;
ap.asa = sup;
ap.alen = lenp;
if ((error = getpeername(td, &ap)) != 0) {
error = kern_getpeername(td, fd, &sa, &sasize);
if (error) {
DPRINTF(("ti_ioctl: getpeername error\n"));
return error;
}
@ -1214,36 +944,27 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
return ENOSYS;
}
if ((error = copyin(sup, skp, sasize)) != 0) {
DPRINTF(("ti_ioctl: error copying in socket data\n"));
return error;
}
oldsasize = sasize;
if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
DPRINTF(("ti_ioctl: error copying in socket size\n"));
return error;
}
if (sasize < 0 || sasize > oldsasize)
if (sasize < 0 || sasize > oldsasize) {
free(sa, M_SONAME);
return EINVAL;
}
switch (st->s_family) {
case AF_INET:
sockaddr_to_netaddr_in(&sc, &sain);
sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa);
skb.len = sasize;
break;
case AF_LOCAL:
sockaddr_to_netaddr_un(&sc, &saun);
sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa);
skb.len = sasize + 4;
break;
default:
free(sa, M_SONAME);
return ENOSYS;
}
free(sa, M_SONAME);
if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
DPRINTF(("ti_ioctl: error copying out socket data\n"));
@ -1314,7 +1035,6 @@ i_fdinsert(fp, td, retval, fd, cmd, dat)
struct svr4_strm *st = svr4_stream_get(fp);
struct svr4_strfdinsert fdi;
struct dup2_args d2p;
struct close_args clp;
if (st == NULL) {
DPRINTF(("fdinsert: bad file type\n"));
@ -1340,9 +1060,7 @@ i_fdinsert(fp, td, retval, fd, cmd, dat)
return error;
}
clp.fd = st->s_afd;
if ((error = close(td, &clp)) != 0) {
if ((error = kern_close(td, st->s_afd)) != 0) {
DPRINTF(("fdinsert: close(%d) failed %d\n",
st->s_afd, error));
return error;
@ -1742,11 +1460,10 @@ svr4_do_putmsg(td, uap, fp)
struct svr4_strmcmd sc;
struct sockaddr_in sain;
struct sockaddr_un saun;
void *skp, *sup;
struct sockaddr *sa;
int sasize, *retval;
struct svr4_strm *st;
int error;
caddr_t sg;
retval = td->td_retval;
@ -1820,9 +1537,10 @@ svr4_do_putmsg(td, uap, fp)
return EINVAL;
}
netaddr_to_sockaddr_in(&sain, &sc);
skp = &sain;
sa = (struct sockaddr *)&sain;
sasize = sizeof(sain);
error = sain.sin_family != st->s_family;
if (sain.sin_family != st->s_family)
error = EINVAL;
break;
case AF_LOCAL:
@ -1836,11 +1554,12 @@ svr4_do_putmsg(td, uap, fp)
/* Maybe we've been given a device/inode pair */
dev_t *dev = SVR4_ADDROF(&sc);
ino_t *ino = (ino_t *) &dev[1];
skp = svr4_find_socket(td, fp, *dev, *ino);
if (skp == NULL) {
skp = &saun;
sa = (struct sockaddr *)
svr4_find_socket(td, fp, *dev, *ino);
if (sa == NULL) {
sa = (struct sockaddr *)&saun;
/* I guess we have it by name */
netaddr_to_sockaddr_un(skp, &sc);
netaddr_to_sockaddr_un(&saun, &sc);
}
sasize = sizeof(saun);
}
@ -1852,22 +1571,11 @@ svr4_do_putmsg(td, uap, fp)
return ENOSYS;
}
sg = stackgap_init();
sup = stackgap_alloc(&sg, sasize);
if ((error = copyout(skp, sup, sasize)) != 0)
return error;
switch (st->s_cmd = sc.cmd) {
case SVR4_TI_CONNECT_REQUEST: /* connect */
{
struct connect_args co;
co.s = uap->fd;
co.name = (void *) sup;
co.namelen = (int) sasize;
return connect(td, &co);
return (kern_connect(td, uap->fd, sa));
}
case SVR4_TI_SENDTO_REQUEST: /* sendto */
@ -1875,7 +1583,7 @@ svr4_do_putmsg(td, uap, fp)
struct msghdr msg;
struct iovec aiov;
msg.msg_name = (caddr_t) sup;
msg.msg_name = sa;
msg.msg_namelen = sasize;
msg.msg_iov = &aiov;
msg.msg_iovlen = 1;
@ -1883,12 +1591,8 @@ svr4_do_putmsg(td, uap, fp)
msg.msg_flags = 0;
aiov.iov_base = dat.buf;
aiov.iov_len = dat.len;
#if 0
error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
uio, 0, 0, 0, uio->uio_td);
#endif
error = svr4_sendit(td, uap->fd, &msg,
uap->flags);
error = kern_sendit(td, uap->fd, &msg, uap->flags,
NULL, UIO_USERSPACE);
DPRINTF(("sendto_request error: %d\n", error));
*retval = 0;
return error;
@ -1925,8 +1629,6 @@ svr4_do_getmsg(td, uap, fp)
struct svr4_sys_getmsg_args *uap;
struct file *fp;
{
struct getpeername_args ga;
struct accept_args aa;
struct svr4_strbuf dat, ctl;
struct svr4_strmcmd sc;
int error, *retval;
@ -1934,14 +1636,13 @@ svr4_do_getmsg(td, uap, fp)
struct iovec aiov;
struct sockaddr_in sain;
struct sockaddr_un saun;
void *skp, *sup;
int sasize;
struct sockaddr *sa;
socklen_t sasize;
struct svr4_strm *st;
int *flen;
int fl;
caddr_t sg;
retval = td->td_retval;
error = 0;
FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
@ -1987,12 +1688,10 @@ svr4_do_getmsg(td, uap, fp)
switch (st->s_family) {
case AF_INET:
skp = &sain;
sasize = sizeof(sain);
break;
case AF_LOCAL:
skp = &saun;
sasize = sizeof(saun);
break;
@ -2002,14 +1701,6 @@ svr4_do_getmsg(td, uap, fp)
return ENOSYS;
}
sg = stackgap_init();
sup = stackgap_alloc(&sg, sasize);
flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
fl = sasize;
if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
return error;
switch (st->s_cmd) {
case SVR4_TI_CONNECT_REQUEST:
DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
@ -2033,18 +1724,12 @@ svr4_do_getmsg(td, uap, fp)
* a connect verification.
*/
ga.fdes = uap->fd;
ga.asa = (void *) sup;
ga.alen = flen;
if ((error = getpeername(td, &ga)) != 0) {
error = kern_getpeername(td, uap->fd, &sa, &sasize);
if (error) {
DPRINTF(("getmsg: getpeername failed %d\n", error));
return error;
}
if ((error = copyin(sup, skp, sasize)) != 0)
return error;
sc.cmd = SVR4_TI_CONNECT_REPLY;
sc.pad[0] = 0x4;
sc.offs = 0x18;
@ -2054,17 +1739,19 @@ svr4_do_getmsg(td, uap, fp)
switch (st->s_family) {
case AF_INET:
sc.len = sasize;
sockaddr_to_netaddr_in(&sc, &sain);
sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa);
break;
case AF_LOCAL:
sc.len = sasize + 4;
sockaddr_to_netaddr_un(&sc, &saun);
sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa);
break;
default:
free(sa, M_SONAME);
return ENOSYS;
}
free(sa, M_SONAME);
ctl.len = 40;
dat.len = -1;
@ -2092,11 +1779,9 @@ svr4_do_getmsg(td, uap, fp)
/*
* We are after a listen, so we try to accept...
*/
aa.s = uap->fd;
aa.name = (void *) sup;
aa.anamelen = flen;
if ((error = accept(td, &aa)) != 0) {
error = kern_accept(td, uap->fd, &sa, &sasize);
if (error) {
DPRINTF(("getmsg: accept failed %d\n", error));
return error;
}
@ -2105,9 +1790,6 @@ svr4_do_getmsg(td, uap, fp)
DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
if ((error = copyin(sup, skp, sasize)) != 0)
return error;
sc.cmd = SVR4_TI_ACCEPT_REPLY;
sc.offs = 0x18;
sc.pad[0] = 0x0;
@ -2115,7 +1797,7 @@ svr4_do_getmsg(td, uap, fp)
switch (st->s_family) {
case AF_INET:
sc.pad[1] = 0x28;
sockaddr_to_netaddr_in(&sc, &sain);
sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)&sa);
ctl.len = 40;
sc.len = sasize;
break;
@ -2129,8 +1811,10 @@ svr4_do_getmsg(td, uap, fp)
break;
default:
free(sa, M_SONAME);
return ENOSYS;
}
free(sa, M_SONAME);
dat.len = -1;
fl = 0;
@ -2150,10 +1834,12 @@ svr4_do_getmsg(td, uap, fp)
switch (st->s_family) {
case AF_INET:
sa = (struct sockaddr *)&sain;
sockaddr_to_netaddr_in(&sc, &sain);
break;
case AF_LOCAL:
sa = (struct sockaddr *)&saun;
sockaddr_to_netaddr_un(&sc, &saun);
break;
@ -2161,7 +1847,7 @@ svr4_do_getmsg(td, uap, fp)
return ENOSYS;
}
msg.msg_name = (caddr_t) sup;
msg.msg_name = sa;
msg.msg_namelen = sasize;
msg.msg_iov = &aiov;
msg.msg_iovlen = 1;
@ -2170,16 +1856,13 @@ svr4_do_getmsg(td, uap, fp)
aiov.iov_len = dat.maxlen;
msg.msg_flags = 0;
error = svr4_recvit(td, uap->fd, &msg, (caddr_t) flen);
error = kern_recvit(td, uap->fd, &msg, UIO_SYSSPACE, NULL);
if (error) {
DPRINTF(("getmsg: recvit failed %d\n", error));
return error;
}
if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
return error;
sc.cmd = SVR4_TI_RECVFROM_IND;
switch (st->s_family) {
@ -2233,6 +1916,7 @@ svr4_do_getmsg(td, uap, fp)
return EINVAL;
}
/* XXX: We leak the accept fd if we get an error here. */
if (uap->ctl) {
if (ctl.len > sizeof(sc))
ctl.len = sizeof(sc);

View File

@ -47,30 +47,6 @@
#define DPRINTF(a)
#endif
static __inline caddr_t stackgap_init(void);
static __inline void *stackgap_alloc(caddr_t *, size_t);
static __inline caddr_t
stackgap_init()
{
#define szsigcode (*(curthread->td_proc->p_sysent->sv_szsigcode))
return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE);
}
static __inline void *
stackgap_alloc(sgp, sz)
caddr_t *sgp;
size_t sz;
{
void *p = (void *) *sgp;
sz = ALIGN(sz);
if (*sgp + sz > (caddr_t)(PS_STRINGS - szsigcode))
return NULL;
*sgp += sz;
return p;
}
int svr4_emul_find(struct thread *, char *, enum uio_seg, char **, int);
#define CHECKALT(td, upath, pathp, i) \

View File

@ -295,11 +295,54 @@ accept1(td, uap, compat)
socklen_t * __restrict anamelen;
} */ *uap;
int compat;
{
struct sockaddr *name;
socklen_t namelen;
int error;
if (uap->name == NULL)
return (kern_accept(td, uap->s, NULL, NULL));
error = copyin(uap->anamelen, &namelen, sizeof (namelen));
if (error)
return (error);
error = kern_accept(td, uap->s, &name, &namelen);
/*
* return a namelen of zero for older code which might
* ignore the return value from accept.
*/
if (error) {
(void) copyout(&namelen,
uap->anamelen, sizeof(*uap->anamelen));
return (error);
}
if (error == 0 && name != NULL) {
#ifdef COMPAT_OLDSOCK
if (compat)
((struct osockaddr *)name)->sa_family =
name->sa_family;
#endif
error = copyout(name, uap->name, namelen);
}
if (error == 0)
error = copyout(&namelen, uap->anamelen,
sizeof(namelen));
if (error)
kern_close(td, td->td_retval[0]);
free(name, M_SONAME);
return (error);
}
int
kern_accept(struct thread *td, int s, struct sockaddr **name,
socklen_t *namelen)
{
struct filedesc *fdp;
struct file *headfp, *nfp = NULL;
struct sockaddr *sa = NULL;
socklen_t namelen;
int error;
struct socket *head, *so;
int fd;
@ -307,16 +350,15 @@ accept1(td, uap, compat)
pid_t pgid;
int tmp;
fdp = td->td_proc->p_fd;
if (uap->name) {
error = copyin(uap->anamelen, &namelen, sizeof (namelen));
if(error)
return (error);
if (namelen < 0)
if (name) {
*name = NULL;
if (*namelen < 0)
return (EINVAL);
}
fdp = td->td_proc->p_fd;
NET_LOCK_GIANT();
error = getsock(fdp, uap->s, &headfp, &fflag);
error = getsock(fdp, s, &headfp, &fflag);
if (error)
goto done2;
head = headfp->f_data;
@ -407,34 +449,21 @@ accept1(td, uap, compat)
* return a namelen of zero for older code which might
* ignore the return value from accept.
*/
if (uap->name != NULL) {
namelen = 0;
(void) copyout(&namelen,
uap->anamelen, sizeof(*uap->anamelen));
}
if (name)
*namelen = 0;
goto noconnection;
}
if (sa == NULL) {
namelen = 0;
if (uap->name)
goto gotnoname;
error = 0;
if (name)
*namelen = 0;
goto done;
}
if (uap->name) {
if (name) {
/* check sa_len before it is destroyed */
if (namelen > sa->sa_len)
namelen = sa->sa_len;
#ifdef COMPAT_OLDSOCK
if (compat)
((struct osockaddr *)sa)->sa_family =
sa->sa_family;
#endif
error = copyout(sa, uap->name, (u_int)namelen);
if (!error)
gotnoname:
error = copyout(&namelen,
uap->anamelen, sizeof (*uap->anamelen));
if (*namelen > sa->sa_len)
*namelen = sa->sa_len;
*name = sa;
sa = NULL;
}
noconnection:
if (sa)
@ -926,12 +955,11 @@ sendmsg(td, uap)
}
int
kern_recvit(td, s, mp, namelenp, segflg, controlp)
kern_recvit(td, s, mp, fromseg, controlp)
struct thread *td;
int s;
struct msghdr *mp;
void *namelenp;
enum uio_seg segflg;
enum uio_seg fromseg;
struct mbuf **controlp;
{
struct uio auio;
@ -972,7 +1000,7 @@ kern_recvit(td, s, mp, namelenp, segflg, controlp)
auio.uio_iov = mp->msg_iov;
auio.uio_iovcnt = mp->msg_iovlen;
auio.uio_segflg = segflg;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_rw = UIO_READ;
auio.uio_td = td;
auio.uio_offset = 0; /* XXX */
@ -1020,20 +1048,15 @@ kern_recvit(td, s, mp, namelenp, segflg, controlp)
((struct osockaddr *)fromsa)->sa_family =
fromsa->sa_family;
#endif
error = copyout(fromsa, mp->msg_name, (unsigned)len);
if (error)
goto out;
if (fromseg == UIO_USERSPACE) {
error = copyout(fromsa, mp->msg_name,
(unsigned)len);
if (error)
goto out;
} else
bcopy(fromsa, mp->msg_name, len);
}
mp->msg_namelen = len;
if (namelenp &&
(error = copyout(&len, namelenp, sizeof (socklen_t)))) {
#ifdef COMPAT_OLDSOCK
if (mp->msg_flags & MSG_COMPAT)
error = 0; /* old recvfrom didn't check */
else
#endif
goto out;
}
}
if (mp->msg_control && controlp == NULL) {
#ifdef COMPAT_OLDSOCK
@ -1102,8 +1125,19 @@ recvit(td, s, mp, namelenp)
struct msghdr *mp;
void *namelenp;
{
int error;
return (kern_recvit(td, s, mp, namelenp, UIO_USERSPACE, NULL));
error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL);
if (error)
return (error);
if (namelenp) {
error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t));
#ifdef COMPAT_OLDSOCK
if (mp->msg_flags & MSG_COMPAT)
error = 0; /* old recvfrom didn't check */
#endif
}
return (error);
}
/*
@ -1459,48 +1493,64 @@ getsockname1(td, uap, compat)
} */ *uap;
int compat;
{
struct socket *so;
struct sockaddr *sa;
socklen_t len;
int error;
error = copyin(uap->alen, &len, sizeof(len));
if (error)
return (error);
error = kern_getsockname(td, uap->fdes, &sa, &len);
if (error)
return (error);
if (len != 0) {
#ifdef COMPAT_OLDSOCK
if (compat)
((struct osockaddr *)sa)->sa_family = sa->sa_family;
#endif
error = copyout(sa, uap->asa, (u_int)len);
}
free(sa, M_SONAME);
if (error == 0)
error = copyout(&len, uap->alen, sizeof(len));
return (error);
}
int
kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
socklen_t *alen)
{
struct socket *so;
struct file *fp;
socklen_t len;
int error;
if (*alen < 0)
return (EINVAL);
NET_LOCK_GIANT();
error = getsock(td->td_proc->p_fd, uap->fdes, &fp, NULL);
error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
if (error)
goto done2;
goto done;
so = fp->f_data;
error = copyin(uap->alen, &len, sizeof (len));
if (error)
goto done1;
if (len < 0) {
error = EINVAL;
goto done1;
}
sa = 0;
error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
*sa = NULL;
error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa);
if (error)
goto bad;
if (sa == 0) {
if (*sa == NULL)
len = 0;
goto gotnothing;
}
len = MIN(len, sa->sa_len);
#ifdef COMPAT_OLDSOCK
if (compat)
((struct osockaddr *)sa)->sa_family = sa->sa_family;
#endif
error = copyout(sa, uap->asa, (u_int)len);
if (error == 0)
gotnothing:
error = copyout(&len, uap->alen, sizeof (len));
else
len = MIN(*alen, (*sa)->sa_len);
*alen = len;
bad:
if (sa)
FREE(sa, M_SONAME);
done1:
fdrop(fp, td);
done2:
if (error && *sa) {
free(*sa, M_SONAME);
*sa = NULL;
}
done:
NET_UNLOCK_GIANT();
return (error);
}
@ -1547,14 +1597,45 @@ getpeername1(td, uap, compat)
} */ *uap;
int compat;
{
struct socket *so;
struct sockaddr *sa;
socklen_t len;
int error;
error = copyin(uap->alen, &len, sizeof (len));
if (error)
return (error);
error = kern_getpeername(td, uap->fdes, &sa, &len);
if (error)
return (error);
if (len != 0) {
#ifdef COMPAT_OLDSOCK
if (compat)
((struct osockaddr *)sa)->sa_family = sa->sa_family;
#endif
error = copyout(sa, uap->asa, (u_int)len);
}
free(sa, M_SONAME);
if (error == 0)
error = copyout(&len, uap->alen, sizeof(len));
return (error);
}
int
kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
socklen_t *alen)
{
struct socket *so;
struct file *fp;
socklen_t len;
int error;
if (*alen < 0)
return (EINVAL);
NET_LOCK_GIANT();
error = getsock(td->td_proc->p_fd, uap->fdes, &fp, NULL);
error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
if (error)
goto done2;
so = fp->f_data;
@ -1562,35 +1643,20 @@ getpeername1(td, uap, compat)
error = ENOTCONN;
goto done1;
}
error = copyin(uap->alen, &len, sizeof (len));
if (error)
goto done1;
if (len < 0) {
error = EINVAL;
goto done1;
}
sa = 0;
error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
*sa = NULL;
error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, sa);
if (error)
goto bad;
if (sa == 0) {
if (*sa == NULL)
len = 0;
goto gotnothing;
}
len = MIN(len, sa->sa_len);
#ifdef COMPAT_OLDSOCK
if (compat)
((struct osockaddr *)sa)->sa_family =
sa->sa_family;
#endif
error = copyout(sa, uap->asa, (u_int)len);
if (error)
goto bad;
gotnothing:
error = copyout(&len, uap->alen, sizeof (len));
else
len = MIN(*alen, (*sa)->sa_len);
*alen = len;
bad:
if (sa)
FREE(sa, M_SONAME);
if (error && *sa) {
free(*sa, M_SONAME);
*sa = NULL;
}
done1:
fdrop(fp, td);
done2:

View File

@ -50,6 +50,8 @@ struct sendfile_args;
int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg,
u_int buflen);
int kern_accept(struct thread *td, int s, struct sockaddr **name,
socklen_t *namelen);
int kern_access(struct thread *td, char *path, enum uio_seg pathseg,
int flags);
int kern_adjtime(struct thread *td, struct timeval *delta,
@ -84,7 +86,11 @@ int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
enum uio_seg bufseg, int flags);
int kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups);
int kern_getitimer(struct thread *, u_int, struct itimerval *);
int kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
socklen_t *alen);
int kern_getrusage(struct thread *td, int who, struct rusage *rup);
int kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
socklen_t *alen);
int kern_getsockopt(struct thread *td, int s, int level, int name,
void *optval, enum uio_seg valseg, socklen_t *valsize);
int kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data);
@ -120,8 +126,8 @@ int kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset);
int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg,
char *buf, enum uio_seg bufseg, int count);
int kern_readv(struct thread *td, int fd, struct uio *auio);
int kern_recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp,
enum uio_seg segflg, struct mbuf **controlp);
int kern_recvit(struct thread *td, int s, struct msghdr *mp,
enum uio_seg fromseg, struct mbuf **controlp);
int kern_rename(struct thread *td, char *from, char *to,
enum uio_seg pathseg);
int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg);