svn commit: r248534 - in head: lib/libc/sys share/man/man4 sys/kern sys/sys

Jilles Tjoelker jilles at FreeBSD.org
Tue Mar 19 20:58:20 UTC 2013


Author: jilles
Date: Tue Mar 19 20:58:17 2013
New Revision: 248534
URL: http://svnweb.freebsd.org/changeset/base/248534

Log:
  Implement SOCK_CLOEXEC, SOCK_NONBLOCK and MSG_CMSG_CLOEXEC.
  
  This change allows creating file descriptors with close-on-exec set in some
  situations. SOCK_CLOEXEC and SOCK_NONBLOCK can be OR'ed in socket() and
  socketpair()'s type parameter, and MSG_CMSG_CLOEXEC to recvmsg() makes file
  descriptors (SCM_RIGHTS) atomically close-on-exec.
  
  The numerical values for SOCK_CLOEXEC and SOCK_NONBLOCK are as in NetBSD.
  MSG_CMSG_CLOEXEC is the first free bit for MSG_*.
  
  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.
  
  For MSG_CMSG_CLOEXEC, unp_externalize() is extended to take a flags
  argument.
  
  Reviewed by:	kib

Modified:
  head/lib/libc/sys/recv.2
  head/lib/libc/sys/socket.2
  head/lib/libc/sys/socketpair.2
  head/share/man/man4/unix.4
  head/sys/kern/uipc_socket.c
  head/sys/kern/uipc_syscalls.c
  head/sys/kern/uipc_usrreq.c
  head/sys/sys/domain.h
  head/sys/sys/socket.h

Modified: head/lib/libc/sys/recv.2
==============================================================================
--- head/lib/libc/sys/recv.2	Tue Mar 19 20:20:00 2013	(r248533)
+++ head/lib/libc/sys/recv.2	Tue Mar 19 20:58:17 2013	(r248534)
@@ -28,7 +28,7 @@
 .\"     @(#)recv.2	8.3 (Berkeley) 2/21/94
 .\" $FreeBSD$
 .\"
-.Dd September 12, 2012
+.Dd March 19, 2013
 .Dt RECV 2
 .Os
 .Sh NAME
@@ -121,11 +121,12 @@ argument to a
 function is formed by
 .Em or Ap ing
 one or more of the values:
-.Bl -column ".Dv MSG_DONTWAIT" -offset indent
+.Bl -column ".Dv MSG_CMSG_CLOEXEC" -offset indent
 .It Dv MSG_OOB Ta process out-of-band data
 .It Dv MSG_PEEK Ta peek at incoming message
 .It Dv MSG_WAITALL Ta wait for full request or error
 .It Dv MSG_DONTWAIT Ta do not block
+.It Dv MSG_CMSG_CLOEXEC Ta set received fds close-on-exec
 .El
 .Pp
 The
@@ -227,6 +228,10 @@ and
 .Fa cmsg_type
 set to
 .Dv SCM_RIGHTS .
+The close-on-exec flag on received descriptors is set according to the
+.Dv MSG_CMSG_CLOEXEC
+flag passed to
+.Fn recvmsg .
 .Pp
 Process credentials can also be passed as ancillary data for
 .Dv AF_UNIX

Modified: head/lib/libc/sys/socket.2
==============================================================================
--- head/lib/libc/sys/socket.2	Tue Mar 19 20:20:00 2013	(r248533)
+++ head/lib/libc/sys/socket.2	Tue Mar 19 20:58:17 2013	(r248534)
@@ -28,7 +28,7 @@
 .\"     From: @(#)socket.2	8.1 (Berkeley) 6/4/93
 .\" $FreeBSD$
 .\"
-.Dd December 7, 2012
+.Dd March 19, 2013
 .Dt SOCKET 2
 .Os
 .Sh NAME
@@ -115,6 +115,15 @@ which is available only to the super-use
 which is planned,
 but not yet implemented, are not described here.
 .Pp
+Additionally, the following flags are allowed in the
+.Fa type
+argument:
+.Pp
+.Bd -literal -offset indent -compact
+SOCK_CLOEXEC	Set close-on-exec on the new descriptor,
+SOCK_NONBLOCK	Set non-blocking mode on the new socket
+.Ed
+.Pp
 The
 .Fa protocol
 argument

Modified: head/lib/libc/sys/socketpair.2
==============================================================================
--- head/lib/libc/sys/socketpair.2	Tue Mar 19 20:20:00 2013	(r248533)
+++ head/lib/libc/sys/socketpair.2	Tue Mar 19 20:58:17 2013	(r248534)
@@ -28,7 +28,7 @@
 .\"     @(#)socketpair.2	8.1 (Berkeley) 6/4/93
 .\" $FreeBSD$
 .\"
-.Dd June 4, 1993
+.Dd March 19, 2013
 .Dt SOCKETPAIR 2
 .Os
 .Sh NAME
@@ -57,6 +57,14 @@ are returned in
 and
 .Fa sv Ns [1] .
 The two sockets are indistinguishable.
+.Pp
+The
+.Dv SOCK_CLOEXEC
+and
+.Dv SOCK_NONBLOCK
+flags in the
+.Fa type
+argument apply to both descriptors.
 .Sh RETURN VALUES
 .Rv -std socketpair
 .Sh ERRORS
@@ -79,6 +87,7 @@ process address space.
 .Sh SEE ALSO
 .Xr pipe 2 ,
 .Xr read 2 ,
+.Xr socket 2 ,
 .Xr write 2
 .Sh HISTORY
 The

Modified: head/share/man/man4/unix.4
==============================================================================
--- head/share/man/man4/unix.4	Tue Mar 19 20:20:00 2013	(r248533)
+++ head/share/man/man4/unix.4	Tue Mar 19 20:58:17 2013	(r248534)
@@ -32,7 +32,7 @@
 .\"     @(#)unix.4	8.1 (Berkeley) 6/9/93
 .\" $FreeBSD$
 .\"
-.Dd November 16, 2012
+.Dd March 19, 2013
 .Dt UNIX 4
 .Os
 .Sh NAME
@@ -153,13 +153,15 @@ plus the size of the array of file descr
 .Pp
 The received descriptor is a
 .Em duplicate
-of the sender's descriptor, as if it were created with a call to
-.Xr dup 2 .
-Per-process descriptor flags, set with
-.Xr fcntl 2 ,
-are
-.Em not
-passed to a receiver.
+of the sender's descriptor, as if it were created via
+.Li dup(fd)
+or
+.Li fcntl(fd, F_DUPFD_CLOEXEC, 0)
+depending on whether
+.Dv MSG_CMSG_CLOEXEC
+is passed in the
+.Xr recvmsg 2
+call.
 Descriptors that are awaiting delivery, or that are
 purposely not received, are automatically closed by the system
 when the destination socket is closed.

Modified: head/sys/kern/uipc_socket.c
==============================================================================
--- head/sys/kern/uipc_socket.c	Tue Mar 19 20:20:00 2013	(r248533)
+++ head/sys/kern/uipc_socket.c	Tue Mar 19 20:58:17 2013	(r248534)
@@ -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, struc
 			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

Modified: head/sys/kern/uipc_syscalls.c
==============================================================================
--- head/sys/kern/uipc_syscalls.c	Tue Mar 19 20:20:00 2013	(r248533)
+++ head/sys/kern/uipc_syscalls.c	Tue Mar 19 20:58:17 2013	(r248534)
@@ -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 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,
@@ -665,12 +691,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 */
@@ -686,8 +712,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);

Modified: head/sys/kern/uipc_usrreq.c
==============================================================================
--- head/sys/kern/uipc_usrreq.c	Tue Mar 19 20:20:00 2013	(r248533)
+++ head/sys/kern/uipc_usrreq.c	Tue Mar 19 20:58:17 2013	(r248534)
@@ -288,7 +288,7 @@ static void	unp_freerights(struct filede
 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
 }
 
 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, st
 				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;
 			}

Modified: head/sys/sys/domain.h
==============================================================================
--- head/sys/sys/domain.h	Tue Mar 19 20:20:00 2013	(r248533)
+++ head/sys/sys/domain.h	Tue Mar 19 20:58:17 2013	(r248534)
@@ -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;

Modified: head/sys/sys/socket.h
==============================================================================
--- head/sys/sys/socket.h	Tue Mar 19 20:20:00 2013	(r248533)
+++ head/sys/sys/socket.h	Tue Mar 19 20:58:17 2013	(r248534)
@@ -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
 
 /*


More information about the svn-src-all mailing list