Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_syscalls.c
Show First 20 Lines • Show All 899 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
int | int | ||||
kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg, | kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg, | ||||
struct mbuf **controlp) | struct mbuf **controlp) | ||||
{ | { | ||||
struct uio auio; | struct uio auio; | ||||
struct iovec *iov; | struct iovec *iov; | ||||
struct mbuf *m, *control = NULL; | struct mbuf *control, *m; | ||||
caddr_t ctlbuf; | caddr_t ctlbuf; | ||||
struct file *fp; | struct file *fp; | ||||
struct socket *so; | struct socket *so; | ||||
struct sockaddr *fromsa = NULL; | struct sockaddr *fromsa = NULL; | ||||
#ifdef KTRACE | #ifdef KTRACE | ||||
struct uio *ktruio = NULL; | struct uio *ktruio = NULL; | ||||
#endif | #endif | ||||
ssize_t len; | ssize_t len; | ||||
Show All 30 Lines | if ((auio.uio_resid += iov->iov_len) < 0) { | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
} | } | ||||
#ifdef KTRACE | #ifdef KTRACE | ||||
if (KTRPOINT(td, KTR_GENIO)) | if (KTRPOINT(td, KTR_GENIO)) | ||||
ktruio = cloneuio(&auio); | ktruio = cloneuio(&auio); | ||||
#endif | #endif | ||||
control = NULL; | |||||
len = auio.uio_resid; | len = auio.uio_resid; | ||||
error = soreceive(so, &fromsa, &auio, NULL, | error = soreceive(so, &fromsa, &auio, NULL, | ||||
(mp->msg_control || controlp) ? &control : NULL, | (mp->msg_control || controlp) ? &control : NULL, | ||||
&mp->msg_flags); | &mp->msg_flags); | ||||
if (error != 0) { | if (error != 0) { | ||||
if (auio.uio_resid != len && (error == ERESTART || | if (auio.uio_resid != len && (error == ERESTART || | ||||
error == EINTR || error == EWOULDBLOCK)) | error == EINTR || error == EWOULDBLOCK)) | ||||
error = 0; | error = 0; | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | if (control && mp->msg_flags & MSG_COMPAT) { | ||||
SCM_RIGHTS) { | SCM_RIGHTS) { | ||||
mp->msg_controllen = 0; | mp->msg_controllen = 0; | ||||
goto out; | goto out; | ||||
} | } | ||||
control->m_len -= sizeof (struct cmsghdr); | control->m_len -= sizeof (struct cmsghdr); | ||||
control->m_data += sizeof (struct cmsghdr); | control->m_data += sizeof (struct cmsghdr); | ||||
} | } | ||||
#endif | #endif | ||||
ctlbuf = mp->msg_control; | |||||
len = mp->msg_controllen; | len = mp->msg_controllen; | ||||
m = control; | |||||
mp->msg_controllen = 0; | mp->msg_controllen = 0; | ||||
ctlbuf = mp->msg_control; | for (m = control; m != NULL && len >= m->m_len; m = m->m_next) { | ||||
if ((error = copyout(mtod(m, caddr_t), ctlbuf, | |||||
while (m && len > 0) { | m->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(mtod(m, caddr_t), | |||||
ctlbuf, tocopy)) != 0) | |||||
goto out; | goto out; | ||||
ctlbuf += tocopy; | ctlbuf += m->m_len; | ||||
len -= tocopy; | len -= m->m_len; | ||||
m = m->m_next; | mp->msg_controllen += m->m_len; | ||||
} | } | ||||
mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control; | if (m != NULL) { | ||||
mp->msg_flags |= MSG_CTRUNC; | |||||
m_dispose_extcontrolm(m); | |||||
} | } | ||||
} | |||||
out: | out: | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
#ifdef KTRACE | #ifdef KTRACE | ||||
if (fromsa && KTRPOINT(td, KTR_STRUCT)) | if (fromsa && KTRPOINT(td, KTR_STRUCT)) | ||||
ktrsockaddr(fromsa); | ktrsockaddr(fromsa); | ||||
#endif | #endif | ||||
free(fromsa, M_SONAME); | free(fromsa, M_SONAME); | ||||
if (error == 0 && controlp != NULL) | if (error == 0 && controlp != NULL) | ||||
*controlp = control; | *controlp = control; | ||||
else if (control) | else if (control != NULL) { | ||||
if (error != 0) | |||||
m_dispose_extcontrolm(control); | |||||
m_freem(control); | m_freem(control); | ||||
} | |||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp) | recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp) | ||||
{ | { | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 504 Lines • ▼ Show 20 Lines | |||||
#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN | #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN | ||||
if (sa->sa_family == 0 && sa->sa_len < AF_MAX) | if (sa->sa_family == 0 && sa->sa_len < AF_MAX) | ||||
sa->sa_family = sa->sa_len; | sa->sa_family = sa->sa_len; | ||||
#endif | #endif | ||||
sa->sa_len = len; | sa->sa_len = len; | ||||
*namp = sa; | *namp = sa; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | |||||
/* | |||||
* Dispose of externalized rights from an SCM_RIGHTS message. This function | |||||
* should be used in error or truncation cases to avoid leaking file descriptors | |||||
* into the recipient's (the current thread's) table. | |||||
*/ | |||||
void | |||||
m_dispose_extcontrolm(struct mbuf *m) | |||||
{ | |||||
struct cmsghdr *cm; | |||||
struct file *fp; | |||||
struct thread *td; | |||||
socklen_t clen, datalen; | |||||
int error, fd, *fds, nfd; | |||||
td = curthread; | |||||
for (; m != NULL; m = m->m_next) { | |||||
if (m->m_type != MT_EXTCONTROL) | |||||
continue; | |||||
cm = mtod(m, struct cmsghdr *); | |||||
clen = m->m_len; | |||||
while (clen > 0) { | |||||
if (clen < sizeof(*cm)) | |||||
panic("%s: truncated mbuf %p", __func__, m); | |||||
datalen = CMSG_SPACE(cm->cmsg_len - CMSG_SPACE(0)); | |||||
if (clen < datalen) | |||||
panic("%s: truncated mbuf %p", __func__, m); | |||||
if (cm->cmsg_level == SOL_SOCKET && | |||||
cm->cmsg_type == SCM_RIGHTS) { | |||||
fds = (int *)CMSG_DATA(cm); | |||||
nfd = (cm->cmsg_len - CMSG_SPACE(0)) / | |||||
sizeof(int); | |||||
while (nfd-- > 0) { | |||||
fd = *fds++; | |||||
error = fget(td, fd, &cap_no_rights, | |||||
&fp); | |||||
if (error == 0) | |||||
fdclose(td, fp, fd); | |||||
} | |||||
} | |||||
clen -= datalen; | |||||
cm = (struct cmsghdr *)((uint8_t *)cm + datalen); | |||||
} | |||||
m_chtype(m, MT_CONTROL); | |||||
} | |||||
} | } |