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 | |||||