Date: Fri, 6 Sep 2013 12:45:09 +0000 (UTC) From: Jilles Tjoelker <jilles@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r255299 - stable/9/sys/kern Message-ID: <201309061245.r86Cj9jA071731@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jilles Date: Fri Sep 6 12:45:08 2013 New Revision: 255299 URL: http://svnweb.freebsd.org/changeset/base/255299 Log: Partial MFC of r248534: Implement SOCK_CLOEXEC and SOCK_NONBLOCK in kernel. SOCK_CLOEXEC and SOCK_NONBLOCK can be OR'ed in socket() and socketpair()'s type parameter. The numerical values for SOCK_CLOEXEC and SOCK_NONBLOCK are as in NetBSD. The SOCK_* flags are not passed to MAC because this may cause incorrect failures and can be done later via fcntl() anyway. On the other hand, audit is expected to cope with the new flags. This commit does not add the constants to <sys/socket.h> as in r248534 because this would lead to various newly compiled software not working on old kernels. It only serves to help 10.x binaries and prepare for a possible full MFC (if third-party software starts to insist on SOCK_CLOEXEC and SOCK_NONBLOCK). MSG_CMSG_CLOEXEC from r248534 is not merged here because it changes a KPI/KBI. No mergeinfo because the rest of r248534 is missing. Modified: stable/9/sys/kern/uipc_syscalls.c Modified: stable/9/sys/kern/uipc_syscalls.c ============================================================================== --- stable/9/sys/kern/uipc_syscalls.c Fri Sep 6 10:40:38 2013 (r255298) +++ stable/9/sys/kern/uipc_syscalls.c Fri Sep 6 12:45:08 2013 (r255299) @@ -96,6 +96,13 @@ __FBSDID("$FreeBSD$"); #endif /* SCTP */ #endif /* INET || INET6 */ +/* + * Creation flags, OR'ed into socket() and socketpair() type argument. + * For stable/9, these are supported but not exposed in the header file. + */ +#define SOCK_CLOEXEC 0x10000000 +#define SOCK_NONBLOCK 0x20000000 + static int sendit(struct thread *td, int s, struct msghdr *mp, int flags); static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp); @@ -183,26 +190,41 @@ sys_socket(td, uap) struct filedesc *fdp; 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 fdp = td->td_proc->p_fd; - 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(fdp, 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); @@ -606,9 +628,20 @@ kern_socketpair(struct thread *td, int d 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, @@ -623,12 +656,12 @@ kern_socketpair(struct thread *td, int d 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 */ @@ -644,8 +677,14 @@ kern_socketpair(struct thread *td, int d 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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201309061245.r86Cj9jA071731>