summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2013-05-08 18:18:49 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2013-05-08 18:18:49 +0000
commit43840e901cacf50a9bb41148069e34ca307524e8 (patch)
tree2836162f69bba2534e8b9acf9797e5892f103258 /usr/src/uts/common
parentabd43b3991c3becf4fd3cc1a370aeafdc8749a30 (diff)
parent5dbfd19ad5fcc2b779f40f80fa05c1bd28fd0b4e (diff)
downloadillumos-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.c44
-rw-r--r--usr/src/uts/common/os/sysent.c5
-rw-r--r--usr/src/uts/common/sys/fcntl.h3
-rw-r--r--usr/src/uts/common/sys/socket.h8
-rw-r--r--usr/src/uts/common/syscall/fcntl.c18
-rw-r--r--usr/src/uts/common/syscall/pipe.c74
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));
}