Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/uipc_syscalls.c
Show First 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
#include <sys/filio.h> | #include <sys/filio.h> | ||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/protosw.h> | #include <sys/protosw.h> | ||||
#include <sys/rwlock.h> | #include <sys/rwlock.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/socketvar.h> | #include <sys/socketvar.h> | ||||
#include <sys/syscallsubr.h> | #include <sys/syscallsubr.h> | ||||
#include <sys/sysent.h> | |||||
#include <sys/uio.h> | #include <sys/uio.h> | ||||
#include <sys/un.h> | #include <sys/un.h> | ||||
#include <sys/unpcb.h> | #include <sys/unpcb.h> | ||||
#ifdef KTRACE | #ifdef KTRACE | ||||
#include <sys/ktrace.h> | #include <sys/ktrace.h> | ||||
#endif | #endif | ||||
#ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
#include <compat/freebsd32/freebsd32_util.h> | #include <compat/freebsd32/freebsd32_util.h> | ||||
▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | accept1(td, s, uname, anamelen, flags) | ||||
error = kern_accept4(td, s, &name, &namelen, flags, &fp); | error = kern_accept4(td, s, &name, &namelen, flags, &fp); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
if (error == 0 && uname != NULL) { | if (error == 0 && uname != NULL) { | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (flags & ACCEPT4_COMPAT) | if (SV_PROC_FLAG(td->td_proc, SV_AOUT) && | ||||
(flags & ACCEPT4_COMPAT) != 0) | |||||
((struct osockaddr *)name)->sa_family = | ((struct osockaddr *)name)->sa_family = | ||||
name->sa_family; | name->sa_family; | ||||
#endif | #endif | ||||
error = copyout(name, uname, namelen); | error = copyout(name, uname, namelen); | ||||
} | } | ||||
if (error == 0) | if (error == 0) | ||||
error = copyout(&namelen, anamelen, | error = copyout(&namelen, anamelen, | ||||
sizeof(namelen)); | sizeof(namelen)); | ||||
▲ Show 20 Lines • Show All 382 Lines • ▼ Show 20 Lines | if (mp->msg_name != NULL) { | ||||
mp->msg_name = to; | mp->msg_name = to; | ||||
} else { | } else { | ||||
to = NULL; | to = NULL; | ||||
} | } | ||||
if (mp->msg_control) { | if (mp->msg_control) { | ||||
if (mp->msg_controllen < sizeof(struct cmsghdr) | if (mp->msg_controllen < sizeof(struct cmsghdr) | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
&& mp->msg_flags != MSG_COMPAT | && (mp->msg_flags != MSG_COMPAT || | ||||
!SV_PROC_FLAG(td->td_proc, SV_AOUT)) | |||||
#endif | #endif | ||||
) { | ) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
error = sockargs(&control, mp->msg_control, | error = sockargs(&control, mp->msg_control, | ||||
mp->msg_controllen, MT_CONTROL); | mp->msg_controllen, MT_CONTROL); | ||||
if (error != 0) | if (error != 0) | ||||
goto bad; | goto bad; | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (mp->msg_flags == MSG_COMPAT) { | if (mp->msg_flags == MSG_COMPAT && | ||||
SV_PROC_FLAG(td->td_proc, SV_AOUT)) { | |||||
struct cmsghdr *cm; | struct cmsghdr *cm; | ||||
M_PREPEND(control, sizeof(*cm), M_WAITOK); | M_PREPEND(control, sizeof(*cm), M_WAITOK); | ||||
cm = mtod(control, struct cmsghdr *); | cm = mtod(control, struct cmsghdr *); | ||||
cm->cmsg_len = control->m_len; | cm->cmsg_len = control->m_len; | ||||
cm->cmsg_level = SOL_SOCKET; | cm->cmsg_level = SOL_SOCKET; | ||||
cm->cmsg_type = SCM_RIGHTS; | cm->cmsg_type = SCM_RIGHTS; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | sys_sendto(struct thread *td, struct sendto_args *uap) | ||||
struct iovec aiov; | struct iovec aiov; | ||||
msg.msg_name = __DECONST(void *, uap->to); | msg.msg_name = __DECONST(void *, uap->to); | ||||
msg.msg_namelen = uap->tolen; | msg.msg_namelen = uap->tolen; | ||||
msg.msg_iov = &aiov; | msg.msg_iov = &aiov; | ||||
msg.msg_iovlen = 1; | msg.msg_iovlen = 1; | ||||
msg.msg_control = 0; | msg.msg_control = 0; | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (SV_PROC_FLAG(td->td_proc, SV_AOUT)) | |||||
msg.msg_flags = 0; | msg.msg_flags = 0; | ||||
#endif | #endif | ||||
aiov.iov_base = __DECONST(void *, uap->buf); | aiov.iov_base = __DECONST(void *, uap->buf); | ||||
aiov.iov_len = uap->len; | aiov.iov_len = uap->len; | ||||
return (sendit(td, uap->s, &msg, uap->flags)); | return (sendit(td, uap->s, &msg, uap->flags)); | ||||
} | } | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
int | int | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | sys_sendmsg(struct thread *td, struct sendmsg_args *uap) | ||||
error = copyin(uap->msg, &msg, sizeof (msg)); | error = copyin(uap->msg, &msg, sizeof (msg)); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); | error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
msg.msg_iov = iov; | msg.msg_iov = iov; | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (SV_PROC_FLAG(td->td_proc, SV_AOUT)) | |||||
msg.msg_flags = 0; | msg.msg_flags = 0; | ||||
#endif | #endif | ||||
error = sendit(td, uap->s, &msg, uap->flags); | error = sendit(td, uap->s, &msg, uap->flags); | ||||
free(iov, M_IOV); | free(iov, M_IOV); | ||||
return (error); | return (error); | ||||
} | } | ||||
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, | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | #endif | ||||
if (mp->msg_name) { | if (mp->msg_name) { | ||||
len = mp->msg_namelen; | len = mp->msg_namelen; | ||||
if (len <= 0 || fromsa == NULL) | if (len <= 0 || fromsa == NULL) | ||||
len = 0; | len = 0; | ||||
else { | else { | ||||
/* save sa_len before it is destroyed by MSG_COMPAT */ | /* save sa_len before it is destroyed by MSG_COMPAT */ | ||||
len = MIN(len, fromsa->sa_len); | len = MIN(len, fromsa->sa_len); | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (mp->msg_flags & MSG_COMPAT) | if ((mp->msg_flags & MSG_COMPAT) != 0 && | ||||
SV_PROC_FLAG(td->td_proc, SV_AOUT)) | |||||
((struct osockaddr *)fromsa)->sa_family = | ((struct osockaddr *)fromsa)->sa_family = | ||||
fromsa->sa_family; | fromsa->sa_family; | ||||
#endif | #endif | ||||
if (fromseg == UIO_USERSPACE) { | if (fromseg == UIO_USERSPACE) { | ||||
error = copyout(fromsa, mp->msg_name, | error = copyout(fromsa, mp->msg_name, | ||||
(unsigned)len); | (unsigned)len); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
} else | } else | ||||
bcopy(fromsa, mp->msg_name, len); | bcopy(fromsa, mp->msg_name, len); | ||||
} | } | ||||
mp->msg_namelen = len; | mp->msg_namelen = len; | ||||
} | } | ||||
if (mp->msg_control && controlp == NULL) { | if (mp->msg_control && controlp == NULL) { | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
/* | /* | ||||
* We assume that old recvmsg calls won't receive access | * We assume that old recvmsg calls won't receive access | ||||
* rights and other control info, esp. as control info | * rights and other control info, esp. as control info | ||||
* is always optional and those options didn't exist in 4.3. | * is always optional and those options didn't exist in 4.3. | ||||
* If we receive rights, trim the cmsghdr; anything else | * If we receive rights, trim the cmsghdr; anything else | ||||
* is tossed. | * is tossed. | ||||
*/ | */ | ||||
if (control && mp->msg_flags & MSG_COMPAT) { | if (control && (mp->msg_flags & MSG_COMPAT) != 0 && | ||||
SV_PROC_FLAG(td->td_proc, SV_AOUT)) { | |||||
if (mtod(control, struct cmsghdr *)->cmsg_level != | if (mtod(control, struct cmsghdr *)->cmsg_level != | ||||
SOL_SOCKET || | SOL_SOCKET || | ||||
mtod(control, struct cmsghdr *)->cmsg_type != | mtod(control, struct cmsghdr *)->cmsg_type != | ||||
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); | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp) | ||||
int error; | int error; | ||||
error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL); | error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
if (namelenp != NULL) { | if (namelenp != NULL) { | ||||
error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t)); | error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t)); | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (mp->msg_flags & MSG_COMPAT) | if ((mp->msg_flags & MSG_COMPAT) != 0 && | ||||
SV_PROC_FLAG(td->td_proc, SV_AOUT)) | |||||
error = 0; /* old recvfrom didn't check */ | error = 0; /* old recvfrom didn't check */ | ||||
#endif | #endif | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
sys_recvfrom(struct thread *td, struct recvfrom_args *uap) | sys_recvfrom(struct thread *td, struct recvfrom_args *uap) | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | sys_recvmsg(struct thread *td, struct recvmsg_args *uap) | ||||
error = copyin(uap->msg, &msg, sizeof (msg)); | error = copyin(uap->msg, &msg, sizeof (msg)); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); | error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
msg.msg_flags = uap->flags; | msg.msg_flags = uap->flags; | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (SV_PROC_FLAG(td->td_proc, SV_AOUT)) | |||||
msg.msg_flags &= ~MSG_COMPAT; | msg.msg_flags &= ~MSG_COMPAT; | ||||
#endif | #endif | ||||
uiov = msg.msg_iov; | uiov = msg.msg_iov; | ||||
msg.msg_iov = iov; | msg.msg_iov = iov; | ||||
error = recvit(td, uap->s, &msg, NULL); | error = recvit(td, uap->s, &msg, NULL); | ||||
if (error == 0) { | if (error == 0) { | ||||
msg.msg_iov = uiov; | msg.msg_iov = uiov; | ||||
error = copyout(&msg, uap->msg, sizeof(msg)); | error = copyout(&msg, uap->msg, sizeof(msg)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | if (error != 0) | ||||
return (error); | return (error); | ||||
error = kern_getsockname(td, uap->fdes, &sa, &len); | error = kern_getsockname(td, uap->fdes, &sa, &len); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
if (len != 0) { | if (len != 0) { | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (compat) | if (compat && SV_PROC_FLAG(td->td_proc, SV_AOUT)) | ||||
((struct osockaddr *)sa)->sa_family = sa->sa_family; | ((struct osockaddr *)sa)->sa_family = sa->sa_family; | ||||
#endif | #endif | ||||
error = copyout(sa, uap->asa, (u_int)len); | error = copyout(sa, uap->asa, (u_int)len); | ||||
} | } | ||||
free(sa, M_SONAME); | free(sa, M_SONAME); | ||||
if (error == 0) | if (error == 0) | ||||
error = copyout(&len, uap->alen, sizeof(len)); | error = copyout(&len, uap->alen, sizeof(len)); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | if (error != 0) | ||||
return (error); | return (error); | ||||
error = kern_getpeername(td, uap->fdes, &sa, &len); | error = kern_getpeername(td, uap->fdes, &sa, &len); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
if (len != 0) { | if (len != 0) { | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (compat) | if (compat && SV_PROC_FLAG(td->td_proc, SV_AOUT)) | ||||
((struct osockaddr *)sa)->sa_family = sa->sa_family; | ((struct osockaddr *)sa)->sa_family = sa->sa_family; | ||||
#endif | #endif | ||||
error = copyout(sa, uap->asa, (u_int)len); | error = copyout(sa, uap->asa, (u_int)len); | ||||
} | } | ||||
free(sa, M_SONAME); | free(sa, M_SONAME); | ||||
if (error == 0) | if (error == 0) | ||||
error = copyout(&len, uap->alen, sizeof(len)); | error = copyout(&len, uap->alen, sizeof(len)); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
sockargs(struct mbuf **mp, char *buf, socklen_t buflen, int type) | sockargs(struct mbuf **mp, char *buf, socklen_t buflen, int type) | ||||
{ | { | ||||
struct sockaddr *sa; | struct sockaddr *sa; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
int error; | int error; | ||||
if (buflen > MLEN) { | if (buflen > MLEN) { | ||||
#ifdef COMPAT_OLDSOCK | #ifdef COMPAT_OLDSOCK | ||||
if (type == MT_SONAME && buflen <= 112) | if (type == MT_SONAME && buflen <= 112 && | ||||
SV_CURPROC_FLAG(SV_AOUT)) | |||||
buflen = MLEN; /* unix domain compat. hack */ | buflen = MLEN; /* unix domain compat. hack */ | ||||
else | else | ||||
#endif | #endif | ||||
if (buflen > MCLBYTES) | if (buflen > MCLBYTES) | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
m = m_get2(buflen, M_WAITOK, type, 0); | m = m_get2(buflen, M_WAITOK, type, 0); | ||||
m->m_len = buflen; | m->m_len = buflen; | ||||
error = copyin(buf, mtod(m, void *), buflen); | error = copyin(buf, mtod(m, void *), buflen); | ||||
if (error != 0) | if (error != 0) | ||||
(void) m_free(m); | (void) m_free(m); | ||||
else { | else { | ||||
*mp = m; | *mp = m; | ||||
if (type == MT_SONAME) { | if (type == MT_SONAME) { | ||||
sa = mtod(m, struct sockaddr *); | sa = mtod(m, struct sockaddr *); | ||||
#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 && | ||||
SV_CURPROC_FLAG(SV_AOUT)) | |||||
sa->sa_family = sa->sa_len; | sa->sa_family = sa->sa_len; | ||||
#endif | #endif | ||||
sa->sa_len = buflen; | sa->sa_len = buflen; | ||||
} | } | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr, size_t len) | getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr, size_t len) | ||||
{ | { | ||||
struct sockaddr *sa; | struct sockaddr *sa; | ||||
int error; | int error; | ||||
if (len > SOCK_MAXADDRLEN) | if (len > SOCK_MAXADDRLEN) | ||||
return (ENAMETOOLONG); | return (ENAMETOOLONG); | ||||
if (len < offsetof(struct sockaddr, sa_data[0])) | if (len < offsetof(struct sockaddr, sa_data[0])) | ||||
return (EINVAL); | return (EINVAL); | ||||
sa = malloc(len, M_SONAME, M_WAITOK); | sa = malloc(len, M_SONAME, M_WAITOK); | ||||
error = copyin(uaddr, sa, len); | error = copyin(uaddr, sa, len); | ||||
if (error != 0) { | if (error != 0) { | ||||
free(sa, M_SONAME); | free(sa, M_SONAME); | ||||
} else { | } else { | ||||
#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 && | ||||
SV_CURPROC_FLAG(SV_AOUT)) | |||||
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); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 49 Lines • Show Last 20 Lines |