Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 2 Mar 2013 21:11:31 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r247667 - in head: contrib/openbsm/etc lib/libc/sys sys/bsm sys/compat/freebsd32 sys/kern sys/security/audit sys/sys usr.bin/procstat
Message-ID:  <201303022111.r22LBVEd045583@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pjd
Date: Sat Mar  2 21:11:30 2013
New Revision: 247667
URL: http://svnweb.freebsd.org/changeset/base/247667

Log:
  - Implement two new system calls:
  
  	int bindat(int fd, int s, const struct sockaddr *addr, socklen_t addrlen);
  	int connectat(int fd, int s, const struct sockaddr *name, socklen_t namelen);
  
    which allow to bind and connect respectively to a UNIX domain socket with a
    path relative to the directory associated with the given file descriptor 'fd'.
  
  - Add manual pages for the new syscalls.
  
  - Make the new syscalls available for processes in capability mode sandbox.
  
  - Add capability rights CAP_BINDAT and CAP_CONNECTAT that has to be present on
    the directory descriptor for the syscalls to work.
  
  - Update audit(4) to support those two new syscalls and to handle path
    in sockaddr_un structure relative to the given directory descriptor.
  
  - Update procstat(1) to recognize the new capability rights.
  
  - Document the new capability rights in cap_rights_limit(2).
  
  Sponsored by:	The FreeBSD Foundation
  Discussed with:	rwatson, jilles, kib, des

Added:
  head/lib/libc/sys/bindat.2   (contents, props changed)
  head/lib/libc/sys/connectat.2   (contents, props changed)
Modified:
  head/contrib/openbsm/etc/audit_event
  head/lib/libc/sys/Makefile.inc
  head/lib/libc/sys/Symbol.map
  head/lib/libc/sys/cap_rights_limit.2
  head/sys/bsm/audit_kevents.h
  head/sys/compat/freebsd32/syscalls.master
  head/sys/kern/capabilities.conf
  head/sys/kern/syscalls.master
  head/sys/kern/uipc_domain.c
  head/sys/kern/uipc_socket.c
  head/sys/kern/uipc_syscalls.c
  head/sys/kern/uipc_usrreq.c
  head/sys/security/audit/audit.h
  head/sys/security/audit/audit_arg.c
  head/sys/security/audit/audit_bsm.c
  head/sys/sys/capability.h
  head/sys/sys/protosw.h
  head/sys/sys/socket.h
  head/sys/sys/socketvar.h
  head/usr.bin/procstat/procstat_files.c

Modified: head/contrib/openbsm/etc/audit_event
==============================================================================
--- head/contrib/openbsm/etc/audit_event	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/contrib/openbsm/etc/audit_event	Sat Mar  2 21:11:30 2013	(r247667)
@@ -568,6 +568,8 @@
 43204:AUE_CAP_IOCTLS_GET:cap_ioctls_get(2):fm
 43205:AUE_CAP_FCNTLS_LIMIT:cap_fcntls_limit(2):fm
 43206:AUE_CAP_FCNTLS_GET:cap_fcntls_get(2):fm
+43207:AUE_BINDAT:bindat(2):nt
+43208:AUE_CONNECTAT:connectat(2):nt
 #
 # Solaris userspace events.
 #

Modified: head/lib/libc/sys/Makefile.inc
==============================================================================
--- head/lib/libc/sys/Makefile.inc	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/lib/libc/sys/Makefile.inc	Sat Mar  2 21:11:30 2013	(r247667)
@@ -91,6 +91,7 @@ MAN+=	abort2.2 \
 	aio_waitcomplete.2 \
 	aio_write.2 \
 	bind.2 \
+	bindat.2 \
 	brk.2 \
 	cap_enter.2 \
 	cap_fcntls_limit.2 \
@@ -105,6 +106,7 @@ MAN+=	abort2.2 \
 	close.2 \
 	closefrom.2 \
 	connect.2 \
+	connectat.2 \
 	cpuset.2 \
 	cpuset_getaffinity.2 \
 	dup.2 \

Modified: head/lib/libc/sys/Symbol.map
==============================================================================
--- head/lib/libc/sys/Symbol.map	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/lib/libc/sys/Symbol.map	Sat Mar  2 21:11:30 2013	(r247667)
@@ -378,6 +378,7 @@ FBSD_1.2 {
 };
 
 FBSD_1.3 {
+	bindat;
 	cap_fcntls_get;
 	cap_fcntls_limit;
 	cap_ioctls_get;
@@ -386,6 +387,7 @@ FBSD_1.3 {
 	cap_rights_limit;
 	cap_sandboxed;
 	clock_getcpuclockid2;
+	connectat;
 	ffclock_getcounter;
 	ffclock_getestimate;
 	ffclock_setestimate;

Added: head/lib/libc/sys/bindat.2
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libc/sys/bindat.2	Sat Mar  2 21:11:30 2013	(r247667)
@@ -0,0 +1,109 @@
+.\" Copyright (c) 2013 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by Pawel Jakub Dawidek under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 13, 2013
+.Dt BINDAT 2
+.Os
+.Sh NAME
+.Nm bindat
+.Nd assign a local protocol address to a socket
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.Pp
+.In fcntl.h
+.Ft int
+.Fn bindat "int fd" "int s" "const struct sockaddr *addr" "socklen_t addrlen"
+.Sh DESCRIPTION
+The
+.Fn bindat
+system call assigns the local protocol address to a socket.
+It works just like the
+.Xr bind 2
+system call with two exceptions:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+It is limited to sockets in the PF_LOCAL domain.
+.Pp
+.It
+If the file path stored in the
+.Fa sun_path
+field of the sockaddr_un structure is a relative path, it is located relative
+to the directory associated with the file descriptor
+.Fa fd .
+If
+.Fn bindat
+is passed the special value
+.Dv AT_FDCWD
+in the
+.Fa fd
+parameter, the current working directory is used and the behavior is identical
+to a call to
+.Xr bind 2 .
+.El
+.Sh RETURN VALUES
+.Rv -std bindat
+.Sh ERRORS
+The
+.Fn bindat
+system call may fail with the same errors as the
+.Xr bind 2
+system call for a UNIX domain socket or with the following errors:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa sun_path
+field does not specify an absolute path and the
+.Fa fd
+argument is neither
+.Dv AT_FDCWD
+nor a valid file descriptor.
+.It Bq Er ENOTDIR
+The
+.Fa sun_path
+field is not an absolute path and
+.Fa fd
+is neither
+.Dv AT_FDCWD
+nor a file descriptor associated with a directory.
+.El
+.Sh SEE ALSO
+.Xr bind 2 ,
+.Xr connectat 2 ,
+.Xr socket 2 ,
+.Xr unix 4
+.Sh AUTHORS
+The
+.Nm
+was developed by
+.An Pawel Jakub Dawidek Aq pawel@dawidek.net
+under sponsorship from the FreeBSD Foundation.

Modified: head/lib/libc/sys/cap_rights_limit.2
==============================================================================
--- head/lib/libc/sys/cap_rights_limit.2	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/lib/libc/sys/cap_rights_limit.2	Sat Mar  2 21:11:30 2013	(r247667)
@@ -104,12 +104,20 @@ or
 and that socket options set with
 .Xr setsockopt 2
 may also affect binding behavior.
+.It Dv CAP_BINDAT
+Permit
+.Xr bindat 2 .
+This right has to be present on the directory descriptor.
 .It Dv CAP_CONNECT
 Permit
 .Xr connect 2 ;
 also required for
 .Xr sendto 2
 with a non-NULL destination address.
+.It Dv CAP_CONNECTAT
+Permit
+.Xr connectat 2 .
+This right has to be present on the directory descriptor.
 .It Dv CAP_CREATE
 Permit
 .Xr openat 2
@@ -511,11 +519,13 @@ argument points at an invalid address.
 .Xr aio_read 2 ,
 .Xr aio_write 2 ,
 .Xr bind 2 ,
+.Xr bindat 2 ,
 .Xr cap_enter 2 ,
 .Xr cap_fcntls_limit 2 ,
 .Xr cap_ioctls_limit 2 ,
 .Xr cap_rights_limit 2 ,
 .Xr connect 2 ,
+.Xr connectat 2 ,
 .Xr dup 2 ,
 .Xr dup2 2 ,
 .Xr extattr_delete_fd 2 ,

Added: head/lib/libc/sys/connectat.2
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libc/sys/connectat.2	Sat Mar  2 21:11:30 2013	(r247667)
@@ -0,0 +1,109 @@
+.\" Copyright (c) 2013 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by Pawel Jakub Dawidek under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 13, 2013
+.Dt CONNECTAT 2
+.Os
+.Sh NAME
+.Nm connectat
+.Nd initiate a connection on a socket
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.Pp
+.In fcntl.h
+.Ft int
+.Fn connectat "int fd" "int s" "const struct sockaddr *name" "socklen_t namelen"
+.Sh DESCRIPTION
+The
+.Fn connectat
+system call initiates a connection on a socket.
+It works just like the
+.Xr connect 2
+system call with two exceptions:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+It is limited to sockets in the PF_LOCAL domain.
+.Pp
+.It
+If the file path stored in the
+.Fa sun_path
+field of the sockaddr_un structure is a relative path, it is located relative
+to the directory associated with the file descriptor
+.Fa fd .
+If
+.Fn connectat
+is passed the special value
+.Dv AT_FDCWD
+in the
+.Fa fd
+parameter, the current working directory is used and the behavior is identical
+to a call to
+.Xr connect 2 .
+.El
+.Sh RETURN VALUES
+.Rv -std connectat
+.Sh ERRORS
+The
+.Fn connectat
+system call may fail with the same errors as the
+.Xr connect 2
+system call for a UNIX domain socket or with the following errors:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa sun_path
+field does not specify an absolute path and the
+.Fa fd
+argument is neither
+.Dv AT_FDCWD
+nor a valid file descriptor.
+.It Bq Er ENOTDIR
+The
+.Fa sun_path
+field is not an absolute path and
+.Fa fd
+is neither
+.Dv AT_FDCWD
+nor a file descriptor associated with a directory.
+.El
+.Sh SEE ALSO
+.Xr bindat 2 ,
+.Xr connect 2 ,
+.Xr socket 2 ,
+.Xr unix 4
+.Sh AUTHORS
+The
+.Nm
+was developed by
+.An Pawel Jakub Dawidek Aq pawel@dawidek.net
+under sponsorship from the FreeBSD Foundation.

Modified: head/sys/bsm/audit_kevents.h
==============================================================================
--- head/sys/bsm/audit_kevents.h	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/bsm/audit_kevents.h	Sat Mar  2 21:11:30 2013	(r247667)
@@ -608,6 +608,8 @@
 #define	AUE_CAP_IOCTLS_GET	43204	/* TrustedBSD. */
 #define	AUE_CAP_FCNTLS_LIMIT	43205	/* TrustedBSD. */
 #define	AUE_CAP_FCNTLS_GET	43206	/* TrustedBSD. */
+#define	AUE_BINDAT		43207	/* TrustedBSD. */
+#define	AUE_CONNECTAT		43208	/* TrustedBSD. */
 
 /*
  * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the

Modified: head/sys/compat/freebsd32/syscalls.master
==============================================================================
--- head/sys/compat/freebsd32/syscalls.master	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/compat/freebsd32/syscalls.master	Sat Mar  2 21:11:30 2013	(r247667)
@@ -1015,3 +1015,7 @@
 				    uint32_t fcntlrights); }
 537	AUE_CAP_FCNTLS_GET	NOPROTO	{ int cap_fcntls_get(int fd, \
 				    uint32_t *fcntlrightsp); }
+538	AUE_BINDAT	NOPROTO	{ int bindat(int fd, int s, caddr_t name, \
+				    int namelen); }
+539	AUE_CONNECTAT	NOPROTO	{ int connectat(int fd, int s, caddr_t name, \
+				    int namelen); }

Modified: head/sys/kern/capabilities.conf
==============================================================================
--- head/sys/kern/capabilities.conf	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/kern/capabilities.conf	Sat Mar  2 21:11:30 2013	(r247667)
@@ -100,11 +100,9 @@ aio_write
 #audit
 
 ##
-## Disllow bind(2) for now, even though we support CAP_BIND.
+## Allow bindat(2).
 ##
-## XXXRW: Revisit this.
-##
-#bind
+bindat
 
 ##
 ## Allow capability mode and capability system calls.
@@ -132,11 +130,9 @@ close
 closefrom
 
 ##
-## Disallow connect(2) for now, despite CAP_CONNECT.
-##
-## XXXRW: Revisit this.
+## Allow connectat(2).
 ##
-#connect
+connectat
 
 ##
 ## cpuset(2) and related calls require scoping by process, but should

Modified: head/sys/kern/syscalls.master
==============================================================================
--- head/sys/kern/syscalls.master	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/kern/syscalls.master	Sat Mar  2 21:11:30 2013	(r247667)
@@ -965,5 +965,9 @@
 					    uint32_t fcntlrights); }
 537	AUE_CAP_FCNTLS_GET	STD	{ int cap_fcntls_get(int fd, \
 					    uint32_t *fcntlrightsp); }
+538	AUE_BINDAT	STD	{ int bindat(int fd, int s, caddr_t name, \
+				    int namelen); }
+539	AUE_CONNECTAT	STD	{ int connectat(int fd, int s, caddr_t name, \
+				    int namelen); }
 ; Please copy any additions and changes to the following compatability tables:
 ; sys/compat/freebsd32/syscalls.master

Modified: head/sys/kern/uipc_domain.c
==============================================================================
--- head/sys/kern/uipc_domain.c	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/kern/uipc_domain.c	Sat Mar  2 21:11:30 2013	(r247667)
@@ -136,8 +136,10 @@ protosw_init(struct protosw *pr)
 #define DEFAULT(foo, bar)	if ((foo) == NULL)  (foo) = (bar)
 	DEFAULT(pu->pru_accept, pru_accept_notsupp);
 	DEFAULT(pu->pru_bind, pru_bind_notsupp);
+	DEFAULT(pu->pru_bindat, pru_bindat_notsupp);
 	DEFAULT(pu->pru_connect, pru_connect_notsupp);
 	DEFAULT(pu->pru_connect2, pru_connect2_notsupp);
+	DEFAULT(pu->pru_connectat, pru_connectat_notsupp);
 	DEFAULT(pu->pru_control, pru_control_notsupp);
 	DEFAULT(pu->pru_disconnect, pru_disconnect_notsupp);
 	DEFAULT(pu->pru_listen, pru_listen_notsupp);

Modified: head/sys/kern/uipc_socket.c
==============================================================================
--- head/sys/kern/uipc_socket.c	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/kern/uipc_socket.c	Sat Mar  2 21:11:30 2013	(r247667)
@@ -615,7 +615,18 @@ sobind(struct socket *so, struct sockadd
 	CURVNET_SET(so->so_vnet);
 	error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, td);
 	CURVNET_RESTORE();
-	return error;
+	return (error);
+}
+
+int
+sobindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
+{
+	int error;
+
+	CURVNET_SET(so->so_vnet);
+	error = (*so->so_proto->pr_usrreqs->pru_bindat)(fd, so, nam, td);
+	CURVNET_RESTORE();
+	return (error);
 }
 
 /*
@@ -638,7 +649,7 @@ solisten(struct socket *so, int backlog,
 	CURVNET_SET(so->so_vnet);
 	error = (*so->so_proto->pr_usrreqs->pru_listen)(so, backlog, td);
 	CURVNET_RESTORE();
-	return error;
+	return (error);
 }
 
 int
@@ -896,6 +907,13 @@ soaccept(struct socket *so, struct socka
 int
 soconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
+
+	return (soconnectat(AT_FDCWD, so, nam, td));
+}
+
+int
+soconnectat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
+{
 	int error;
 
 	if (so->so_options & SO_ACCEPTCONN)
@@ -917,7 +935,13 @@ soconnect(struct socket *so, struct sock
 		 * biting us.
 		 */
 		so->so_error = 0;
-		error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, td);
+		if (fd == AT_FDCWD) {
+			error = (*so->so_proto->pr_usrreqs->pru_connect)(so,
+			    nam, td);
+		} else {
+			error = (*so->so_proto->pr_usrreqs->pru_connectat)(fd,
+			    so, nam, td);
+		}
 	}
 	CURVNET_RESTORE();
 
@@ -3141,6 +3165,14 @@ pru_bind_notsupp(struct socket *so, stru
 }
 
 int
+pru_bindat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
+    struct thread *td)
+{
+
+	return EOPNOTSUPP;
+}
+
+int
 pru_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
 
@@ -3148,6 +3180,14 @@ pru_connect_notsupp(struct socket *so, s
 }
 
 int
+pru_connectat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
+    struct thread *td)
+{
+
+	return EOPNOTSUPP;
+}
+
+int
 pru_connect2_notsupp(struct socket *so1, struct socket *so2)
 {
 

Modified: head/sys/kern/uipc_syscalls.c
==============================================================================
--- head/sys/kern/uipc_syscalls.c	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/kern/uipc_syscalls.c	Sat Mar  2 21:11:30 2013	(r247667)
@@ -201,26 +201,23 @@ sys_bind(td, uap)
 	struct sockaddr *sa;
 	int error;
 
-	if ((error = getsockaddr(&sa, uap->name, uap->namelen)) != 0)
-		return (error);
-
-	error = kern_bind(td, uap->s, sa);
-	free(sa, M_SONAME);
+	error = getsockaddr(&sa, uap->name, uap->namelen);
+	if (error == 0) {
+		error = kern_bind(td, uap->s, sa);
+		free(sa, M_SONAME);
+	}
 	return (error);
 }
 
-int
-kern_bind(td, fd, sa)
-	struct thread *td;
-	int fd;
-	struct sockaddr *sa;
+static int
+kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
 {
 	struct socket *so;
 	struct file *fp;
 	int error;
 
 	AUDIT_ARG_FD(fd);
-	AUDIT_ARG_SOCKADDR(td, sa);
+	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
 	error = getsock_cap(td->td_proc->p_fd, fd, CAP_BIND, &fp, NULL);
 	if (error)
 		return (error);
@@ -231,13 +228,48 @@ kern_bind(td, fd, sa)
 #endif
 #ifdef MAC
 	error = mac_socket_check_bind(td->td_ucred, so, sa);
-	if (error == 0)
+	if (error == 0) {
+#endif
+		if (dirfd == AT_FDCWD)
+			error = sobind(so, sa, td);
+		else
+			error = sobindat(dirfd, so, sa, td);
+#ifdef MAC
+	}
 #endif
-		error = sobind(so, sa, td);
 	fdrop(fp, td);
 	return (error);
 }
 
+int
+kern_bind(struct thread *td, int fd, struct sockaddr *sa)
+{
+
+	return (kern_bindat(td, AT_FDCWD, fd, sa));
+}
+
+/* ARGSUSED */
+int
+sys_bindat(td, uap)
+	struct thread *td;
+	struct bindat_args /* {
+		int	fd;
+		int	s;
+		caddr_t	name;
+		int	namelen;
+	} */ *uap;
+{
+	struct sockaddr *sa;
+	int error;
+
+	error = getsockaddr(&sa, uap->name, uap->namelen);
+	if (error == 0) {
+		error = kern_bindat(td, uap->fd, uap->s, sa);
+		free(sa, M_SONAME);
+	}
+	return (error);
+}
+
 /* ARGSUSED */
 int
 sys_listen(td, uap)
@@ -435,7 +467,7 @@ kern_accept(struct thread *td, int s, st
 			*namelen = 0;
 		goto done;
 	}
-	AUDIT_ARG_SOCKADDR(td, sa);
+	AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa);
 	if (name) {
 		/* check sa_len before it is destroyed */
 		if (*namelen > sa->sa_len)
@@ -510,20 +542,15 @@ sys_connect(td, uap)
 	int error;
 
 	error = getsockaddr(&sa, uap->name, uap->namelen);
-	if (error)
-		return (error);
-
-	error = kern_connect(td, uap->s, sa);
-	free(sa, M_SONAME);
+	if (error == 0) {
+		error = kern_connect(td, uap->s, sa);
+		free(sa, M_SONAME);
+	}
 	return (error);
 }
 
-
-int
-kern_connect(td, fd, sa)
-	struct thread *td;
-	int fd;
-	struct sockaddr *sa;
+static int
+kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
 {
 	struct socket *so;
 	struct file *fp;
@@ -531,7 +558,7 @@ kern_connect(td, fd, sa)
 	int interrupted = 0;
 
 	AUDIT_ARG_FD(fd);
-	AUDIT_ARG_SOCKADDR(td, sa);
+	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
 	error = getsock_cap(td->td_proc->p_fd, fd, CAP_CONNECT, &fp, NULL);
 	if (error)
 		return (error);
@@ -549,7 +576,10 @@ kern_connect(td, fd, sa)
 	if (error)
 		goto bad;
 #endif
-	error = soconnect(so, sa, td);
+	if (dirfd == AT_FDCWD)
+		error = soconnect(so, sa, td);
+	else
+		error = soconnectat(dirfd, so, sa, td);
 	if (error)
 		goto bad;
 	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
@@ -582,6 +612,35 @@ done1:
 }
 
 int
+kern_connect(struct thread *td, int fd, struct sockaddr *sa)
+{
+
+	return (kern_connectat(td, AT_FDCWD, fd, sa));
+}
+
+/* ARGSUSED */
+int
+sys_connectat(td, uap)
+	struct thread *td;
+	struct connectat_args /* {
+		int	fd;
+		int	s;
+		caddr_t	name;
+		int	namelen;
+	} */ *uap;
+{
+	struct sockaddr *sa;
+	int error;
+
+	error = getsockaddr(&sa, uap->name, uap->namelen);
+	if (error == 0) {
+		error = kern_connectat(td, uap->fd, uap->s, sa);
+		free(sa, M_SONAME);
+	}
+	return (error);
+}
+
+int
 kern_socketpair(struct thread *td, int domain, int type, int protocol,
     int *rsv)
 {
@@ -749,7 +808,7 @@ kern_sendit(td, s, mp, flags, control, s
 	AUDIT_ARG_FD(s);
 	rights = CAP_SEND;
 	if (mp->msg_name != NULL) {
-		AUDIT_ARG_SOCKADDR(td, mp->msg_name);
+		AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name);
 		rights |= CAP_CONNECT;
 	}
 	error = getsock_cap(td->td_proc->p_fd, s, rights, &fp, NULL);
@@ -997,7 +1056,7 @@ kern_recvit(td, s, mp, fromseg, controlp
 			error = 0;
 	}
 	if (fromsa != NULL)
-		AUDIT_ARG_SOCKADDR(td, fromsa);
+		AUDIT_ARG_SOCKADDR(td, AT_FDCWD, fromsa);
 #ifdef KTRACE
 	if (ktruio != NULL) {
 		ktruio->uio_resid = len - auio.uio_resid;

Modified: head/sys/kern/uipc_usrreq.c
==============================================================================
--- head/sys/kern/uipc_usrreq.c	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/kern/uipc_usrreq.c	Sat Mar  2 21:11:30 2013	(r247667)
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
 #include "opt_ddb.h"
 
 #include <sys/param.h>
+#include <sys/capability.h>
 #include <sys/domain.h>
 #include <sys/fcntl.h>
 #include <sys/malloc.h>		/* XXX must be before <sys/file.h> */
@@ -271,6 +272,8 @@ static int	uipc_connect2(struct socket *
 static int	uipc_ctloutput(struct socket *, struct sockopt *);
 static int	unp_connect(struct socket *, struct sockaddr *,
 		    struct thread *);
+static int	unp_connectat(int, struct socket *, struct sockaddr *,
+		    struct thread *);
 static int	unp_connect2(struct socket *so, struct socket *so2, int);
 static void	unp_disconnect(struct unpcb *unp, struct unpcb *unp2);
 static void	unp_dispose(struct mbuf *);
@@ -450,7 +453,7 @@ uipc_attach(struct socket *so, int proto
 }
 
 static int
-uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
+uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
 {
 	struct sockaddr_un *soun = (struct sockaddr_un *)nam;
 	struct vattr vattr;
@@ -496,8 +499,8 @@ uipc_bind(struct socket *so, struct sock
 	buf[namelen] = 0;
 
 restart:
-	NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME,
-	    UIO_SYSSPACE, buf, td);
+	NDINIT_ATRIGHTS(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME,
+	    UIO_SYSSPACE, buf, fd, CAP_BINDAT, td);
 /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
 	error = namei(&nd);
 	if (error)
@@ -560,6 +563,13 @@ error:
 }
 
 static int
+uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
+{
+
+	return (uipc_bindat(AT_FDCWD, so, nam, td));
+}
+
+static int
 uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
 	int error;
@@ -571,6 +581,19 @@ uipc_connect(struct socket *so, struct s
 	return (error);
 }
 
+static int
+uipc_connectat(int fd, struct socket *so, struct sockaddr *nam,
+    struct thread *td)
+{
+	int error;
+
+	KASSERT(td == curthread, ("uipc_connectat: td != curthread"));
+	UNP_LINK_WLOCK();
+	error = unp_connectat(fd, so, nam, td);
+	UNP_LINK_WUNLOCK();
+	return (error);
+}
+
 static void
 uipc_close(struct socket *so)
 {
@@ -1081,7 +1104,9 @@ static struct pr_usrreqs uipc_usrreqs_dg
 	.pru_accept =		uipc_accept,
 	.pru_attach =		uipc_attach,
 	.pru_bind =		uipc_bind,
+	.pru_bindat =		uipc_bindat,
 	.pru_connect =		uipc_connect,
+	.pru_connectat =	uipc_connectat,
 	.pru_connect2 =		uipc_connect2,
 	.pru_detach =		uipc_detach,
 	.pru_disconnect =	uipc_disconnect,
@@ -1101,7 +1126,9 @@ static struct pr_usrreqs uipc_usrreqs_se
 	.pru_accept =		uipc_accept,
 	.pru_attach =		uipc_attach,
 	.pru_bind =		uipc_bind,
+	.pru_bindat =		uipc_bindat,
 	.pru_connect =		uipc_connect,
+	.pru_connectat =	uipc_connectat,
 	.pru_connect2 =		uipc_connect2,
 	.pru_detach =		uipc_detach,
 	.pru_disconnect =	uipc_disconnect,
@@ -1121,7 +1148,9 @@ static struct pr_usrreqs uipc_usrreqs_st
 	.pru_accept =		uipc_accept,
 	.pru_attach =		uipc_attach,
 	.pru_bind =		uipc_bind,
+	.pru_bindat =		uipc_bindat,
 	.pru_connect =		uipc_connect,
+	.pru_connectat =	uipc_connectat,
 	.pru_connect2 =		uipc_connect2,
 	.pru_detach =		uipc_detach,
 	.pru_disconnect =	uipc_disconnect,
@@ -1233,6 +1262,14 @@ uipc_ctloutput(struct socket *so, struct
 static int
 unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
+
+	return (unp_connectat(AT_FDCWD, so, nam, td));
+}
+
+static int
+unp_connectat(int fd, struct socket *so, struct sockaddr *nam,
+    struct thread *td)
+{
 	struct sockaddr_un *soun = (struct sockaddr_un *)nam;
 	struct vnode *vp;
 	struct socket *so2, *so3;
@@ -1265,8 +1302,8 @@ unp_connect(struct socket *so, struct so
 	UNP_PCB_UNLOCK(unp);
 
 	sa = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
-	NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
-	    UIO_SYSSPACE, buf, td);
+	NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
+	    UIO_SYSSPACE, buf, fd, CAP_CONNECTAT, td);
 	error = namei(&nd);
 	if (error)
 		vp = NULL;

Modified: head/sys/security/audit/audit.h
==============================================================================
--- head/sys/security/audit/audit.h	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/security/audit/audit.h	Sat Mar  2 21:11:30 2013	(r247667)
@@ -95,7 +95,7 @@ void	 audit_arg_pid(pid_t pid);
 void	 audit_arg_process(struct proc *p);
 void	 audit_arg_signum(u_int signum);
 void	 audit_arg_socket(int sodomain, int sotype, int soprotocol);
-void	 audit_arg_sockaddr(struct thread *td, struct sockaddr *sa);
+void	 audit_arg_sockaddr(struct thread *td, int dirfd, struct sockaddr *sa);
 void	 audit_arg_auid(uid_t auid);
 void	 audit_arg_auditinfo(struct auditinfo *au_info);
 void	 audit_arg_auditinfo_addr(struct auditinfo_addr *au_info);
@@ -267,9 +267,9 @@ void	 audit_thread_free(struct thread *t
 		audit_arg_socket((sodomain), (sotype), (soprotocol));	\
 } while (0)
 
-#define	AUDIT_ARG_SOCKADDR(td, sa) do {					\
+#define	AUDIT_ARG_SOCKADDR(td, dirfd, sa) do {				\
 	if (AUDITING_TD(curthread))					\
-		audit_arg_sockaddr((td), (sa));				\
+		audit_arg_sockaddr((td), (dirfd), (sa));		\
 } while (0)
 
 #define	AUDIT_ARG_SUID(suid) do {					\
@@ -365,7 +365,7 @@ void	 audit_thread_free(struct thread *t
 #define	AUDIT_ARG_SIGNUM(signum)
 #define	AUDIT_ARG_SGID(sgid)
 #define	AUDIT_ARG_SOCKET(sodomain, sotype, soprotocol)
-#define	AUDIT_ARG_SOCKADDR(td, sa)
+#define	AUDIT_ARG_SOCKADDR(td, dirfd, sa)
 #define	AUDIT_ARG_SUID(suid)
 #define	AUDIT_ARG_TEXT(text)
 #define	AUDIT_ARG_UID(uid)

Modified: head/sys/security/audit/audit_arg.c
==============================================================================
--- head/sys/security/audit/audit_arg.c	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/security/audit/audit_arg.c	Sat Mar  2 21:11:30 2013	(r247667)
@@ -441,7 +441,7 @@ audit_arg_socket(int sodomain, int sotyp
 }
 
 void
-audit_arg_sockaddr(struct thread *td, struct sockaddr *sa)
+audit_arg_sockaddr(struct thread *td, int dirfd, struct sockaddr *sa)
 {
 	struct kaudit_record *ar;
 
@@ -463,7 +463,9 @@ audit_arg_sockaddr(struct thread *td, st
 		break;
 
 	case AF_UNIX:
-		audit_arg_upath1(td, AT_FDCWD,
+		if (dirfd != AT_FDCWD)
+			audit_arg_atfd1(dirfd);
+		audit_arg_upath1(td, dirfd,
 		    ((struct sockaddr_un *)sa)->sun_path);
 		ARG_SET_VALID(ar, ARG_SADDRUNIX);
 		break;

Modified: head/sys/security/audit/audit_bsm.c
==============================================================================
--- head/sys/security/audit/audit_bsm.c	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/security/audit/audit_bsm.c	Sat Mar  2 21:11:30 2013	(r247667)
@@ -554,6 +554,21 @@ kaudit_to_bsm(struct kaudit_record *kar,
 		/* XXX Need to handle ARG_SADDRINET6 */
 		break;
 
+	case AUE_BINDAT:
+	case AUE_CONNECTAT:
+		ATFD1_TOKENS(1);
+		if (ARG_IS_VALID(kar, ARG_FD)) {
+			tok = au_to_arg32(2, "fd", ar->ar_arg_fd);
+			kau_write(rec, tok);
+		}
+		if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) {
+			tok = au_to_sock_unix((struct sockaddr_un *)
+			    &ar->ar_arg_sockaddr);
+			kau_write(rec, tok);
+			UPATH1_TOKENS;
+		}
+		break;
+
 	case AUE_SOCKET:
 	case AUE_SOCKETPAIR:
 		if (ARG_IS_VALID(kar, ARG_SOCKINFO)) {

Modified: head/sys/sys/capability.h
==============================================================================
--- head/sys/sys/capability.h	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/sys/capability.h	Sat Mar  2 21:11:30 2013	(r247667)
@@ -182,13 +182,18 @@
 #define	CAP_PDWAIT		0x0020000000000000ULL
 #define	CAP_PDKILL		0x0040000000000000ULL
 
+/*
+ * Rights that allow to use bindat(2) and connectat(2) syscalls on a
+ * directory descriptor.
+ */
+#define	CAP_BINDAT		0x0400000000000000ULL
+#define	CAP_CONNECTAT		0x0800000000000000ULL
+
 /* The mask of all valid method rights. */
-#define	CAP_MASK_VALID		0x03ffffffffffffffULL
+#define	CAP_MASK_VALID		0x0fffffffffffffffULL
 #define	CAP_ALL			CAP_MASK_VALID
 
 /* Available bits. */
-#define	CAP_UNUSED5		0x0400000000000000ULL
-#define	CAP_UNUSED4		0x0800000000000000ULL
 #define	CAP_UNUSED3		0x1000000000000000ULL
 #define	CAP_UNUSED2		0x2000000000000000ULL
 #define	CAP_UNUSED1		0x4000000000000000ULL

Modified: head/sys/sys/protosw.h
==============================================================================
--- head/sys/sys/protosw.h	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/sys/protosw.h	Sat Mar  2 21:11:30 2013	(r247667)
@@ -223,6 +223,10 @@ struct pr_usrreqs {
 		    struct ucred *cred, struct thread *td);
 	void	(*pru_sosetlabel)(struct socket *so);
 	void	(*pru_close)(struct socket *so);
+	int	(*pru_bindat)(int fd, struct socket *so, struct sockaddr *nam,
+		    struct thread *td);
+	int	(*pru_connectat)(int fd, struct socket *so,
+		    struct sockaddr *nam, struct thread *td);
 };
 
 /*
@@ -232,8 +236,12 @@ int	pru_accept_notsupp(struct socket *so
 int	pru_attach_notsupp(struct socket *so, int proto, struct thread *td);
 int	pru_bind_notsupp(struct socket *so, struct sockaddr *nam,
 	    struct thread *td);
+int	pru_bindat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
+	    struct thread *td);
 int	pru_connect_notsupp(struct socket *so, struct sockaddr *nam,
 	    struct thread *td);
+int	pru_connectat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
+	    struct thread *td);
 int	pru_connect2_notsupp(struct socket *so1, struct socket *so2);
 int	pru_control_notsupp(struct socket *so, u_long cmd, caddr_t data,
 	    struct ifnet *ifp, struct thread *td);

Modified: head/sys/sys/socket.h
==============================================================================
--- head/sys/sys/socket.h	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/sys/socket.h	Sat Mar  2 21:11:30 2013	(r247667)
@@ -620,7 +620,9 @@ struct sf_hdtr {
 __BEGIN_DECLS
 int	accept(int, struct sockaddr * __restrict, socklen_t * __restrict);
 int	bind(int, const struct sockaddr *, socklen_t);
+int	bindat(int, int, const struct sockaddr *, socklen_t);
 int	connect(int, const struct sockaddr *, socklen_t);
+int	connectat(int, int, const struct sockaddr *, socklen_t);
 int	getpeername(int, struct sockaddr * __restrict, socklen_t * __restrict);
 int	getsockname(int, struct sockaddr * __restrict, socklen_t * __restrict);
 int	getsockopt(int, int, int, void * __restrict, socklen_t * __restrict);

Modified: head/sys/sys/socketvar.h
==============================================================================
--- head/sys/sys/socketvar.h	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/sys/sys/socketvar.h	Sat Mar  2 21:11:30 2013	(r247667)
@@ -318,8 +318,12 @@ void	soabort(struct socket *so);
 int	soaccept(struct socket *so, struct sockaddr **nam);
 int	socheckuid(struct socket *so, uid_t uid);
 int	sobind(struct socket *so, struct sockaddr *nam, struct thread *td);
+int	sobindat(int fd, struct socket *so, struct sockaddr *nam,
+	    struct thread *td);
 int	soclose(struct socket *so);
 int	soconnect(struct socket *so, struct sockaddr *nam, struct thread *td);
+int	soconnectat(int fd, struct socket *so, struct sockaddr *nam,
+	    struct thread *td);
 int	soconnect2(struct socket *so1, struct socket *so2);
 int	socow_setup(struct mbuf *m0, struct uio *uio);
 int	socreate(int dom, struct socket **aso, int type, int proto,

Modified: head/usr.bin/procstat/procstat_files.c
==============================================================================
--- head/usr.bin/procstat/procstat_files.c	Sat Mar  2 18:51:26 2013	(r247666)
+++ head/usr.bin/procstat/procstat_files.c	Sat Mar  2 21:11:30 2013	(r247667)
@@ -215,6 +215,13 @@ static struct cap_desc {
 	{ CAP_PDWAIT,		"pw" },
 	{ CAP_PDKILL,		"pk" },
 
+	/*
+	 * Rights that allow to use bindat(2) and connectat(2) syscalls on a
+	 * directory descriptor.
+	 */
+	{ CAP_BINDAT,		"ba" },
+	{ CAP_CONNECTAT,	"ca" },
+
 	/* Aliases and defines that combine multiple rights. */
 	{ CAP_PREAD,		"prd" },
 	{ CAP_PWRITE,		"pwr" },



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303022111.r22LBVEd045583>