diff options
author | Keith M Wesolowski <wesolows@foobazco.org> | 2013-05-08 18:18:49 +0000 |
---|---|---|
committer | Keith M Wesolowski <wesolows@foobazco.org> | 2013-05-08 18:18:49 +0000 |
commit | 43840e901cacf50a9bb41148069e34ca307524e8 (patch) | |
tree | 2836162f69bba2534e8b9acf9797e5892f103258 /usr/src/uts/common | |
parent | abd43b3991c3becf4fd3cc1a370aeafdc8749a30 (diff) | |
parent | 5dbfd19ad5fcc2b779f40f80fa05c1bd28fd0b4e (diff) | |
download | illumos-joyent-43840e901cacf50a9bb41148069e34ca307524e8.tar.gz |
[illumos-gate merge]
commit 5dbfd19ad5fcc2b779f40f80fa05c1bd28fd0b4e
3713 Implement accept4()
3714 Implement pipe2()
3715 Implement dup3()
3716 Implement mkostemp() and mkostemps()
3719 so_socketpair syscall should preserve FD_CLOEXEC flag
commit 6136c589445a3ea081bd34ab72db1060875b6bcc
3722 link-editor is over restrictive of R_AMD64_32 addends
Conflicts:
usr/src/lib/libc/sparcv9/Makefile.com [copyright]
usr/src/lib/libc/sparc/Makefile.com [copyright]
usr/src/lib/libc/i386/Makefile.com [copyright]
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r-- | usr/src/uts/common/fs/sockfs/socksyscalls.c | 44 | ||||
-rw-r--r-- | usr/src/uts/common/os/sysent.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/sys/fcntl.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/sys/socket.h | 8 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/fcntl.c | 18 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/pipe.c | 74 |
6 files changed, 126 insertions, 26 deletions
diff --git a/usr/src/uts/common/fs/sockfs/socksyscalls.c b/usr/src/uts/common/fs/sockfs/socksyscalls.c index d4f36470e7..078b32fa76 100644 --- a/usr/src/uts/common/fs/sockfs/socksyscalls.c +++ b/usr/src/uts/common/fs/sockfs/socksyscalls.c @@ -338,6 +338,7 @@ so_socketpair(int sv[2]) int svs[2]; struct sonode *so1, *so2; int error; + int orig_flags; struct sockaddr_ux *name; size_t namelen; sotpi_info_t *sti1; @@ -494,13 +495,23 @@ so_socketpair(int sv[2]) releasef(svs[0]); releasef(svs[1]); - svs[0] = nfd; + + /* + * If FD_CLOEXEC was set on the filedescriptor we're + * swapping out, we should set it on the new one too. + */ + VERIFY(f_getfd_error(svs[0], &orig_flags) == 0); + if (orig_flags & FD_CLOEXEC) { + f_setfd(nfd, FD_CLOEXEC); + } /* * The socketpair library routine will close the original * svs[0] when this code passes out a different file * descriptor. */ + svs[0] = nfd; + if (copyout(svs, sv, sizeof (svs))) { (void) closeandsetf(nfd, NULL); eprintline(EFAULT); @@ -586,9 +597,10 @@ listen(int sock, int backlog, int version) return (0); } -/*ARGSUSED3*/ +/*ARGSUSED4*/ int -accept(int sock, struct sockaddr *name, socklen_t *namelenp, int version) +accept(int sock, struct sockaddr *name, socklen_t *namelenp, int version, + int flags) { struct sonode *so; file_t *fp; @@ -598,12 +610,24 @@ accept(int sock, struct sockaddr *name, socklen_t *namelenp, int version) struct vnode *nvp; struct file *nfp; int nfd; + int ssflags; struct sockaddr *addrp; socklen_t addrlen; dprint(1, ("accept(%d, %p, %p)\n", sock, (void *)name, (void *)namelenp)); + if (flags & ~(SOCK_CLOEXEC|SOCK_NONBLOCK|SOCK_NDELAY)) { + return (set_errno(EINVAL)); + } + + /* Translate SOCK_ flags to their SS_ variant */ + ssflags = 0; + if (flags & SOCK_NONBLOCK) + ssflags |= SS_NONBLOCK; + if (flags & SOCK_NDELAY) + ssflags |= SS_NDELAY; + if ((so = getsonode(sock, &error, &fp)) == NULL) return (set_errno(error)); @@ -682,15 +706,23 @@ accept(int sock, struct sockaddr *name, socklen_t *namelenp, int version) setf(nfd, nfp); /* + * Act on SOCK_CLOEXEC from flags + */ + if (flags & SOCK_CLOEXEC) { + f_setfd(nfd, FD_CLOEXEC); + } + + /* * Copy FNDELAY and FNONBLOCK from listener to acceptor + * and from ssflags */ - if (so->so_state & (SS_NDELAY|SS_NONBLOCK)) { + if ((ssflags | so->so_state) & (SS_NDELAY|SS_NONBLOCK)) { uint_t oflag = nfp->f_flag; int arg = 0; - if (so->so_state & SS_NONBLOCK) + if ((ssflags | so->so_state) & SS_NONBLOCK) arg |= FNONBLOCK; - else if (so->so_state & SS_NDELAY) + else if ((ssflags | so->so_state) & SS_NDELAY) arg |= FNDELAY; /* diff --git a/usr/src/uts/common/os/sysent.c b/usr/src/uts/common/os/sysent.c index a79b101796..48ae2ed349 100644 --- a/usr/src/uts/common/os/sysent.c +++ b/usr/src/uts/common/os/sysent.c @@ -24,6 +24,7 @@ /* * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Milan Jurik. All rights reserved. + * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -742,7 +743,7 @@ struct sysent sysent[NSYSCALL] = /* 231 */ SYSENT_CI("so_socketpair", so_socketpair, 1), /* 232 */ SYSENT_CI("bind", bind, 4), /* 233 */ SYSENT_CI("listen", listen, 3), - /* 234 */ SYSENT_CI("accept", accept, 4), + /* 234 */ SYSENT_CI("accept", accept, 5), /* 235 */ SYSENT_CI("connect", connect, 4), /* 236 */ SYSENT_CI("shutdown", shutdown, 3), /* 237 */ SYSENT_CL("recv", recv, 4), @@ -1073,7 +1074,7 @@ struct sysent sysent32[NSYSCALL] = /* 231 */ SYSENT_CI("so_socketpair", so_socketpair, 1), /* 232 */ SYSENT_CI("bind", bind, 4), /* 233 */ SYSENT_CI("listen", listen, 3), - /* 234 */ SYSENT_CI("accept", accept, 4), + /* 234 */ SYSENT_CI("accept", accept, 5), /* 235 */ SYSENT_CI("connect", connect, 4), /* 236 */ SYSENT_CI("shutdown", shutdown, 3), /* 237 */ SYSENT_CI("recv", recv32, 4), diff --git a/usr/src/uts/common/sys/fcntl.h b/usr/src/uts/common/sys/fcntl.h index f3ca84fff1..aa74cab8b5 100644 --- a/usr/src/uts/common/sys/fcntl.h +++ b/usr/src/uts/common/sys/fcntl.h @@ -120,6 +120,9 @@ extern "C" { #define F_CHKFL 8 /* Unused */ #define F_DUP2FD 9 /* Duplicate fildes at third arg */ +#define F_DUP2FD_CLOEXEC 36 /* Like F_DUP2FD with O_CLOEXEC set */ + /* EINVAL is fildes matches arg1 */ +#define F_DUPFD_CLOEXEC 37 /* Like F_DUPFD with O_CLOEXEC set */ #define F_ISSTREAM 13 /* Is the file desc. a stream ? */ #define F_PRIV 15 /* Turn on private access to file */ diff --git a/usr/src/uts/common/sys/socket.h b/usr/src/uts/common/sys/socket.h index 0b91740d3a..2733c50faa 100644 --- a/usr/src/uts/common/sys/socket.h +++ b/usr/src/uts/common/sys/socket.h @@ -106,9 +106,11 @@ typedef void *_RESTRICT_KYWD Psocklen_t; #define SOCK_TYPE_MASK 0xffff /* type reside in these bits only */ /* - * Flags for socket() + * Flags for socket() and accept4() */ -#define SOCK_CLOEXEC 0x80000 /* like open(2) O_CLOEXEC for socket */ +#define SOCK_CLOEXEC 0x080000 /* like open(2) O_CLOEXEC for socket */ +#define SOCK_NONBLOCK 0x100000 /* like O_NONBLOCK */ +#define SOCK_NDELAY 0x200000 /* like O_NDELAY */ /* * Option flags per-socket. @@ -522,6 +524,7 @@ struct cmsghdr { #if !defined(_KERNEL) || defined(_BOOT) #ifdef __STDC__ extern int accept(int, struct sockaddr *_RESTRICT_KYWD, Psocklen_t); +extern int accept4(int, struct sockaddr *_RESTRICT_KYWD, Psocklen_t, int); extern int bind(int, const struct sockaddr *, socklen_t); extern int connect(int, const struct sockaddr *, socklen_t); extern int getpeername(int, struct sockaddr *_RESTRICT_KYWD, Psocklen_t); @@ -546,6 +549,7 @@ extern int sockatmark(int); #endif /* !defined(_XPG4_2) || defined(_XPG6) || defined(__EXTENSIONS__) */ #else /* __STDC__ */ extern int accept(); +extern int accept4(); extern int bind(); extern int connect(); extern int getpeername(); diff --git a/usr/src/uts/common/syscall/fcntl.c b/usr/src/uts/common/syscall/fcntl.c index 4a6e58f6b0..43a50d6d58 100644 --- a/usr/src/uts/common/syscall/fcntl.c +++ b/usr/src/uts/common/syscall/fcntl.c @@ -22,6 +22,7 @@ /* ONC_PLUS EXTRACT START */ /* * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -32,6 +33,7 @@ * under license from the Regents of the University of California. */ + /* ONC_PLUS EXTRACT END */ #include <sys/param.h> @@ -151,6 +153,7 @@ fcntl(int fdes, int cmd, intptr_t arg) /* ONC_PLUS EXTRACT END */ case F_DUPFD: + case F_DUPFD_CLOEXEC: p = curproc; if ((uint_t)iarg >= p->p_fno_ctl) { if (iarg >= 0) @@ -178,9 +181,21 @@ fcntl(int fdes, int cmd, intptr_t arg) fp->f_count--; mutex_exit(&fp->f_tlock); error = EMFILE; + } else { + if (cmd == F_DUPFD_CLOEXEC) { + f_setfd(retval, FD_CLOEXEC); + } } goto done; + case F_DUP2FD_CLOEXEC: + if (fdes == iarg) { + error = EINVAL; + goto done; + } + + /* lint -fallthrough */ + case F_DUP2FD: p = curproc; if (fdes == iarg) { @@ -208,6 +223,9 @@ fcntl(int fdes, int cmd, intptr_t arg) mutex_exit(&fp->f_tlock); releasef(fdes); if ((error = closeandsetf(iarg, fp)) == 0) { + if (cmd == F_DUP2FD_CLOEXEC) { + f_setfd(iarg, FD_CLOEXEC); + } retval = iarg; } else { mutex_enter(&fp->f_tlock); diff --git a/usr/src/uts/common/syscall/pipe.c b/usr/src/uts/common/syscall/pipe.c index a626b2364a..1b9ea4f6db 100644 --- a/usr/src/uts/common/syscall/pipe.c +++ b/usr/src/uts/common/syscall/pipe.c @@ -19,6 +19,7 @@ * CDDL HEADER END */ /* + * Copyright 2013 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2011 Bayard G. Bell. All rights reserved. @@ -41,6 +42,7 @@ #include <sys/errno.h> #include <sys/debug.h> #include <sys/fs/fifonode.h> +#include <sys/fcntl.h> /* * This is the loadable module wrapper. @@ -48,11 +50,11 @@ #include <sys/modctl.h> #include <sys/syscall.h> -longlong_t pipe(); +int pipe(intptr_t fds, int); static struct sysent pipe_sysent = { - 0, - SE_32RVAL1 | SE_32RVAL2 | SE_NOUNLOAD | SE_ARGC, + 2, + SE_ARGC | SE_32RVAL1 | SE_NOUNLOAD, (int (*)())pipe }; @@ -102,16 +104,22 @@ _info(struct modinfo *modinfop) * each end of the pipe with a vnode, a file descriptor and * one of the streams. */ -longlong_t -pipe() +int +pipe(intptr_t arg, int flags) { vnode_t *vp1, *vp2; struct file *fp1, *fp2; int error = 0; + int flag1, flag2, iflags; int fd1, fd2; - rval_t r; /* + * Validate allowed flags. + */ + if (flags & ~(FCLOEXEC|FNONBLOCK) != 0) { + return (set_errno(EINVAL)); + } + /* * Allocate and initialize two vnodes. */ makepipe(&vp1, &vp2); @@ -124,7 +132,7 @@ pipe() if (error = falloc(vp1, FWRITE|FREAD, &fp1, &fd1)) { VN_RELE(vp1); VN_RELE(vp2); - return ((longlong_t)set_errno(error)); + return (set_errno(error)); } if (error = falloc(vp2, FWRITE|FREAD, &fp2, &fd2)) @@ -147,6 +155,36 @@ pipe() VTOF(vp1)->fn_ino = VTOF(vp2)->fn_ino = fifogetid(); /* + * Set the O_NONBLOCK flag if requested. + */ + if (flags & FNONBLOCK) { + flag1 = fp1->f_flag; + flag2 = fp2->f_flag; + iflags = flags & FNONBLOCK; + + if (error = VOP_SETFL(vp1, flag1, iflags, fp1->f_cred, NULL)) { + goto out_vop_close; + } + fp1->f_flag |= iflags; + + if (error = VOP_SETFL(vp2, flag2, iflags, fp2->f_cred, NULL)) { + goto out_vop_close; + } + fp2->f_flag |= iflags; + } + + /* + * Return the file descriptors to the user. They now + * point to two different vnodes which have different + * stream heads. + */ + if (copyout(&fd1, &((int *)arg)[0], sizeof (int)) || + copyout(&fd2, &((int *)arg)[1], sizeof (int))) { + error = EFAULT; + goto out_vop_close; + } + + /* * Now fill in the entries that falloc reserved */ mutex_exit(&fp1->f_tlock); @@ -155,20 +193,24 @@ pipe() setf(fd2, fp2); /* - * Return the file descriptors to the user. They now - * point to two different vnodes which have different - * stream heads. + * Optionally set the FCLOEXEC flag */ - r.r_val1 = fd1; - r.r_val2 = fd2; - return (r.r_vals); + if ((flags & FCLOEXEC) != 0) { + f_setfd(fd1, FD_CLOEXEC); + f_setfd(fd2, FD_CLOEXEC); + } + + return (0); +out_vop_close: + (void) VOP_CLOSE(vp1, FWRITE|FREAD, 1, (offset_t)0, fp1->f_cred, NULL); + (void) VOP_CLOSE(vp2, FWRITE|FREAD, 1, (offset_t)0, fp2->f_cred, NULL); out: - unfalloc(fp2); setf(fd2, NULL); + unfalloc(fp2); out2: - unfalloc(fp1); setf(fd1, NULL); + unfalloc(fp1); VN_RELE(vp1); VN_RELE(vp2); - return ((longlong_t)set_errno(error)); + return (set_errno(error)); } |