aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPawel Jakub Dawidek <pjd@FreeBSD.org>2013-03-02 21:11:30 +0000
committerPawel Jakub Dawidek <pjd@FreeBSD.org>2013-03-02 21:11:30 +0000
commit7493f24ee6846df33931904c87493b08400df5bd (patch)
tree5dbc48bdb7b78718e22183ef377b76f2e3bc74c2 /sys
parent136b1ada11e4b3ec91b4b15562ba803e5ab66c10 (diff)
downloadsrc-7493f24ee6846df33931904c87493b08400df5bd.tar.gz
src-7493f24ee6846df33931904c87493b08400df5bd.zip
- 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
Notes
Notes: svn path=/head/; revision=247667
Diffstat (limited to 'sys')
-rw-r--r--sys/bsm/audit_kevents.h2
-rw-r--r--sys/compat/freebsd32/syscalls.master4
-rw-r--r--sys/kern/capabilities.conf12
-rw-r--r--sys/kern/syscalls.master4
-rw-r--r--sys/kern/uipc_domain.c2
-rw-r--r--sys/kern/uipc_socket.c46
-rw-r--r--sys/kern/uipc_syscalls.c117
-rw-r--r--sys/kern/uipc_usrreq.c47
-rw-r--r--sys/security/audit/audit.h8
-rw-r--r--sys/security/audit/audit_arg.c6
-rw-r--r--sys/security/audit/audit_bsm.c15
-rw-r--r--sys/sys/capability.h11
-rw-r--r--sys/sys/protosw.h8
-rw-r--r--sys/sys/socket.h2
-rw-r--r--sys/sys/socketvar.h4
15 files changed, 234 insertions, 54 deletions
diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
index 9d71fa28335c..d56a96b4e687 100644
--- a/sys/bsm/audit_kevents.h
+++ b/sys/bsm/audit_kevents.h
@@ -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
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 6552d137e5a0..655296c779ef 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -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); }
diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf
index 3c087827d8b6..71c22bf2264f 100644
--- a/sys/kern/capabilities.conf
+++ b/sys/kern/capabilities.conf
@@ -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
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 1a890104c56f..9c22f2ba9e9f 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -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
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index c1462328ed74..709cc0eb0569 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -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);
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index de8ae5a7243d..7fcac1ceef36 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -615,7 +615,18 @@ sobind(struct socket *so, struct sockaddr *nam, struct thread *td)
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, struct thread *td)
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 sockaddr **nam)
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 sockaddr *nam, struct thread *td)
* 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, struct sockaddr *nam, struct thread *td)
}
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, struct sockaddr *nam, struct thread *td)
}
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)
{
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 847db35b5038..cd37a4d24dba 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -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, struct sockaddr **name,
*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, segflg)
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;
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index dcfd009d62a6..1da80e0cedbc 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -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 *, 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, struct thread *td)
}
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 sockaddr *nam, struct thread *td)
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 sockaddr *nam, struct thread *td)
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_dgram = {
.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_seqpacket = {
.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_stream = {
.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 sockopt *sopt)
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 sockaddr *nam, struct thread *td)
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;
diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h
index 733a3c79166f..dd55875be5b4 100644
--- a/sys/security/audit/audit.h
+++ b/sys/security/audit/audit.h
@@ -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 *td);
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 *td);
#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)
diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c
index ec04b8bef7be..4927be0d1349 100644
--- a/sys/security/audit/audit_arg.c
+++ b/sys/security/audit/audit_arg.c
@@ -441,7 +441,7 @@ audit_arg_socket(int sodomain, int sotype, int soprotocol)
}
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, struct sockaddr *sa)
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;
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
index 9c69b1e040d6..03b3c23e5c42 100644
--- a/sys/security/audit/audit_bsm.c
+++ b/sys/security/audit/audit_bsm.c
@@ -554,6 +554,21 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
/* 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)) {
diff --git a/sys/sys/capability.h b/sys/sys/capability.h
index 27e56c2952ec..0d1ea5c16ac9 100644
--- a/sys/sys/capability.h
+++ b/sys/sys/capability.h
@@ -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
diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h
index 78d6e069a05b..8553bafdff16 100644
--- a/sys/sys/protosw.h
+++ b/sys/sys/protosw.h
@@ -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, struct sockaddr **nam);
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);
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index c29a689b5915..632dae4bc88c 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -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);
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 9012f24065e5..77f31df336a7 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -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,