--- //depot/user/pjd/capsicum/contrib/openbsm/etc/audit_event 2013-02-06 22:59:43.000000000 0000 +++ //depot/user/pjd/bindconnectat/contrib/openbsm/etc/audit_event 2013-02-07 00:03:01.000000000 0000 @@ -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. # --- //depot/user/pjd/capsicum/lib/libc/sys/Symbol.map 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/lib/libc/sys/Symbol.map 2013-02-05 20:44:17.000000000 0000 @@ -378,6 +378,7 @@ }; FBSD_1.3 { + bindat; cap_fcntls_get; cap_fcntls_limit; cap_ioctls_get; @@ -385,6 +386,7 @@ cap_rights_get; cap_rights_limit; clock_getcpuclockid2; + connectat; ffclock_getcounter; ffclock_getestimate; ffclock_setestimate; --- //depot/user/pjd/capsicum/sys/bsm/audit_kevents.h 2013-02-13 02:50:42.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/bsm/audit_kevents.h 2013-02-13 02:51:24.000000000 0000 @@ -609,6 +609,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 --- //depot/user/pjd/capsicum/sys/compat/freebsd32/freebsd32_proto.h 2013-01-21 16:39:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/compat/freebsd32/freebsd32_proto.h 2013-02-05 19:53:10.000000000 0000 @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/compat/freebsd32/freebsd32_proto.h 242959 2012-11-13 12:53:41Z kib $ + * $FreeBSD$ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib */ --- //depot/user/pjd/capsicum/sys/compat/freebsd32/freebsd32_syscall.h 2013-01-23 13:06:01.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/compat/freebsd32/freebsd32_syscall.h 2013-02-05 19:53:10.000000000 0000 @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscall.h 242959 2012-11-13 12:53:41Z kib $ + * $FreeBSD$ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib */ @@ -435,4 +435,6 @@ #define FREEBSD32_SYS_cap_ioctls_get 535 #define FREEBSD32_SYS_cap_fcntls_limit 536 #define FREEBSD32_SYS_cap_fcntls_get 537 -#define FREEBSD32_SYS_MAXSYSCALL 538 +#define FREEBSD32_SYS_bindat 538 +#define FREEBSD32_SYS_connectat 539 +#define FREEBSD32_SYS_MAXSYSCALL 540 --- //depot/user/pjd/capsicum/sys/compat/freebsd32/freebsd32_syscalls.c 2013-01-21 16:39:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/compat/freebsd32/freebsd32_syscalls.c 2013-02-05 19:53:10.000000000 0000 @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscalls.c 242959 2012-11-13 12:53:41Z kib $ + * $FreeBSD$ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib */ @@ -561,4 +561,6 @@ "cap_ioctls_get", /* 535 = cap_ioctls_get */ "cap_fcntls_limit", /* 536 = cap_fcntls_limit */ "cap_fcntls_get", /* 537 = cap_fcntls_get */ + "bindat", /* 538 = bindat */ + "connectat", /* 539 = connectat */ }; --- //depot/user/pjd/capsicum/sys/compat/freebsd32/freebsd32_sysent.c 2013-01-21 16:39:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/compat/freebsd32/freebsd32_sysent.c 2013-02-05 19:53:10.000000000 0000 @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/compat/freebsd32/freebsd32_sysent.c 242959 2012-11-13 12:53:41Z kib $ + * $FreeBSD$ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib */ @@ -598,4 +598,6 @@ { AS(cap_ioctls_get_args), (sy_call_t *)sys_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 535 = cap_ioctls_get */ { AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 536 = cap_fcntls_limit */ { AS(cap_fcntls_get_args), (sy_call_t *)sys_cap_fcntls_get, AUE_CAP_FCNTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 537 = cap_fcntls_get */ + { AS(bindat_args), (sy_call_t *)sys_bindat, AUE_BINDAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 538 = bindat */ + { AS(connectat_args), (sy_call_t *)sys_connectat, AUE_CONNECTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 539 = connectat */ }; --- //depot/user/pjd/capsicum/sys/compat/freebsd32/freebsd32_systrace_args.c 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/compat/freebsd32/freebsd32_systrace_args.c 2013-02-05 19:53:10.000000000 0000 @@ -2,7 +2,7 @@ * System call argument to DTrace register array converstion. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/compat/freebsd32/freebsd32_systrace_args.c 242959 2012-11-13 12:53:41Z kib $ + * $FreeBSD$ * This file is part of the DTrace syscall provider. */ @@ -3130,6 +3130,26 @@ *n_args = 2; break; } + /* bindat */ + case 538: { + struct bindat_args *p = params; + iarg[0] = p->fd; /* int */ + iarg[1] = p->s; /* int */ + uarg[2] = (intptr_t) p->name; /* caddr_t */ + iarg[3] = p->namelen; /* int */ + *n_args = 4; + break; + } + /* connectat */ + case 539: { + struct connectat_args *p = params; + iarg[0] = p->fd; /* int */ + iarg[1] = p->s; /* int */ + uarg[2] = (intptr_t) p->name; /* caddr_t */ + iarg[3] = p->namelen; /* int */ + *n_args = 4; + break; + } default: *n_args = 0; break; @@ -8356,6 +8376,44 @@ break; }; break; + /* bindat */ + case 538: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "int"; + break; + case 2: + p = "caddr_t"; + break; + case 3: + p = "int"; + break; + default: + break; + }; + break; + /* connectat */ + case 539: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "int"; + break; + case 2: + p = "caddr_t"; + break; + case 3: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10143,6 +10201,16 @@ if (ndx == 0 || ndx == 1) p = "int"; break; + /* bindat */ + case 538: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* connectat */ + case 539: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; --- //depot/user/pjd/capsicum/sys/compat/freebsd32/syscalls.master 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/compat/freebsd32/syscalls.master 2013-02-05 19:48:17.000000000 0000 @@ -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); } --- //depot/user/pjd/capsicum/sys/kern/capabilities.conf 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/kern/capabilities.conf 2013-02-06 21:14:46.000000000 0000 @@ -105,6 +105,10 @@ ## XXXRW: Revisit this. ## #bind +## +## ...but allow bindat(2). +## +bindat ## ## Allow capability mode and capability system calls. @@ -137,6 +141,10 @@ ## XXXRW: Revisit this. ## #connect +## +## ...but allow connectat(2). +## +connectat ## ## cpuset(2) and related calls require scoping by process, but should --- //depot/user/pjd/capsicum/sys/kern/init_sysent.c 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/kern/init_sysent.c 2013-02-06 21:24:01.000000000 0000 @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/kern/init_sysent.c 243611 2012-11-27 10:25:03Z pjd $ + * $FreeBSD$ * created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib */ @@ -572,4 +572,6 @@ { AS(cap_ioctls_get_args), (sy_call_t *)sys_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 535 = cap_ioctls_get */ { AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 536 = cap_fcntls_limit */ { AS(cap_fcntls_get_args), (sy_call_t *)sys_cap_fcntls_get, AUE_CAP_FCNTLS_GET, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 537 = cap_fcntls_get */ + { AS(bindat_args), (sy_call_t *)sys_bindat, AUE_BINDAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 538 = bindat */ + { AS(connectat_args), (sy_call_t *)sys_connectat, AUE_CONNECTAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 539 = connectat */ }; --- //depot/user/pjd/capsicum/sys/kern/syscalls.c 2013-01-21 16:39:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/kern/syscalls.c 2013-02-05 19:53:10.000000000 0000 @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/kern/syscalls.c 242959 2012-11-13 12:53:41Z kib $ + * $FreeBSD$ * created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib */ @@ -545,4 +545,6 @@ "cap_ioctls_get", /* 535 = cap_ioctls_get */ "cap_fcntls_limit", /* 536 = cap_fcntls_limit */ "cap_fcntls_get", /* 537 = cap_fcntls_get */ + "bindat", /* 538 = bindat */ + "connectat", /* 539 = connectat */ }; --- //depot/user/pjd/capsicum/sys/kern/syscalls.master 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/kern/syscalls.master 2013-02-05 19:48:17.000000000 0000 @@ -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 --- //depot/user/pjd/capsicum/sys/kern/systrace_args.c 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/kern/systrace_args.c 2013-02-05 19:53:10.000000000 0000 @@ -2,7 +2,7 @@ * System call argument to DTrace register array converstion. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/kern/systrace_args.c 242959 2012-11-13 12:53:41Z kib $ + * $FreeBSD$ * This file is part of the DTrace syscall provider. */ @@ -3328,6 +3328,26 @@ *n_args = 2; break; } + /* bindat */ + case 538: { + struct bindat_args *p = params; + iarg[0] = p->fd; /* int */ + iarg[1] = p->s; /* int */ + uarg[2] = (intptr_t) p->name; /* caddr_t */ + iarg[3] = p->namelen; /* int */ + *n_args = 4; + break; + } + /* connectat */ + case 539: { + struct connectat_args *p = params; + iarg[0] = p->fd; /* int */ + iarg[1] = p->s; /* int */ + uarg[2] = (intptr_t) p->name; /* caddr_t */ + iarg[3] = p->namelen; /* int */ + *n_args = 4; + break; + } default: *n_args = 0; break; @@ -8858,6 +8878,44 @@ break; }; break; + /* bindat */ + case 538: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "int"; + break; + case 2: + p = "caddr_t"; + break; + case 3: + p = "int"; + break; + default: + break; + }; + break; + /* connectat */ + case 539: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "int"; + break; + case 2: + p = "caddr_t"; + break; + case 3: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10776,6 +10834,16 @@ if (ndx == 0 || ndx == 1) p = "int"; break; + /* bindat */ + case 538: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* connectat */ + case 539: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; --- //depot/user/pjd/capsicum/sys/kern/uipc_domain.c 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/kern/uipc_domain.c 2013-02-05 00:53:19.000000000 0000 @@ -138,6 +138,7 @@ DEFAULT(pu->pru_bind, pru_bind_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); --- //depot/user/pjd/capsicum/sys/kern/uipc_socket.c 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/kern/uipc_socket.c 2013-02-06 22:06:32.000000000 0000 @@ -615,7 +615,18 @@ 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 @@ 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 @@ 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 @@ * 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 @@ } 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 @@ } 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) { --- //depot/user/pjd/capsicum/sys/kern/uipc_syscalls.c 2013-02-07 00:47:20.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/kern/uipc_syscalls.c 2013-02-07 00:53:50.000000000 0000 @@ -209,18 +209,15 @@ 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 @@ #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; + + if ((error = getsockaddr(&sa, uap->name, uap->namelen)) != 0) + return (error); + + 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 @@ *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) @@ -518,12 +550,8 @@ 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 +559,7 @@ 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 +577,10 @@ 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 +613,36 @@ } 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) + return (error); + + 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 +810,7 @@ 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 +1058,7 @@ 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; --- //depot/user/pjd/capsicum/sys/kern/uipc_usrreq.c 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/kern/uipc_usrreq.c 2013-02-06 22:06:32.000000000 0000 @@ -62,6 +62,7 @@ #include "opt_ddb.h" #include +#include #include #include #include /* XXX must be before */ @@ -271,6 +272,8 @@ 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 @@ } 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 @@ 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 @@ } 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 @@ 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 @@ .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 @@ .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 @@ .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 @@ 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_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; --- //depot/user/pjd/capsicum/sys/security/audit/audit.h 2013-02-13 02:50:42.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/security/audit/audit.h 2013-02-13 02:51:24.000000000 0000 @@ -95,7 +95,7 @@ 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 @@ 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 @@ #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) --- //depot/user/pjd/capsicum/sys/security/audit/audit_arg.c 2013-02-13 02:50:42.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/security/audit/audit_arg.c 2013-02-13 02:51:24.000000000 0000 @@ -441,7 +441,7 @@ } 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 @@ 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; --- //depot/user/pjd/capsicum/sys/security/audit/audit_bsm.c 2013-02-13 02:50:42.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/security/audit/audit_bsm.c 2013-02-13 02:51:24.000000000 0000 @@ -554,6 +554,21 @@ /* 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)) { --- //depot/user/pjd/capsicum/sys/sys/capability.h 2013-02-13 02:50:42.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/sys/capability.h 2013-02-13 02:51:24.000000000 0000 @@ -177,8 +177,14 @@ #define CAP_PDWAIT 0x0020000000000000ULL #define CAP_PDKILL 0x0040000000000000ULL + * Rights that allow to use bindat(2) and connectat(2) syscalls on a + * directory descriptor. +/* The mask of all valid method rights. */ +#define CAP_BINDAT 0x0200000000000000ULL +#define CAP_CONNECTAT 0x0400000000000000ULL + /* The mask of all valid method rights. */ -#define CAP_MASK_VALID 0x01ffffffffffffffULL +#define CAP_MASK_VALID 0x07ffffffffffffffULL #define CAP_ALL CAP_MASK_VALID /* --- //depot/user/pjd/capsicum/sys/sys/protosw.h 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/sys/protosw.h 2013-02-06 22:06:32.000000000 0000 @@ -203,7 +203,7 @@ int (*pru_peeraddr)(struct socket *so, struct sockaddr **nam); int (*pru_rcvd)(struct socket *so, int flags); int (*pru_rcvoob)(struct socket *so, struct mbuf *m, int flags); - int (*pru_send)(struct socket *so, int flags, struct mbuf *m, + int (*pru_send)(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, struct mbuf *control, struct thread *td); #define PRUS_OOB 0x1 @@ -211,7 +211,7 @@ #define PRUS_MORETOCOME 0x4 int (*pru_sense)(struct socket *so, struct stat *sb); int (*pru_shutdown)(struct socket *so); - int (*pru_flush)(struct socket *so, int direction); + int (*pru_flush)(struct socket *so, int direction); int (*pru_sockaddr)(struct socket *so, struct sockaddr **nam); int (*pru_sosend)(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, @@ -223,6 +223,10 @@ 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_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); --- //depot/user/pjd/capsicum/sys/sys/socket.h 2013-02-04 20:44:06.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/sys/socket.h 2013-02-05 22:18:22.000000000 0000 @@ -620,7 +620,9 @@ __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); --- //depot/user/pjd/capsicum/sys/sys/socketvar.h 2013-01-21 16:23:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/sys/socketvar.h 2013-02-06 22:06:32.000000000 0000 @@ -318,8 +318,12 @@ 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, --- //depot/user/pjd/capsicum/sys/sys/syscall.h 2013-01-21 16:39:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/sys/syscall.h 2013-02-05 19:53:10.000000000 0000 @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/sys/syscall.h 242959 2012-11-13 12:53:41Z kib $ + * $FreeBSD$ * created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib */ @@ -457,4 +457,6 @@ #define SYS_cap_ioctls_get 535 #define SYS_cap_fcntls_limit 536 #define SYS_cap_fcntls_get 537 -#define SYS_MAXSYSCALL 538 +#define SYS_bindat 538 +#define SYS_connectat 539 +#define SYS_MAXSYSCALL 540 --- //depot/user/pjd/capsicum/sys/sys/syscall.mk 2013-01-21 16:39:53.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/sys/syscall.mk 2013-02-05 19:53:10.000000000 0000 @@ -1,6 +1,6 @@ # FreeBSD system call names. # DO NOT EDIT-- this file is automatically generated. -# $FreeBSD: head/sys/sys/syscall.mk 242959 2012-11-13 12:53:41Z kib $ +# $FreeBSD$ # created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib MIASM = \ syscall.o \ @@ -405,4 +405,6 @@ cap_ioctls_limit.o \ cap_ioctls_get.o \ cap_fcntls_limit.o \ - cap_fcntls_get.o + cap_fcntls_get.o \ + bindat.o \ + connectat.o --- //depot/user/pjd/capsicum/sys/sys/sysproto.h 2013-01-23 13:06:01.000000000 0000 +++ //depot/user/pjd/bindconnectat/sys/sys/sysproto.h 2013-02-05 19:53:10.000000000 0000 @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: head/sys/sys/sysproto.h 242959 2012-11-13 12:53:41Z kib $ + * $FreeBSD$ * created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib */ @@ -1784,6 +1784,18 @@ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char fcntlrightsp_l_[PADL_(uint32_t *)]; uint32_t * fcntlrightsp; char fcntlrightsp_r_[PADR_(uint32_t *)]; }; +struct bindat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; + char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)]; + char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)]; +}; +struct connectat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; + char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)]; + char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_sys_exit(struct thread *, struct sys_exit_args *); int sys_fork(struct thread *, struct fork_args *); @@ -2171,6 +2183,8 @@ int sys_cap_ioctls_get(struct thread *, struct cap_ioctls_get_args *); int sys_cap_fcntls_limit(struct thread *, struct cap_fcntls_limit_args *); int sys_cap_fcntls_get(struct thread *, struct cap_fcntls_get_args *); +int sys_bindat(struct thread *, struct bindat_args *); +int sys_connectat(struct thread *, struct connectat_args *); #ifdef COMPAT_43 @@ -2872,6 +2886,8 @@ #define SYS_AUE_cap_ioctls_get AUE_CAP_IOCTLS_GET #define SYS_AUE_cap_fcntls_limit AUE_CAP_FCNTLS_LIMIT #define SYS_AUE_cap_fcntls_get AUE_CAP_FCNTLS_GET +#define SYS_AUE_bindat AUE_BINDAT +#define SYS_AUE_connectat AUE_CONNECTAT #undef PAD_ #undef PADL_ --- //depot/user/pjd/capsicum/tools/regression/pjdfstest/Makefile 2012-11-20 00:03:58.000000000 0000 +++ //depot/user/pjd/bindconnectat/tools/regression/pjdfstest/Makefile 2013-02-05 22:19:05.000000000 0000 @@ -6,7 +6,7 @@ @OSTYPE=`uname`; \ CFLAGS=-D__OS_$${OSTYPE}__; \ if [ $$OSTYPE = "FreeBSD" ]; then \ - CFLAGS="$$CFLAGS -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_FCHFLAGS -DHAS_LCHFLAGS -DHAS_FREEBSD_ACL"; \ + CFLAGS="$$CFLAGS -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_FCHFLAGS -DHAS_LCHFLAGS -DHAS_FREEBSD_ACL -DHAS_BINDAT -DHAS_CONNECTAT"; \ elif [ $$OSTYPE = "SunOS" ]; then \ CFLAGS="$$CFLAGS -DHAS_TRUNCATE64 -DHAS_STAT64"; \ CFLAGS="$$CFLAGS -lsocket"; \ --- //depot/user/pjd/capsicum/tools/regression/pjdfstest/pjdfstest.c 2012-11-20 00:03:58.000000000 0000 +++ //depot/user/pjd/bindconnectat/tools/regression/pjdfstest/pjdfstest.c 2013-02-05 22:19:05.000000000 0000 @@ -82,7 +82,13 @@ ACTION_MKNOD, ACTION_MKNODAT, ACTION_BIND, +#ifdef HAS_BINDAT + ACTION_BINDAT, +#endif ACTION_CONNECT, +#ifdef HAS_CONNECTAT + ACTION_CONNECTAT, +#endif ACTION_CHMOD, ACTION_FCHMOD, #ifdef HAS_LCHMOD @@ -154,7 +160,13 @@ { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } }, +#ifdef HAS_BINDAT + { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, +#endif { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } }, +#ifdef HAS_CONNECTAT + { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, +#endif { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } }, #ifdef HAS_LCHMOD @@ -732,6 +744,22 @@ rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } +#ifdef HAS_BINDAT + case ACTION_BINDAT: + { + struct sockaddr_un sunx; + + sunx.sun_family = AF_UNIX; + strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); + sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; + rval = socket(AF_UNIX, SOCK_STREAM, 0); + if (rval < 0) + break; + rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx, + sizeof(sunx)); + break; + } +#endif case ACTION_CONNECT: { struct sockaddr_un sunx; @@ -745,6 +773,22 @@ rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } +#ifdef HAS_CONNECTAT + case ACTION_CONNECTAT: + { + struct sockaddr_un sunx; + + sunx.sun_family = AF_UNIX; + strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); + sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; + rval = socket(AF_UNIX, SOCK_STREAM, 0); + if (rval < 0) + break; + rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx, + sizeof(sunx)); + break; + } +#endif case ACTION_CHMOD: rval = chmod(STR(0), (mode_t)NUM(1)); break;