diff options
author | 2014-08-31 01:42:36 +0000 | |
---|---|---|
committer | 2014-08-31 01:42:36 +0000 | |
commit | b65639bd219b95b988677e8920af7a5b157bf154 (patch) | |
tree | 95e750bdd8bd7c588849acf13e4b9cb25704c49f | |
parent | Finally ``revert'' to the recent pexecute interface, now that we do not need (diff) | |
download | wireguard-openbsd-b65639bd219b95b988677e8920af7a5b157bf154.tar.xz wireguard-openbsd-b65639bd219b95b988677e8920af7a5b157bf154.zip |
Add additional kernel interfaces for setting close-on-exec on fds
when creating them: pipe2(), dup3(), accept4(), MSG_CMSG_CLOEXEC,
SOCK_CLOEXEC. Includes SOCK_NONBLOCK support.
ok matthew@
-rw-r--r-- | include/unistd.h | 7 | ||||
-rw-r--r-- | lib/libc/gen/signal.3 | 8 | ||||
-rw-r--r-- | lib/libc/shlib_version | 2 | ||||
-rw-r--r-- | lib/libc/sys/Makefile.inc | 12 | ||||
-rw-r--r-- | lib/libc/sys/accept.2 | 51 | ||||
-rw-r--r-- | lib/libc/sys/dup.2 | 68 | ||||
-rw-r--r-- | lib/libc/sys/pipe.2 | 50 | ||||
-rw-r--r-- | lib/libc/sys/recv.2 | 17 | ||||
-rw-r--r-- | lib/libc/sys/sigaction.2 | 8 | ||||
-rw-r--r-- | lib/libc/sys/socket.2 | 19 | ||||
-rw-r--r-- | lib/libc/sys/socketpair.2 | 17 | ||||
-rw-r--r-- | sys/kern/kern_descrip.c | 31 | ||||
-rw-r--r-- | sys/kern/sys_pipe.c | 36 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 9 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 4 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 114 | ||||
-rw-r--r-- | sys/kern/uipc_usrreq.c | 7 | ||||
-rw-r--r-- | sys/sys/domain.h | 4 | ||||
-rw-r--r-- | sys/sys/socket.h | 40 | ||||
-rw-r--r-- | sys/sys/un.h | 4 |
20 files changed, 399 insertions, 109 deletions
diff --git a/include/unistd.h b/include/unistd.h index a2aab2d9875..a86998768e0 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: unistd.h,v 1.89 2014/07/08 21:35:39 tedu Exp $ */ +/* $OpenBSD: unistd.h,v 1.90 2014/08/31 01:42:36 guenther Exp $ */ /* $NetBSD: unistd.h,v 1.26.4.1 1996/05/28 02:31:51 mrg Exp $ */ /*- @@ -485,6 +485,11 @@ int unlinkat(int, const char *, int); #endif #if __BSD_VISIBLE +int dup3(int, int, int); +int pipe2(int [2], int); +#endif + +#if __BSD_VISIBLE int acct(const char *); int closefrom(int); int des_cipher(const char *, char *, int32_t, int); diff --git a/lib/libc/gen/signal.3 b/lib/libc/gen/signal.3 index c5abe822b26..ec3b7baabdf 100644 --- a/lib/libc/gen/signal.3 +++ b/lib/libc/gen/signal.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: signal.3,v 1.48 2014/07/21 23:05:12 matthew Exp $ +.\" $OpenBSD: signal.3,v 1.49 2014/08/31 01:42:36 guenther Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: July 21 2014 $ +.Dd $Mdocdate: August 31 2014 $ .Dt SIGNAL 3 .Os .Sh NAME @@ -400,12 +400,16 @@ and perhaps some others. .Pp Extension Interfaces: .Pp +.Fn accept4 , .Fn chflags , +.Fn dup3 , .Fn fchflags , .Fn getentropy , .Fn getresgid , .Fn getresuid , +.Fn pipe2 , .Fn ppoll , +.Fn sendsyslog , .Fn setresgid , .Fn setresuid , .Fn strlcat , diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version index de48abcf271..2402feed036 100644 --- a/lib/libc/shlib_version +++ b/lib/libc/shlib_version @@ -1,4 +1,4 @@ major=77 -minor=0 +minor=1 # note: If changes were made to include/thread_private.h or if system # calls were added/changed then librthread/shlib_version also be updated. diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index a93eb967e32..0fbb0bda402 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.120 2014/08/14 17:55:28 tobias Exp $ +# $OpenBSD: Makefile.inc,v 1.121 2014/08/31 01:42:36 guenther Exp $ # $NetBSD: Makefile.inc,v 1.35 1995/10/16 23:49:07 jtc Exp $ # @(#)Makefile.inc 8.1 (Berkeley) 6/17/93 @@ -26,10 +26,10 @@ SRCS+= stack_protector.c # below: ASM= __get_tcb.o __getcwd.o __semctl.o __set_tcb.o __syscall.o \ __sysctl.o __threxit.o __thrsigdivert.o __thrsleep.o \ - __thrwakeup.o accept.o access.o acct.o adjfreq.o adjtime.o \ + __thrwakeup.o accept.o accept4.o access.o acct.o adjfreq.o adjtime.o \ bind.o chdir.o chflags.o chmod.o chown.o chroot.o \ clock_getres.o clock_gettime.o clock_settime.o close.o \ - closefrom.o connect.o dup.o dup2.o execve.o faccessat.o \ + closefrom.o connect.o dup.o dup2.o dup3.o execve.o faccessat.o \ fchdir.o fchflags.o fchmod.o fchmodat.o fchown.o \ fchownat.o fcntl.o fhopen.o fhstat.o fhstatfs.o \ flock.o fpathconf.o fstat.o fstatat.o fstatfs.o \ @@ -45,7 +45,8 @@ ASM= __get_tcb.o __getcwd.o __semctl.o __set_tcb.o __syscall.o \ mknod.o mknodat.o mlock.o mlockall.o mount.o mprotect.o \ msgctl.o msgget.o msgrcv.o msgsnd.o msync.o munlock.o \ munlockall.o munmap.o nanosleep.o nfssvc.o \ - open.o openat.o pathconf.o pipe.o poll.o ppoll.o profil.o pselect.o \ + open.o openat.o pathconf.o pipe.o pipe2.o \ + poll.o ppoll.o profil.o pselect.o \ quotactl.o read.o readlink.o readlinkat.o readv.o reboot.o \ recvfrom.o recvmsg.o rename.o renameat.o revoke.o rmdir.o \ sched_yield.o select.o semget.o semop.o sendmsg.o sendsyslog.o sendto.o \ @@ -223,6 +224,7 @@ MAN+= __get_tcb.2 __thrsigdivert.2 __thrsleep.2 _exit.2 accept.2 \ MLINKS+=__get_tcb.2 __set_tcb.2 MLINKS+=__thrsleep.2 __thrwakeup.2 MLINKS+=_exit.2 _Exit.2 +MLINKS+=accept.2 accept4.2 MLINKS+=access.2 faccessat.2 MLINKS+=brk.2 sbrk.2 MLINKS+=chdir.2 fchdir.2 @@ -232,6 +234,7 @@ MLINKS+=chown.2 fchown.2 chown.2 fchownat.2 chown.2 lchown.2 MLINKS+=clock_gettime.2 clock_getres.2 MLINKS+=clock_gettime.2 clock_settime.2 MLINKS+=dup.2 dup2.2 +MLINKS+=dup.2 dup3.2 MLINKS+=execve.2 exect.2 MLINKS+=fhopen.2 fhstat.2 fhopen.2 fhstatfs.2 MLINKS+=fsync.2 fdatasync.2 @@ -263,6 +266,7 @@ MLINKS+=mlockall.2 munlockall.2 MLINKS+=mount.2 unmount.2 MLINKS+=open.2 openat.2 MLINKS+=pathconf.2 fpathconf.2 +MLINKS+=pipe.2 pipe2.2 MLINKS+=poll.2 ppoll.2 MLINKS+=read.2 readv.2 read.2 pread.2 read.2 preadv.2 MLINKS+=readlink.2 readlinkat.2 diff --git a/lib/libc/sys/accept.2 b/lib/libc/sys/accept.2 index e600414c3db..e043f79bd63 100644 --- a/lib/libc/sys/accept.2 +++ b/lib/libc/sys/accept.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: accept.2,v 1.26 2013/07/17 05:42:11 schwarze Exp $ +.\" $OpenBSD: accept.2,v 1.27 2014/08/31 01:42:36 guenther Exp $ .\" $NetBSD: accept.2,v 1.7 1996/01/31 20:14:42 mycroft Exp $ .\" .\" Copyright (c) 1983, 1990, 1991, 1993 @@ -30,16 +30,19 @@ .\" .\" @(#)accept.2 8.2 (Berkeley) 12/11/93 .\" -.Dd $Mdocdate: July 17 2013 $ +.Dd $Mdocdate: August 31 2014 $ .Dt ACCEPT 2 .Os .Sh NAME -.Nm accept +.Nm accept , +.Nm accept4 .Nd accept a connection on a socket .Sh SYNOPSIS -.Fd #include <sys/socket.h> +.In sys/socket.h .Ft int .Fn accept "int s" "struct sockaddr *addr" "socklen_t *addrlen" +.Ft int +.Fn accept4 "int s" "struct sockaddr *addr" "socklen_t *addrlen" "int flags" .Sh DESCRIPTION The argument .Fa s @@ -52,9 +55,25 @@ and is listening for connections after a The .Fn accept call extracts the first connection request on the queue of pending -connections, creates a new socket with the same properties of +connections, creates a new socket with the same non-blocking I/O mode as .Fa s , -and allocates a new file descriptor for the socket. +and allocates a new file descriptor for the socket with the +close-on-exec flag clear. +.Pp +The +.Fn accept4 +system call is similar, however the non-blocking I/O mode of the +new socket is determined by the +.Dv SOCK_NONBLOCK +flag in the +.Fa flags +argument and the close-on-exec flag on the new file descriptor is +determined by the +.Dv SOCK_CLOEXEC +flag in the +.Fa flags +argument. +.Pp If no pending connections are present on the queue, and the socket is not marked as non-blocking, .Fn accept @@ -151,6 +170,8 @@ if (retcode == -1) .Ed .Sh ERRORS .Fn accept +and +.Fn accept4 will fail if: .Bl -tag -width Er .It Bq Er EBADF @@ -182,6 +203,15 @@ The system file table is full. .It Bq Er ECONNABORTED A connection has been aborted. .El +.Pp +In addition, +.Fn accept4 +will fail if +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa flags +is invalid. +.El .Sh SEE ALSO .Xr bind 2 , .Xr connect 2 , @@ -194,11 +224,18 @@ The .Fn accept function conforms to .St -p1003.1-2008 . +The +.Fn accept4 +function is expected to conform to a future revision of that standard. .Sh HISTORY The .Fn accept system call first appeared in -.Bx 4.1c . +.Bx 4.1c +and +.Fn accept4 +in +.Ox 5.7 . .Sh CAVEATS When .Er EMFILE diff --git a/lib/libc/sys/dup.2 b/lib/libc/sys/dup.2 index 463c6f0486f..a0e24d19c15 100644 --- a/lib/libc/sys/dup.2 +++ b/lib/libc/sys/dup.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: dup.2,v 1.16 2013/07/17 05:42:11 schwarze Exp $ +.\" $OpenBSD: dup.2,v 1.17 2014/08/31 01:42:36 guenther Exp $ .\" $NetBSD: dup.2,v 1.4 1995/02/27 12:32:21 cgd Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 @@ -30,19 +30,24 @@ .\" .\" @(#)dup.2 8.1 (Berkeley) 6/4/93 .\" -.Dd $Mdocdate: July 17 2013 $ +.Dd $Mdocdate: August 31 2014 $ .Dt DUP 2 .Os .Sh NAME .Nm dup , -.Nm dup2 +.Nm dup2 , +.Nm dup3 .Nd duplicate an existing file descriptor .Sh SYNOPSIS -.Fd #include <unistd.h> +.In unistd.h .Ft int .Fn dup "int oldd" .Ft int .Fn dup2 "int oldd" "int newd" +.In fcntl.h +.In unistd.h +.Ft int +.Fn dup3 "int oldd" "int newd" "int flags" .Sh DESCRIPTION .Fn dup duplicates an existing object descriptor and returns its value to @@ -97,6 +102,32 @@ equals .Fa oldd , .Fn dup2 just returns without affecting the close-on-exec flag. +.Pp +In +.Fn dup3 , +both the value of the new descriptor and the close-on-exec flag on +the new file descriptor are specified: +.Fa newd +specifies the value and the +.Dv O_CLOEXEC +bit in +.Fa flags +specifies the close-on-exec flag. +Unlike +.Fn dup2 , +if +.Fa oldd +and +.Fa newd +are equal then +.Fn dup3 +fails. +Otherwise, if +.Fa flags +is zero then +.Fn dup3 +is identical to a call to +.Fn dup2 . .Sh RETURN VALUES The value \-1 is returned if an error occurs in either call. The external variable @@ -114,6 +145,8 @@ Too many descriptors are active. .El .Pp .Fn dup2 +and +.Fn dup3 will fail if: .Bl -tag -width Er .It Bq Er EBADF @@ -128,6 +161,19 @@ An interrupt was received. .It Bq Er EIO An I/O error occurred while writing to the file system. .El +.Pp +In addition, +.Fn dup3 +will return the following error: +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa oldd +is equal to +.Fa newd +or +.Fa flags +is invalid. +.El .Sh SEE ALSO .Xr accept 2 , .Xr close 2 , @@ -142,14 +188,20 @@ An I/O error occurred while writing to the file system. .Fn dup and .Fn dup2 -are expected to conform to +conform to .St -p1003.1-2008 . +The +.Fn dup3 +function is expected to conform to a future revision of that standard. .Sh HISTORY The .Fn dup system call first appeared in -.At v3 -and +.At v3 , .Fn dup2 in -.At v7 . +.At v7 , +and +.Fn dup3 +in +.Ox 5.7 . diff --git a/lib/libc/sys/pipe.2 b/lib/libc/sys/pipe.2 index 825b19e8910..87608cd05cc 100644 --- a/lib/libc/sys/pipe.2 +++ b/lib/libc/sys/pipe.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pipe.2,v 1.16 2014/08/16 17:33:40 tobias Exp $ +.\" $OpenBSD: pipe.2,v 1.17 2014/08/31 01:42:36 guenther Exp $ .\" $NetBSD: pipe.2,v 1.6 1995/02/27 12:35:27 cgd Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 @@ -30,16 +30,21 @@ .\" .\" @(#)pipe.2 8.1 (Berkeley) 6/4/93 .\" -.Dd $Mdocdate: August 16 2014 $ +.Dd $Mdocdate: August 31 2014 $ .Dt PIPE 2 .Os .Sh NAME -.Nm pipe +.Nm pipe , +.Nm pipe2 .Nd create descriptor pair for interprocess communication .Sh SYNOPSIS -.Fd #include <unistd.h> +.In unistd.h .Ft int .Fn pipe "int fildes[2]" +.In fcntl.h +.In unistd.h +.Ft int +.Fn pipe2 "int fildes[2]" "int flags" .Sh DESCRIPTION The .Fn pipe @@ -69,15 +74,32 @@ signal. Widowing a pipe is the only way to deliver end-of-file to a reader: after the reader consumes any buffered data, reading a widowed pipe returns a zero count. +.Pp +The +.Fn pipe2 +function is identical to +.Fn pipe +except that the non-blocking I/O mode on both ends of the pipe is +determined by the +.Dv O_NONBLOCK +flag in the +.Fa flags +argument and the close-on-exec flag on both the new file descriptors +is determined by the +.Dv O_CLOEXEC +flag in the +.Fa flags +argument. .Sh RETURN VALUES On successful creation of the pipe, zero is returned. Otherwise, a value of \-1 is returned and the variable .Va errno set to indicate the error. .Sh ERRORS -The .Fn pipe -call will fail if: +and +.Fn pipe2 +will succeed unless: .Bl -tag -width Er .It Bq Er EMFILE Too many descriptors are active. @@ -88,6 +110,15 @@ The .Fa fildes buffer is in an invalid area of the process's address space. .El +.Pp +In addition, +.Fn pipe2 +may return the following error: +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa flags +is invalid. +.El .Sh SEE ALSO .Xr sh 1 , .Xr fork 2 , @@ -99,6 +130,9 @@ The .Fn pipe function conforms to .St -p1003.1-2008 . +The +.Fn pipe2 +function is expected to conform to a future revision of that standard. .Pp As an extension, the pipe provided is actually capable of moving data bidirectionally. @@ -113,3 +147,7 @@ function call appeared in Since .At v4 , it allocates two distinct file descriptors. +The +.Fn pipe2 +function appeared in +.Ox 5.7 . diff --git a/lib/libc/sys/recv.2 b/lib/libc/sys/recv.2 index 6b8f6b2d7dd..14fe706d196 100644 --- a/lib/libc/sys/recv.2 +++ b/lib/libc/sys/recv.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: recv.2,v 1.40 2014/02/13 07:30:39 guenther Exp $ +.\" $OpenBSD: recv.2,v 1.41 2014/08/31 01:42:36 guenther Exp $ .\" $NetBSD: recv.2,v 1.6 1995/02/27 12:36:08 cgd Exp $ .\" .\" Copyright (c) 1983, 1990, 1991, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)recv.2 8.3 (Berkeley) 2/21/94 .\" -.Dd $Mdocdate: February 13 2014 $ +.Dd $Mdocdate: August 31 2014 $ .Dt RECV 2 .Os .Sh NAME @@ -39,8 +39,7 @@ .Nm recvmsg .Nd receive a message from a socket .Sh SYNOPSIS -.Fd #include <sys/types.h> -.Fd #include <sys/socket.h> +.In sys/socket.h .Ft ssize_t .Fn recv "int s" "void *buf" "size_t len" "int flags" .Ft ssize_t @@ -116,7 +115,7 @@ The .Fa flags argument is the bitwise OR of zero or more of the following values: .Pp -.Bl -tag -width "MSG_DONTWAITXX" -offset indent -compact +.Bl -tag -width "MSG_CMSG_CLOEXECXX" -offset indent -compact .It Dv MSG_OOB process out-of-band data .It Dv MSG_PEEK @@ -125,6 +124,8 @@ peek at incoming message wait for full request or error .It Dv MSG_DONTWAIT don't block +.It Dv MSG_CMSG_CLOEXEC +set the close-on-exec flag on received file descriptors .El .Pp The @@ -154,6 +155,12 @@ If no data is available, is set to .Er EAGAIN . This flag is not available in strict ANSI or C99 compilation mode. +The +.Dv MSG_CMSG_CLOEXEC +requests that any file descriptors received as ancillary data with +.Fn recvmsg +(see below) +have their close-on-exec flag set. .Pp The .Fn recvmsg diff --git a/lib/libc/sys/sigaction.2 b/lib/libc/sys/sigaction.2 index 5304ce37b3b..5854d415586 100644 --- a/lib/libc/sys/sigaction.2 +++ b/lib/libc/sys/sigaction.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sigaction.2,v 1.60 2014/07/21 23:05:12 matthew Exp $ +.\" $OpenBSD: sigaction.2,v 1.61 2014/08/31 01:42:36 guenther Exp $ .\" $NetBSD: sigaction.2,v 1.7 1995/10/12 15:41:16 jtc Exp $ .\" .\" Copyright (c) 1980, 1990, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)sigaction.2 8.2 (Berkeley) 4/3/94 .\" -.Dd $Mdocdate: July 21 2014 $ +.Dd $Mdocdate: August 31 2014 $ .Dt SIGACTION 2 .Os .Sh NAME @@ -628,12 +628,16 @@ and perhaps some others. .Pp Extension Interfaces: .Pp +.Fn accept4 , .Fn chflags , +.Fn dup3 , .Fn fchflags , .Fn getentropy , .Fn getresgid , .Fn getresuid , +.Fn pipe2 , .Fn ppoll , +.Fn sendsyslog , .Fn setresgid , .Fn setresuid , .Fn strlcat , diff --git a/lib/libc/sys/socket.2 b/lib/libc/sys/socket.2 index d3703d44a93..10f48fe68a7 100644 --- a/lib/libc/sys/socket.2 +++ b/lib/libc/sys/socket.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: socket.2,v 1.37 2014/08/10 07:19:08 guenther Exp $ +.\" $OpenBSD: socket.2,v 1.38 2014/08/31 01:42:36 guenther Exp $ .\" $NetBSD: socket.2,v 1.5 1995/02/27 12:37:53 cgd Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 @@ -30,14 +30,14 @@ .\" .\" @(#)socket.2 8.1 (Berkeley) 6/4/93 .\" -.Dd $Mdocdate: August 10 2014 $ +.Dd $Mdocdate: August 31 2014 $ .Dt SOCKET 2 .Os .Sh NAME .Nm socket .Nd create an endpoint for communication .Sh SYNOPSIS -.Fd #include <sys/socket.h> +.In sys/socket.h .Ft int .Fn socket "int domain" "int type" "int protocol" .Sh DESCRIPTION @@ -90,12 +90,23 @@ socket may provide a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length; a consumer may be required to read an entire packet with each read system call. -This facility is protocol specific, and presently implemented for +This facility is protocol specific, and presently implemented only for .Dv AF_UNIX . .Dv SOCK_RAW sockets provide access to internal network protocols and interfaces, and are available only to the superuser. .Pp +Any combination of the following flags may additionally be used in the +.Fa type +argument: +.Pp +.Bl -tag -width "SOCK_NONBLOCKX" -offset indent -compact +.It SOCK_CLOEXEC +Set close-on-exec flag on the new descriptor. +.It SOCK_NONBLOCK +Set non-blocking I/O mode on the new socket. +.El +.Pp The .Fa protocol specifies a particular protocol to be used with the socket. diff --git a/lib/libc/sys/socketpair.2 b/lib/libc/sys/socketpair.2 index b4131ffea98..bd02dfe4c91 100644 --- a/lib/libc/sys/socketpair.2 +++ b/lib/libc/sys/socketpair.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: socketpair.2,v 1.15 2013/04/08 19:49:55 guenther Exp $ +.\" $OpenBSD: socketpair.2,v 1.16 2014/08/31 01:42:36 guenther Exp $ .\" $NetBSD: socketpair.2,v 1.5 1995/02/27 12:38:00 cgd Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 @@ -30,14 +30,14 @@ .\" .\" @(#)socketpair.2 8.1 (Berkeley) 6/4/93 .\" -.Dd $Mdocdate: April 8 2013 $ +.Dd $Mdocdate: August 31 2014 $ .Dt SOCKETPAIR 2 .Os .Sh NAME .Nm socketpair .Nd create a pair of connected sockets .Sh SYNOPSIS -.Fd #include <sys/socket.h> +.In sys/socket.h .Ft int .Fn socketpair "int d" "int type" "int protocol" "int sv[2]" .Sh DESCRIPTION @@ -56,6 +56,17 @@ are returned in and .Fa sv Ns [1] . The two sockets are indistinguishable. +.Pp +Any combination of the following flags may additionally be used in the +.Fa type +argument: +.Pp +.Bl -tag -width "SOCK_NONBLOCKX" -offset indent -compact +.It SOCK_CLOEXEC +Set close-on-exec flag on both the new descriptors. +.It SOCK_NONBLOCK +Set non-blocking I/O mode on both the new sockets. +.El .Sh RETURN VALUES A 0 is returned if the call succeeds, \-1 if it fails. .Sh ERRORS diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 7450935a2ba..0462dde3516 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_descrip.c,v 1.112 2014/07/13 15:29:04 tedu Exp $ */ +/* $OpenBSD: kern_descrip.c,v 1.113 2014/08/31 01:42:36 guenther Exp $ */ /* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */ /* @@ -74,6 +74,7 @@ static __inline void fd_unused(struct filedesc *, int); static __inline int find_next_zero(u_int *, int, u_int); int finishdup(struct proc *, struct file *, int, int, register_t *, int); int find_last_set(struct filedesc *, int); +int dodup3(struct proc *, int, int, int, register_t *); struct pool file_pool; struct pool fdesc_pool; @@ -235,7 +236,6 @@ out: /* * Duplicate a file descriptor to a particular value. */ -/* ARGSUSED */ int sys_dup2(struct proc *p, void *v, register_t *retval) { @@ -243,7 +243,30 @@ sys_dup2(struct proc *p, void *v, register_t *retval) syscallarg(int) from; syscallarg(int) to; } */ *uap = v; - int old = SCARG(uap, from), new = SCARG(uap, to); + + return (dodup3(p, SCARG(uap, from), SCARG(uap, to), 0, retval)); +} + +int +sys_dup3(struct proc *p, void *v, register_t *retval) +{ + struct sys_dup3_args /* { + syscallarg(int) from; + syscallarg(int) to; + syscallarg(int) flags; + } */ *uap = v; + + if (SCARG(uap, from) == SCARG(uap, to)) + return (EINVAL); + if (SCARG(uap, flags) & ~O_CLOEXEC) + return (EINVAL); + return (dodup3(p, SCARG(uap, from), SCARG(uap, to), + SCARG(uap, flags), retval)); +} + +int +dodup3(struct proc *p, int old, int new, int flags, register_t *retval) +{ struct filedesc *fdp = p->p_fd; struct file *fp; int i, error; @@ -281,6 +304,8 @@ restart: } /* finishdup() does FRELE */ error = finishdup(p, fp, old, new, retval, 1); + if (!error && flags & O_CLOEXEC) + fdp->fd_ofileflags[new] |= UF_EXCLOSE; out: fdpunlock(fdp); diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index b670234c591..cf8d88b51e7 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_pipe.c,v 1.65 2014/01/24 06:00:01 guenther Exp $ */ +/* $OpenBSD: sys_pipe.c,v 1.66 2014/08/31 01:42:36 guenther Exp $ */ /* * Copyright (c) 1996 John S. Dyson @@ -87,6 +87,7 @@ static int amountpipekva; struct pool pipe_pool; +int dopipe(struct proc *, int *, int); void pipeclose(struct pipe *); void pipe_free_kmem(struct pipe *); int pipe_create(struct pipe *); @@ -99,13 +100,33 @@ int pipespace(struct pipe *, u_int); * The pipe system call for the DTYPE_PIPE type of pipes */ -/* ARGSUSED */ int sys_pipe(struct proc *p, void *v, register_t *retval) { struct sys_pipe_args /* { syscallarg(int *) fdp; } */ *uap = v; + + return (dopipe(p, SCARG(uap, fdp), 0)); +} + +int +sys_pipe2(struct proc *p, void *v, register_t *retval) +{ + struct sys_pipe2_args /* { + syscallarg(int *) fdp; + syscallarg(int) flags; + } */ *uap = v; + + if (SCARG(uap, flags) & ~(O_CLOEXEC | FNONBLOCK)) + return (EINVAL); + + return (dopipe(p, SCARG(uap, fdp), SCARG(uap, flags))); +} + +int +dopipe(struct proc *p, int *ufds, int flags) +{ struct filedesc *fdp = p->p_fd; struct file *rf, *wf; struct pipe *rpipe, *wpipe = NULL; @@ -125,7 +146,7 @@ sys_pipe(struct proc *p, void *v, register_t *retval) error = falloc(p, &rf, &fds[0]); if (error != 0) goto free2; - rf->f_flag = FREAD | FWRITE; + rf->f_flag = FREAD | FWRITE | (flags & FNONBLOCK); rf->f_type = DTYPE_PIPE; rf->f_data = rpipe; rf->f_ops = &pipeops; @@ -133,18 +154,23 @@ sys_pipe(struct proc *p, void *v, register_t *retval) error = falloc(p, &wf, &fds[1]); if (error != 0) goto free3; - wf->f_flag = FREAD | FWRITE; + wf->f_flag = FREAD | FWRITE | (flags & FNONBLOCK); wf->f_type = DTYPE_PIPE; wf->f_data = wpipe; wf->f_ops = &pipeops; + if (flags & O_CLOEXEC) { + fdp->fd_ofileflags[fds[0]] |= UF_EXCLOSE; + fdp->fd_ofileflags[fds[1]] |= UF_EXCLOSE; + } + rpipe->pipe_peer = wpipe; wpipe->pipe_peer = rpipe; FILE_SET_MATURE(rf, p); FILE_SET_MATURE(wf, p); - error = copyout(fds, SCARG(uap, fdp), sizeof(fds)); + error = copyout(fds, ufds, sizeof(fds)); if (error != 0) { fdrelease(p, fds[0]); fdrelease(p, fds[1]); diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index a6f87135ce1..512d2032a96 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1,4 +1,4 @@ -; $OpenBSD: syscalls.master,v 1.143 2014/07/10 08:55:35 deraadt Exp $ +; $OpenBSD: syscalls.master,v 1.144 2014/08/31 01:42:36 guenther Exp $ ; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $ ; @(#)syscalls.master 8.2 (Berkeley) 1/13/94 @@ -203,7 +203,8 @@ 91 STD { int sys_nanosleep(const struct timespec *rqtp, \ struct timespec *rmtp); } 92 STD { int sys_fcntl(int fd, int cmd, ... void *arg); } -93 OBSOL t32_select +93 STD { int sys_accept4(int s, struct sockaddr *name, \ + socklen_t *anamelen, int flags); } 94 STD { int sys___thrsleep(const volatile void *ident, \ clockid_t clock_id, const struct timespec *tp, \ void *lock, const int *abort); } @@ -214,8 +215,8 @@ socklen_t namelen); } 99 STD { int sys_getdents(int fd, void *buf, size_t buflen); } 100 STD { int sys_getpriority(int which, id_t who); } -101 OBSOL osend -102 OBSOL orecv +101 STD { int sys_pipe2(int *fdp, int flags); } +102 STD { int sys_dup3(int from, int to, int flags); } 103 STD { int sys_sigreturn(struct sigcontext *sigcntxp); } 104 STD { int sys_bind(int s, const struct sockaddr *name, \ socklen_t namelen); } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 9e8670d082f..f6ca64c56e0 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.130 2014/07/13 15:52:38 tedu Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.131 2014/08/31 01:42:36 guenther Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -777,7 +777,7 @@ dontblock: mtod(cm, struct cmsghdr *)->cmsg_type == SCM_RIGHTS) error = (*pr->pr_domain->dom_externalize)(cm, - controllen); + controllen, flags); *controlp = cm; } else { /* diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 879e8096c47..f1dc4587ea2 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_syscalls.c,v 1.91 2014/07/13 15:00:40 tedu Exp $ */ +/* $OpenBSD: uipc_syscalls.c,v 1.92 2014/08/31 01:42:36 guenther Exp $ */ /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ /* @@ -37,6 +37,7 @@ #include <sys/filedesc.h> #include <sys/proc.h> #include <sys/file.h> +#include <sys/ioctl.h> #include <sys/buf.h> #include <sys/malloc.h> #include <sys/event.h> @@ -61,8 +62,10 @@ */ extern struct fileops socketops; -int copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t, - socklen_t *); +int copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t, + socklen_t *); +int doaccept(struct proc *, int, struct sockaddr *, socklen_t *, int, + register_t *); int sys_socket(struct proc *p, void *v, register_t *retval) @@ -75,19 +78,22 @@ sys_socket(struct proc *p, void *v, register_t *retval) struct filedesc *fdp = p->p_fd; struct socket *so; struct file *fp; + int type = SCARG(uap, type); int fd, error; fdplock(fdp); error = falloc(p, &fp, &fd); + if (type & SOCK_CLOEXEC) + fdp->fd_ofileflags[fd] |= UF_EXCLOSE; fdpunlock(fdp); if (error != 0) goto out; - fp->f_flag = FREAD|FWRITE; + fp->f_flag = FREAD | FWRITE | (type & SOCK_NONBLOCK ? FNONBLOCK : 0); fp->f_type = DTYPE_SOCKET; fp->f_ops = &socketops; - error = socreate(SCARG(uap, domain), &so, SCARG(uap, type), - SCARG(uap, protocol)); + error = socreate(SCARG(uap, domain), &so, + type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK), SCARG(uap, protocol)); if (error) { fdplock(fdp); fdremove(fdp, fd); @@ -95,6 +101,8 @@ sys_socket(struct proc *p, void *v, register_t *retval) fdpunlock(fdp); } else { fp->f_data = so; + if (type & SOCK_NONBLOCK) + (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&type, p); FILE_SET_MATURE(fp, p); *retval = fd; } @@ -157,6 +165,33 @@ sys_accept(struct proc *p, void *v, register_t *retval) syscallarg(struct sockaddr *) name; syscallarg(socklen_t *) anamelen; } */ *uap = v; + + return (doaccept(p, SCARG(uap, s), SCARG(uap, name), + SCARG(uap, anamelen), SOCK_NONBLOCK_INHERIT, retval)); +} + +int +sys_accept4(struct proc *p, void *v, register_t *retval) +{ + struct sys_accept4_args /* { + syscallarg(int) s; + syscallarg(struct sockaddr *) name; + syscallarg(socklen_t *) anamelen; + syscallarg(socklen_t *) int flags; + } */ *uap = v; + + if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) + return (EINVAL); + + return (doaccept(p, SCARG(uap, s), SCARG(uap, name), + SCARG(uap, anamelen), SCARG(uap, flags), retval)); +} + +int +doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen, + int flags, register_t *retval) +{ + struct filedesc *fdp = p->p_fd; struct file *fp, *headfp; struct mbuf *nam; socklen_t namelen; @@ -164,10 +199,9 @@ sys_accept(struct proc *p, void *v, register_t *retval) struct socket *head, *so; int nflag; - if (SCARG(uap, name) && (error = copyin(SCARG(uap, anamelen), - &namelen, sizeof (namelen)))) + if (name && (error = copyin(anamelen, &namelen, sizeof (namelen)))) return (error); - if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) + if ((error = getsock(fdp, sock, &fp)) != 0) return (error); headfp = fp; s = splsoftnet(); @@ -200,12 +234,15 @@ redo: goto bad; } - /* Take note if socket was non-blocking. */ - nflag = (headfp->f_flag & FNONBLOCK); + /* Figure out whether the new socket should be non-blocking. */ + nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK) + : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0); - fdplock(p->p_fd); + fdplock(fdp); error = falloc(p, &fp, &tmpfd); - fdpunlock(p->p_fd); + if (flags & SOCK_CLOEXEC) + fdp->fd_ofileflags[tmpfd] |= UF_EXCLOSE; + fdpunlock(fdp); if (error != 0) { /* * Probably ran out of file descriptors. Wakeup @@ -224,10 +261,10 @@ redo: */ if (head->so_qlen == 0) { m_freem(nam); - fdplock(p->p_fd); - fdremove(p->p_fd, tmpfd); + fdplock(fdp); + fdremove(fdp, tmpfd); closef(fp, p); - fdpunlock(p->p_fd); + fdpunlock(fdp); goto redo; } @@ -246,18 +283,17 @@ redo: fp->f_ops = &socketops; fp->f_data = so; error = soaccept(so, nam); - if (!error && SCARG(uap, name)) { - error = copyaddrout(p, nam, SCARG(uap, name), namelen, - SCARG(uap, anamelen)); - } + if (!error && name != NULL) + error = copyaddrout(p, nam, name, namelen, anamelen); if (error) { /* if an error occurred, free the file descriptor */ - fdplock(p->p_fd); - fdremove(p->p_fd, tmpfd); + fdplock(fdp); + fdremove(fdp, tmpfd); closef(fp, p); - fdpunlock(p->p_fd); + fdpunlock(fdp); } else { + (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&nflag, p); FILE_SET_MATURE(fp, p); *retval = tmpfd; } @@ -338,32 +374,36 @@ sys_socketpair(struct proc *p, void *v, register_t *retval) struct filedesc *fdp = p->p_fd; struct file *fp1, *fp2; struct socket *so1, *so2; - int fd, error, sv[2]; + int type, flags, fflag, error, sv[2]; - error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), - SCARG(uap, protocol)); + type = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); + flags = SCARG(uap, type) & (SOCK_CLOEXEC | SOCK_NONBLOCK); + fflag = FREAD | FWRITE | (flags & SOCK_NONBLOCK ? FNONBLOCK : 0); + + error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol)); if (error) return (error); - error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), - SCARG(uap, protocol)); + error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol)); if (error) goto free1; fdplock(fdp); - if ((error = falloc(p, &fp1, &fd)) != 0) + if ((error = falloc(p, &fp1, &sv[0])) != 0) goto free2; - sv[0] = fd; - fp1->f_flag = FREAD|FWRITE; + fp1->f_flag = fflag; fp1->f_type = DTYPE_SOCKET; fp1->f_ops = &socketops; fp1->f_data = so1; - if ((error = falloc(p, &fp2, &fd)) != 0) + if ((error = falloc(p, &fp2, &sv[1])) != 0) goto free3; - fp2->f_flag = FREAD|FWRITE; + fp2->f_flag = fflag; fp2->f_type = DTYPE_SOCKET; fp2->f_ops = &socketops; fp2->f_data = so2; - sv[1] = fd; + if (flags & SOCK_CLOEXEC) { + fdp->fd_ofileflags[sv[0]] |= UF_EXCLOSE; + fdp->fd_ofileflags[sv[1]] |= UF_EXCLOSE; + } if ((error = soconnect2(so1, so2)) != 0) goto free4; if (SCARG(uap, type) == SOCK_DGRAM) { @@ -375,6 +415,12 @@ sys_socketpair(struct proc *p, void *v, register_t *retval) } error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int)); if (error == 0) { + if (flags & SOCK_NONBLOCK) { + (*fp1->f_ops->fo_ioctl)(fp1, FIONBIO, (caddr_t)&flags, + p); + (*fp2->f_ops->fo_ioctl)(fp2, FIONBIO, (caddr_t)&flags, + p); + } FILE_SET_MATURE(fp1, p); FILE_SET_MATURE(fp2, p); fdpunlock(fdp); diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 8d81a4a7a7c..b45458469a1 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_usrreq.c,v 1.76 2014/07/13 15:52:38 tedu Exp $ */ +/* $OpenBSD: uipc_usrreq.c,v 1.77 2014/08/31 01:42:36 guenther Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* @@ -648,7 +648,7 @@ unp_drain(void) #endif int -unp_externalize(struct mbuf *rights, socklen_t controllen) +unp_externalize(struct mbuf *rights, socklen_t controllen, int flags) { struct proc *p = curproc; /* XXX */ struct cmsghdr *cm = mtod(rights, struct cmsghdr *); @@ -744,6 +744,9 @@ restart: * in the loop below. */ p->p_fd->fd_ofiles[fdp[i]] = *rp++; + + if (flags & MSG_CMSG_CLOEXEC) + p->p_fd->fd_ofileflags[fdp[i]] |= UF_EXCLOSE; } /* diff --git a/sys/sys/domain.h b/sys/sys/domain.h index 9af839288c6..d62819fa50f 100644 --- a/sys/sys/domain.h +++ b/sys/sys/domain.h @@ -1,4 +1,4 @@ -/* $OpenBSD: domain.h,v 1.11 2013/04/24 10:17:08 mpi Exp $ */ +/* $OpenBSD: domain.h,v 1.12 2014/08/31 01:42:36 guenther Exp $ */ /* $NetBSD: domain.h,v 1.10 1996/02/09 18:25:07 christos Exp $ */ /* @@ -52,7 +52,7 @@ struct domain { char *dom_name; void (*dom_init)(void); /* initialize domain data structures */ /* externalize access rights */ - int (*dom_externalize)(struct mbuf *, socklen_t); + int (*dom_externalize)(struct mbuf *, socklen_t, int); /* dispose of internalized rights */ void (*dom_dispose)(struct mbuf *); struct protosw *dom_protosw, *dom_protoswNPROTOSW; diff --git a/sys/sys/socket.h b/sys/sys/socket.h index aca2e639de4..e1c89489844 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -1,4 +1,4 @@ -/* $OpenBSD: socket.h,v 1.83 2013/04/02 03:38:24 guenther Exp $ */ +/* $OpenBSD: socket.h,v 1.84 2014/08/31 01:42:36 guenther Exp $ */ /* $NetBSD: socket.h,v 1.14 1996/02/09 18:25:36 christos Exp $ */ /* @@ -81,6 +81,17 @@ typedef __ssize_t ssize_t; #define SOCK_SEQPACKET 5 /* sequenced packet stream */ /* + * Socket creation flags + */ +#if __BSD_VISIBLE +#define SOCK_CLOEXEC 0x8000 /* set FD_CLOEXEC */ +#define SOCK_NONBLOCK 0x4000 /* set O_NONBLOCK */ +#endif +#ifdef _KERNEL +#define SOCK_NONBLOCK_INHERIT 0x2000 /* inherit O_NONBLOCK from listener */ +#endif + +/* * Option flags per-socket. */ #define SO_DEBUG 0x0001 /* turn on debugging info recording */ @@ -414,17 +425,18 @@ struct msghdr { int msg_flags; /* flags on received message */ }; -#define MSG_OOB 0x1 /* process out-of-band data */ -#define MSG_PEEK 0x2 /* peek at incoming message */ -#define MSG_DONTROUTE 0x4 /* send without using routing tables */ -#define MSG_EOR 0x8 /* data completes record */ -#define MSG_TRUNC 0x10 /* data discarded before delivery */ -#define MSG_CTRUNC 0x20 /* control data lost before delivery */ -#define MSG_WAITALL 0x40 /* wait for full request or error */ -#define MSG_DONTWAIT 0x80 /* this message should be nonblocking */ -#define MSG_BCAST 0x100 /* this message rec'd as broadcast */ -#define MSG_MCAST 0x200 /* this message rec'd as multicast */ -#define MSG_NOSIGNAL 0x400 /* do not send SIGPIPE */ +#define MSG_OOB 0x1 /* process out-of-band data */ +#define MSG_PEEK 0x2 /* peek at incoming message */ +#define MSG_DONTROUTE 0x4 /* send without using routing tables */ +#define MSG_EOR 0x8 /* data completes record */ +#define MSG_TRUNC 0x10 /* data discarded before delivery */ +#define MSG_CTRUNC 0x20 /* control data lost before delivery */ +#define MSG_WAITALL 0x40 /* wait for full request or error */ +#define MSG_DONTWAIT 0x80 /* this message should be nonblocking */ +#define MSG_BCAST 0x100 /* this message rec'd as broadcast */ +#define MSG_MCAST 0x200 /* this message rec'd as multicast */ +#define MSG_NOSIGNAL 0x400 /* do not send SIGPIPE */ +#define MSG_CMSG_CLOEXEC 0x800 /* set FD_CLOEXEC on received fds */ /* * Header for ancillary data objects in msg_control buffer. @@ -509,6 +521,10 @@ int socket(int, int, int); int socketpair(int, int, int, int *); #if __BSD_VISIBLE +int accept4(int, struct sockaddr *__restrict, socklen_t *__restrict, int); +#endif + +#if __BSD_VISIBLE int getpeereid(int, uid_t *, gid_t *); int getrtable(void); int setrtable(int); diff --git a/sys/sys/un.h b/sys/sys/un.h index 26b726b6107..b2d30ad94c6 100644 --- a/sys/sys/un.h +++ b/sys/sys/un.h @@ -1,4 +1,4 @@ -/* $OpenBSD: un.h,v 1.12 2012/09/15 00:47:09 guenther Exp $ */ +/* $OpenBSD: un.h,v 1.13 2014/08/31 01:42:36 guenther Exp $ */ /* $NetBSD: un.h,v 1.11 1996/02/04 02:12:47 christos Exp $ */ /* @@ -68,7 +68,7 @@ void unp_gc(void); void unp_mark(struct file *); void unp_scan(struct mbuf *, void (*)(struct file *), int); void unp_shutdown(struct unpcb *); -int unp_externalize(struct mbuf *, socklen_t); +int unp_externalize(struct mbuf *, socklen_t, int); int unp_internalize(struct mbuf *, struct proc *); void unp_dispose(struct mbuf *); #else /* !_KERNEL */ |