diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/uipc_socket.c | 4 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 52 | ||||
-rw-r--r-- | sys/kern/uipc_usrreq.c | 6 | ||||
-rw-r--r-- | sys/sys/domain.h | 2 | ||||
-rw-r--r-- | sys/sys/socket.h | 9 |
5 files changed, 58 insertions, 15 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index aa5448c..bce61e5 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1727,7 +1727,7 @@ dontblock: SOCKBUF_UNLOCK(&so->so_rcv); VNET_SO_ASSERT(so); error = (*pr->pr_domain->dom_externalize) - (cm, controlp); + (cm, controlp, flags); SOCKBUF_LOCK(&so->so_rcv); } else if (controlp != NULL) *controlp = cm; @@ -2361,7 +2361,7 @@ soreceive_dgram(struct socket *so, struct sockaddr **psa, struct uio *uio, cm->m_next = NULL; if (pr->pr_domain->dom_externalize != NULL) { error = (*pr->pr_domain->dom_externalize) - (cm, controlp); + (cm, controlp, flags); } else if (controlp != NULL) *controlp = cm; else diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 3a2f032..42a1ff1 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -164,25 +164,40 @@ sys_socket(td, uap) { struct socket *so; struct file *fp; - int fd, error; + int fd, error, type, oflag, fflag; AUDIT_ARG_SOCKET(uap->domain, uap->type, uap->protocol); + + type = uap->type; + oflag = 0; + fflag = 0; + if ((type & SOCK_CLOEXEC) != 0) { + type &= ~SOCK_CLOEXEC; + oflag |= O_CLOEXEC; + } + if ((type & SOCK_NONBLOCK) != 0) { + type &= ~SOCK_NONBLOCK; + fflag |= FNONBLOCK; + } + #ifdef MAC - error = mac_socket_check_create(td->td_ucred, uap->domain, uap->type, + error = mac_socket_check_create(td->td_ucred, uap->domain, type, uap->protocol); if (error) return (error); #endif - error = falloc(td, &fp, &fd, 0); + error = falloc(td, &fp, &fd, oflag); if (error) return (error); /* An extra reference on `fp' has been held for us by falloc(). */ - error = socreate(uap->domain, &so, uap->type, uap->protocol, + error = socreate(uap->domain, &so, type, uap->protocol, td->td_ucred, td); if (error) { fdclose(td->td_proc->p_fd, fp, fd, td); } else { - finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, &socketops); + finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops); + if ((fflag & FNONBLOCK) != 0) + (void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td); td->td_retval[0] = fd; } fdrop(fp, td); @@ -648,9 +663,20 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol, struct filedesc *fdp = td->td_proc->p_fd; struct file *fp1, *fp2; struct socket *so1, *so2; - int fd, error; + int fd, error, oflag, fflag; AUDIT_ARG_SOCKET(domain, type, protocol); + + oflag = 0; + fflag = 0; + if ((type & SOCK_CLOEXEC) != 0) { + type &= ~SOCK_CLOEXEC; + oflag |= O_CLOEXEC; + } + if ((type & SOCK_NONBLOCK) != 0) { + type &= ~SOCK_NONBLOCK; + fflag |= FNONBLOCK; + } #ifdef MAC /* We might want to have a separate check for socket pairs. */ error = mac_socket_check_create(td->td_ucred, domain, type, @@ -665,12 +691,12 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol, if (error) goto free1; /* On success extra reference to `fp1' and 'fp2' is set by falloc. */ - error = falloc(td, &fp1, &fd, 0); + error = falloc(td, &fp1, &fd, oflag); if (error) goto free2; rsv[0] = fd; fp1->f_data = so1; /* so1 already has ref count */ - error = falloc(td, &fp2, &fd, 0); + error = falloc(td, &fp2, &fd, oflag); if (error) goto free3; fp2->f_data = so2; /* so2 already has ref count */ @@ -686,8 +712,14 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol, if (error) goto free4; } - finit(fp1, FREAD | FWRITE, DTYPE_SOCKET, fp1->f_data, &socketops); - finit(fp2, FREAD | FWRITE, DTYPE_SOCKET, fp2->f_data, &socketops); + finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data, + &socketops); + finit(fp2, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp2->f_data, + &socketops); + if ((fflag & FNONBLOCK) != 0) { + (void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td); + (void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td); + } fdrop(fp1, td); fdrop(fp2, td); return (0); diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 2ec83c5..9b60eab 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -288,7 +288,7 @@ static void unp_freerights(struct filedescent **, int); static void unp_init(void); static int unp_internalize(struct mbuf **, struct thread *); static void unp_internalize_fp(struct file *); -static int unp_externalize(struct mbuf *, struct mbuf **); +static int unp_externalize(struct mbuf *, struct mbuf **, int); static int unp_externalize_fp(struct file *); static struct mbuf *unp_addsockcred(struct thread *, struct mbuf *); static void unp_process_defers(void * __unused, int); @@ -1695,7 +1695,7 @@ unp_freerights(struct filedescent **fdep, int fdcount) } static int -unp_externalize(struct mbuf *control, struct mbuf **controlp) +unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags) { struct thread *td = curthread; /* XXX */ struct cmsghdr *cm = mtod(control, struct cmsghdr *); @@ -1765,6 +1765,8 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp) fde->fde_file = fdep[0]->fde_file; filecaps_move(&fdep[0]->fde_caps, &fde->fde_caps); + if ((flags & MSG_CMSG_CLOEXEC) != 0) + fde->fde_flags |= UF_EXCLOSE; unp_externalize_fp(fde->fde_file); *fdp = f; } diff --git a/sys/sys/domain.h b/sys/sys/domain.h index 2563cb6..30e4249 100644 --- a/sys/sys/domain.h +++ b/sys/sys/domain.h @@ -51,7 +51,7 @@ struct domain { void (*dom_destroy) /* cleanup structures / state */ (void); int (*dom_externalize) /* externalize access rights */ - (struct mbuf *, struct mbuf **); + (struct mbuf *, struct mbuf **, int); void (*dom_dispose) /* dispose of internalized rights */ (struct mbuf *); struct protosw *dom_protosw, *dom_protoswNPROTOSW; diff --git a/sys/sys/socket.h b/sys/sys/socket.h index 632dae4..56101b7 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -95,6 +95,14 @@ typedef __uid_t uid_t; #endif #define SOCK_SEQPACKET 5 /* sequenced packet stream */ +#if __BSD_VISIBLE +/* + * Creation flags, OR'ed into socket() and socketpair() type argument. + */ +#define SOCK_CLOEXEC 0x10000000 +#define SOCK_NONBLOCK 0x20000000 +#endif + /* * Option flags per-socket. */ @@ -459,6 +467,7 @@ struct msghdr { #endif #if __BSD_VISIBLE #define MSG_NOSIGNAL 0x20000 /* do not generate SIGPIPE on EOF */ +#define MSG_CMSG_CLOEXEC 0x40000 /* make received fds close-on-exec */ #endif /* |