Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/uipc_syscalls.c
Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | static int getsockname1(struct thread *td, struct getsockname_args *uap, | ||||
int compat); | int compat); | ||||
static int getpeername1(struct thread *td, struct getpeername_args *uap, | static int getpeername1(struct thread *td, struct getpeername_args *uap, | ||||
int compat); | int compat); | ||||
static int sockargs(struct mbuf **, char *, socklen_t, int); | static int sockargs(struct mbuf **, char *, socklen_t, int); | ||||
/* | /* | ||||
* Convert a user file descriptor to a kernel file entry and check if required | * Convert a user file descriptor to a kernel file entry and check if required | ||||
* capability rights are present. | * capability rights are present. | ||||
* If required copy of current set of capability rights is returned. | |||||
* A reference on the file entry is held upon returning. | * A reference on the file entry is held upon returning. | ||||
*/ | */ | ||||
int | int | ||||
getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, | getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, | ||||
struct file **fpp, u_int *fflagp) | struct file **fpp, u_int *fflagp, struct filecaps *havecapsp) | ||||
{ | { | ||||
struct file *fp; | struct file *fp; | ||||
int error; | int error; | ||||
error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp, NULL); | error = fget_cap(td, fd, rightsp, &fp, havecapsp); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
if (fp->f_type != DTYPE_SOCKET) { | if (fp->f_type != DTYPE_SOCKET) { | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
if (havecapsp != NULL) | |||||
filecaps_free(havecapsp); | |||||
return (ENOTSOCK); | return (ENOTSOCK); | ||||
} | } | ||||
if (fflagp != NULL) | if (fflagp != NULL) | ||||
*fflagp = fp->f_flag; | *fflagp = fp->f_flag; | ||||
*fpp = fp; | *fpp = fp; | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) | ||||
struct socket *so; | struct socket *so; | ||||
struct file *fp; | struct file *fp; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
int error; | int error; | ||||
AUDIT_ARG_FD(fd); | AUDIT_ARG_FD(fd); | ||||
AUDIT_ARG_SOCKADDR(td, dirfd, sa); | AUDIT_ARG_SOCKADDR(td, dirfd, sa); | ||||
error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND), | error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND), | ||||
&fp, NULL); | &fp, NULL, NULL); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
so = fp->f_data; | so = fp->f_data; | ||||
#ifdef KTRACE | #ifdef KTRACE | ||||
if (KTRPOINT(td, KTR_STRUCT)) | if (KTRPOINT(td, KTR_STRUCT)) | ||||
ktrsockaddr(sa); | ktrsockaddr(sa); | ||||
#endif | #endif | ||||
#ifdef MAC | #ifdef MAC | ||||
Show All 30 Lines | |||||
{ | { | ||||
struct socket *so; | struct socket *so; | ||||
struct file *fp; | struct file *fp; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
int error; | int error; | ||||
AUDIT_ARG_FD(uap->s); | AUDIT_ARG_FD(uap->s); | ||||
error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_LISTEN), | error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_LISTEN), | ||||
&fp, NULL); | &fp, NULL, NULL); | ||||
if (error == 0) { | if (error == 0) { | ||||
so = fp->f_data; | so = fp->f_data; | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_socket_check_listen(td->td_ucred, so); | error = mac_socket_check_listen(td->td_ucred, so); | ||||
if (error == 0) | if (error == 0) | ||||
#endif | #endif | ||||
error = solisten(so, uap->backlog, td); | error = solisten(so, uap->backlog, td); | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
kern_accept4(struct thread *td, int s, struct sockaddr **name, | kern_accept4(struct thread *td, int s, struct sockaddr **name, | ||||
socklen_t *namelen, int flags, struct file **fp) | socklen_t *namelen, int flags, struct file **fp) | ||||
{ | { | ||||
struct file *headfp, *nfp = NULL; | struct file *headfp, *nfp = NULL; | ||||
struct sockaddr *sa = NULL; | struct sockaddr *sa = NULL; | ||||
struct socket *head, *so; | struct socket *head, *so; | ||||
struct filecaps fcaps; | |||||
cap_rights_t rights; | cap_rights_t rights; | ||||
u_int fflag; | u_int fflag; | ||||
pid_t pgid; | pid_t pgid; | ||||
int error, fd, tmp; | int error, fd, tmp; | ||||
if (name != NULL) | if (name != NULL) | ||||
*name = NULL; | *name = NULL; | ||||
AUDIT_ARG_FD(s); | AUDIT_ARG_FD(s); | ||||
error = getsock_cap(td, s, cap_rights_init(&rights, CAP_ACCEPT), | error = getsock_cap(td, s, cap_rights_init(&rights, CAP_ACCEPT), | ||||
&headfp, &fflag); | &headfp, &fflag, &fcaps); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
head = headfp->f_data; | head = headfp->f_data; | ||||
if ((head->so_options & SO_ACCEPTCONN) == 0) { | if ((head->so_options & SO_ACCEPTCONN) == 0) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto done; | goto done; | ||||
} | } | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_socket_check_accept(td->td_ucred, head); | error = mac_socket_check_accept(td->td_ucred, head); | ||||
if (error != 0) | if (error != 0) | ||||
goto done; | goto done; | ||||
#endif | #endif | ||||
error = falloc(td, &nfp, &fd, (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0); | error = falloc_caps(td, &nfp, &fd, | ||||
(flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0, &fcaps); | |||||
if (error != 0) | if (error != 0) | ||||
goto done; | goto done; | ||||
ACCEPT_LOCK(); | ACCEPT_LOCK(); | ||||
if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) { | if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) { | ||||
ACCEPT_UNLOCK(); | ACCEPT_UNLOCK(); | ||||
error = EWOULDBLOCK; | error = EWOULDBLOCK; | ||||
goto noconnection; | goto noconnection; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | noconnection: | ||||
if (error != 0) | if (error != 0) | ||||
fdclose(td, nfp, fd); | fdclose(td, nfp, fd); | ||||
/* | /* | ||||
* Release explicitly held references before returning. We return | * Release explicitly held references before returning. We return | ||||
* a reference on nfp to the caller on success if they request it. | * a reference on nfp to the caller on success if they request it. | ||||
*/ | */ | ||||
done: | done: | ||||
if (nfp == NULL) | |||||
filecaps_free(&fcaps); | |||||
if (fp != NULL) { | if (fp != NULL) { | ||||
if (error == 0) { | if (error == 0) { | ||||
*fp = nfp; | *fp = nfp; | ||||
nfp = NULL; | nfp = NULL; | ||||
} else | } else | ||||
*fp = NULL; | *fp = NULL; | ||||
} | } | ||||
if (nfp != NULL) | if (nfp != NULL) | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) | ||||
struct socket *so; | struct socket *so; | ||||
struct file *fp; | struct file *fp; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
int error, interrupted = 0; | int error, interrupted = 0; | ||||
AUDIT_ARG_FD(fd); | AUDIT_ARG_FD(fd); | ||||
AUDIT_ARG_SOCKADDR(td, dirfd, sa); | AUDIT_ARG_SOCKADDR(td, dirfd, sa); | ||||
error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT), | error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT), | ||||
&fp, NULL); | &fp, NULL, NULL); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
so = fp->f_data; | so = fp->f_data; | ||||
if (so->so_state & SS_ISCONNECTING) { | if (so->so_state & SS_ISCONNECTING) { | ||||
error = EALREADY; | error = EALREADY; | ||||
goto done1; | goto done1; | ||||
} | } | ||||
#ifdef KTRACE | #ifdef KTRACE | ||||
▲ Show 20 Lines • Show All 226 Lines • ▼ Show 20 Lines | #endif | ||||
int i, error; | int i, error; | ||||
AUDIT_ARG_FD(s); | AUDIT_ARG_FD(s); | ||||
cap_rights_init(&rights, CAP_SEND); | cap_rights_init(&rights, CAP_SEND); | ||||
if (mp->msg_name != NULL) { | if (mp->msg_name != NULL) { | ||||
AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name); | AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name); | ||||
cap_rights_set(&rights, CAP_CONNECT); | cap_rights_set(&rights, CAP_CONNECT); | ||||
} | } | ||||
error = getsock_cap(td, s, &rights, &fp, NULL); | error = getsock_cap(td, s, &rights, &fp, NULL, NULL); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
so = (struct socket *)fp->f_data; | so = (struct socket *)fp->f_data; | ||||
#ifdef KTRACE | #ifdef KTRACE | ||||
if (mp->msg_name != NULL && KTRPOINT(td, KTR_STRUCT)) | if (mp->msg_name != NULL && KTRPOINT(td, KTR_STRUCT)) | ||||
ktrsockaddr(mp->msg_name); | ktrsockaddr(mp->msg_name); | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | #endif | ||||
ssize_t len; | ssize_t len; | ||||
int error, i; | int error, i; | ||||
if (controlp != NULL) | if (controlp != NULL) | ||||
*controlp = NULL; | *controlp = NULL; | ||||
AUDIT_ARG_FD(s); | AUDIT_ARG_FD(s); | ||||
error = getsock_cap(td, s, cap_rights_init(&rights, CAP_RECV), | error = getsock_cap(td, s, cap_rights_init(&rights, CAP_RECV), | ||||
&fp, NULL); | &fp, NULL, NULL); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
so = fp->f_data; | so = fp->f_data; | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_socket_check_receive(td->td_ucred, so); | error = mac_socket_check_receive(td->td_ucred, so); | ||||
if (error != 0) { | if (error != 0) { | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct socket *so; | struct socket *so; | ||||
struct file *fp; | struct file *fp; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
int error; | int error; | ||||
AUDIT_ARG_FD(uap->s); | AUDIT_ARG_FD(uap->s); | ||||
error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_SHUTDOWN), | error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_SHUTDOWN), | ||||
&fp, NULL); | &fp, NULL, NULL); | ||||
if (error == 0) { | if (error == 0) { | ||||
so = fp->f_data; | so = fp->f_data; | ||||
error = soshutdown(so, uap->how); | error = soshutdown(so, uap->how); | ||||
/* | /* | ||||
* Previous versions did not return ENOTCONN, but 0 in | * Previous versions did not return ENOTCONN, but 0 in | ||||
* case the socket was not connected. Some important | * case the socket was not connected. Some important | ||||
* programs like syslogd up to r279016, 2015-02-19, | * programs like syslogd up to r279016, 2015-02-19, | ||||
* still depend on this behavior. | * still depend on this behavior. | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | case UIO_SYSSPACE: | ||||
sopt.sopt_td = NULL; | sopt.sopt_td = NULL; | ||||
break; | break; | ||||
default: | default: | ||||
panic("kern_setsockopt called with bad valseg"); | panic("kern_setsockopt called with bad valseg"); | ||||
} | } | ||||
AUDIT_ARG_FD(s); | AUDIT_ARG_FD(s); | ||||
error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SETSOCKOPT), | error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SETSOCKOPT), | ||||
&fp, NULL); | &fp, NULL, NULL); | ||||
if (error == 0) { | if (error == 0) { | ||||
so = fp->f_data; | so = fp->f_data; | ||||
error = sosetopt(so, &sopt); | error = sosetopt(so, &sopt); | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
} | } | ||||
return(error); | return(error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | case UIO_SYSSPACE: | ||||
sopt.sopt_td = NULL; | sopt.sopt_td = NULL; | ||||
break; | break; | ||||
default: | default: | ||||
panic("kern_getsockopt called with bad valseg"); | panic("kern_getsockopt called with bad valseg"); | ||||
} | } | ||||
AUDIT_ARG_FD(s); | AUDIT_ARG_FD(s); | ||||
error = getsock_cap(td, s, cap_rights_init(&rights, CAP_GETSOCKOPT), | error = getsock_cap(td, s, cap_rights_init(&rights, CAP_GETSOCKOPT), | ||||
&fp, NULL); | &fp, NULL, NULL); | ||||
if (error == 0) { | if (error == 0) { | ||||
so = fp->f_data; | so = fp->f_data; | ||||
error = sogetopt(so, &sopt); | error = sogetopt(so, &sopt); | ||||
*valsize = sopt.sopt_valsize; | *valsize = sopt.sopt_valsize; | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
Show All 36 Lines | kern_getsockname(struct thread *td, int fd, struct sockaddr **sa, | ||||
struct socket *so; | struct socket *so; | ||||
struct file *fp; | struct file *fp; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
socklen_t len; | socklen_t len; | ||||
int error; | int error; | ||||
AUDIT_ARG_FD(fd); | AUDIT_ARG_FD(fd); | ||||
error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETSOCKNAME), | error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETSOCKNAME), | ||||
&fp, NULL); | &fp, NULL, NULL); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
so = fp->f_data; | so = fp->f_data; | ||||
*sa = NULL; | *sa = NULL; | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa); | error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
if (error != 0) | if (error != 0) | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | kern_getpeername(struct thread *td, int fd, struct sockaddr **sa, | ||||
struct socket *so; | struct socket *so; | ||||
struct file *fp; | struct file *fp; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
socklen_t len; | socklen_t len; | ||||
int error; | int error; | ||||
AUDIT_ARG_FD(fd); | AUDIT_ARG_FD(fd); | ||||
error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETPEERNAME), | error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETPEERNAME), | ||||
&fp, NULL); | &fp, NULL, NULL); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
so = fp->f_data; | so = fp->f_data; | ||||
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { | if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { | ||||
error = ENOTCONN; | error = ENOTCONN; | ||||
goto done; | goto done; | ||||
} | } | ||||
*sa = NULL; | *sa = NULL; | ||||
▲ Show 20 Lines • Show All 101 Lines • Show Last 20 Lines |