--- //depot/vendor/freebsd/src/contrib/openbsm/etc/audit_event 2013-03-02 21:12:13.000000000 0000 +++ //depot/user/pjd/capsicum/contrib/openbsm/etc/audit_event 2013-03-15 00:18:07.000000000 0000 @@ -570,6 +570,7 @@ 43206:AUE_CAP_FCNTLS_GET:cap_fcntls_get(2):fm 43207:AUE_BINDAT:bindat(2):nt 43208:AUE_CONNECTAT:connectat(2):nt +43209:AUE_FCHFLAGSAT:fchflagsat(2):fm # # Solaris userspace events. # --- //depot/vendor/freebsd/src/lib/libc/sys/Symbol.map 2013-03-02 21:12:13.000000000 0000 +++ //depot/user/pjd/capsicum/lib/libc/sys/Symbol.map 2013-03-15 00:18:34.000000000 0000 @@ -388,6 +388,7 @@ cap_sandboxed; clock_getcpuclockid2; connectat; + fchflagsat; ffclock_getcounter; ffclock_getestimate; ffclock_setestimate; --- //depot/vendor/freebsd/src/lib/libc/sys/cap_rights_limit.2 2013-03-02 21:12:13.000000000 0000 +++ //depot/user/pjd/capsicum/lib/libc/sys/cap_rights_limit.2 2013-03-15 00:20:35.000000000 0000 @@ -159,7 +159,12 @@ .Xr fchdir 2 . .It Dv CAP_FCHFLAGS Permit -.Xr fchflags 2 . +.Xr fchflags 2 +and +.Xr fchflagsat 2 . +.It Dv CAP_FCHFLAGSAT +An alias to +.Dv CAP_FCHFLAGS . .It Dv CAP_FCHMOD Permit .Xr fchmod 2 --- //depot/vendor/freebsd/src/lib/libc/sys/chflags.2 2013-02-09 17:14:12.000000000 0000 +++ //depot/user/pjd/capsicum/lib/libc/sys/chflags.2 2013-03-15 21:16:26.000000000 0000 @@ -47,6 +47,8 @@ .Fn lchflags "const char *path" "int flags" .Ft int .Fn fchflags "int fd" "u_long flags" +.Ft int +.Fn fchflagsat "int fd" "const char *path" "u_long fflags" "int atflag" .Sh DESCRIPTION The file whose name is given by --- //depot/vendor/freebsd/src/sys/bsm/audit_kevents.h 2013-03-02 21:12:13.000000000 0000 +++ //depot/user/pjd/capsicum/sys/bsm/audit_kevents.h 2013-03-15 00:12:45.000000000 0000 @@ -610,6 +611,7 @@ #define AUE_CAP_FCNTLS_GET 43206 /* TrustedBSD. */ #define AUE_BINDAT 43207 /* TrustedBSD. */ #define AUE_CONNECTAT 43208 /* TrustedBSD. */ +#define AUE_FCHFLAGSAT 43209 /* FreeBSD-specific. */ /* * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the --- //depot/vendor/freebsd/src/sys/compat/freebsd32/syscalls.master 2013-03-02 21:12:13.000000000 0000 +++ //depot/user/pjd/capsicum/sys/compat/freebsd32/syscalls.master 2013-03-15 00:12:45.000000000 0000 @@ -1019,3 +1019,5 @@ int namelen); } 539 AUE_CONNECTAT NOPROTO { int connectat(int fd, int s, caddr_t name, \ int namelen); } +540 AUE_FCHFLAGSAT NOPROTO { int fchflagsat(int fd, char *path, \ + int fflags, int atflag); } --- //depot/vendor/freebsd/src/sys/kern/capabilities.conf 2013-03-02 21:12:13.000000000 0000 +++ //depot/user/pjd/capsicum/sys/kern/capabilities.conf 2013-03-15 00:13:43.000000000 0000 @@ -446,9 +446,10 @@ ## Operations relative to directory capabilities. ## faccessat -fstatat +fchflagsat fchmodat fchownat +fstatat futimesat linkat mkdirat --- //depot/vendor/freebsd/src/sys/kern/syscalls.master 2013-03-02 21:12:13.000000000 0000 +++ //depot/user/pjd/capsicum/sys/kern/syscalls.master 2013-03-15 00:12:45.000000000 0000 @@ -969,5 +969,7 @@ int namelen); } 539 AUE_CONNECTAT STD { int connectat(int fd, int s, caddr_t name, \ int namelen); } +540 AUE_FCHFLAGSAT STD { int fchflagsat(int fd, char *path, \ + int fflags, int atflag); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master --- //depot/vendor/freebsd/src/sys/kern/vfs_syscalls.c 2013-03-09 02:33:14.000000000 0000 +++ //depot/user/pjd/capsicum/sys/kern/vfs_syscalls.c 2013-03-15 00:12:45.000000000 0000 @@ -101,6 +101,10 @@ static int chroot_refuse_vdir_fds(struct filedesc *fdp); static int getutimes(const struct timeval *, enum uio_seg, struct timespec *); +static int kern_chflags(struct thread *td, const char *path, + enum uio_seg pathseg, int flags); +static int kern_fchflagsat(struct thread *td, int fd, const char *path, + enum uio_seg pathseg, int fflags, int atflag); static int setfflags(struct thread *td, struct vnode *, int); static int setutimes(struct thread *td, struct vnode *, const struct timespec *, int, int); @@ -2669,17 +2673,38 @@ int flags; } */ *uap; { - int error; - struct nameidata nd; + + return (kern_chflags(td, uap->path, UIO_USERSPACE, uap->flags)); +} + +#ifndef _SYS_SYSPROTO_H_ +struct fchflagsat_args { + int dirfd; + char *path; + int fflags; + int atflag; +} +#endif +int +sys_fchflagsat(struct thread *td, struct fchflagsat_args *uap) +{ + int atflag = uap->atflag; + int fd = uap->fd; + char *path = uap->path; + int fflags = uap->fflags; + + if (atflag & ~AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + return (kern_fchflagsat(td, fd, path, UIO_USERSPACE, fflags, atflag)); +} + +static int +kern_chflags(struct thread *td, const char *path, enum uio_seg pathseg, + int flags) +{ - AUDIT_ARG_FFLAGS(uap->flags); - NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td); - if ((error = namei(&nd)) != 0) - return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfflags(td, nd.ni_vp, uap->flags); - vrele(nd.ni_vp); - return (error); + return (kern_fchflagsat(td, AT_FDCWD, path, pathseg, flags, 0)); } /* @@ -2689,20 +2714,30 @@ sys_lchflags(td, uap) struct thread *td; register struct lchflags_args /* { - char *path; + const char *path; int flags; } */ *uap; { - int error; + + return (kern_fchflagsat(td, AT_FDCWD, uap->path, UIO_USERSPACE, + uap->flags, AT_SYMLINK_NOFOLLOW)); +} + +static int +kern_fchflagsat(struct thread *td, int fd, const char *path, + enum uio_seg pathseg, int fflags, int atflag) +{ struct nameidata nd; + int error, follow; - AUDIT_ARG_FFLAGS(uap->flags); - NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, - td); + AUDIT_ARG_FFLAGS(fflags); + follow = (atflag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; + NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd, + CAP_FCHFLAGS, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfflags(td, nd.ni_vp, uap->flags); + error = setfflags(td, nd.ni_vp, fflags); vrele(nd.ni_vp); return (error); } --- //depot/vendor/freebsd/src/sys/sys/capability.h 2013-03-02 21:12:13.000000000 0000 +++ //depot/user/pjd/capsicum/sys/sys/capability.h 2013-03-15 00:20:35.000000000 0000 @@ -102,6 +102,7 @@ /* VFS methods. */ #define CAP_FCHDIR 0x0000000000000200ULL #define CAP_FCHFLAGS 0x0000000000000100ULL +#define CAP_FCHFLAGSAT CAP_FCHFLAGS #define CAP_FCHMOD 0x0000000000000400ULL #define CAP_FCHMODAT CAP_FCHMOD #define CAP_FCHOWN 0x0000000000000800ULL --- //depot/vendor/freebsd/src/sys/sys/stat.h 2012-11-05 07:02:52.000000000 0000 +++ //depot/user/pjd/capsicum/sys/sys/stat.h 2013-03-15 00:21:08.000000000 0000 @@ -297,6 +297,7 @@ int chmod(const char *, mode_t); #if __BSD_VISIBLE int fchflags(int, unsigned long); +int fchflagsat(int, const char *, unsigned long, int); #endif #if __POSIX_VISIBLE >= 200112 int fchmod(int, mode_t); --- //depot/vendor/freebsd/src/tools/regression/pjdfstest/Makefile 2013-03-02 21:17:12.000000000 0000 +++ //depot/user/pjd/capsicum/tools/regression/pjdfstest/Makefile 2013-03-15 00:21:43.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 -DHAS_BINDAT -DHAS_CONNECTAT"; \ + CFLAGS="$$CFLAGS -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_FCHFLAGS -DHAS_FCHFLAGSAT -DHAS_LCHFLAGS -DHAS_FREEBSD_ACL -DHAS_BINDAT -DHAS_CONNECTAT"; \ elif [ $$OSTYPE = "SunOS" ]; then \ CFLAGS="$$CFLAGS -DHAS_TRUNCATE64 -DHAS_STAT64"; \ CFLAGS="$$CFLAGS -lsocket"; \ --- //depot/vendor/freebsd/src/tools/regression/pjdfstest/pjdfstest.c 2013-03-02 21:17:12.000000000 0000 +++ //depot/user/pjd/capsicum/tools/regression/pjdfstest/pjdfstest.c 2013-03-15 00:21:43.000000000 0000 @@ -105,6 +105,9 @@ #ifdef HAS_FCHFLAGS ACTION_FCHFLAGS, #endif +#ifdef HAS_FCHFLAGSAT + ACTION_FCHFLAGSAT, +#endif #ifdef HAS_LCHFLAGS ACTION_LCHFLAGS, #endif @@ -183,6 +186,9 @@ #ifdef HAS_FCHFLAGS { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, #endif +#ifdef HAS_FCHFLAGSAT + { "fchflagsat", ACTION_FCHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, +#endif #ifdef HAS_LCHFLAGS { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, #endif @@ -306,6 +312,11 @@ { 0, NULL } }; +static struct flag fchflagsat_flags[] = { + { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, + { 0, NULL } +}; + static struct flag fchmodat_flags[] = { { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, { 0, NULL } @@ -829,6 +840,13 @@ (unsigned long)str2flags(chflags_flags, STR(1))); break; #endif +#ifdef HAS_FCHFLAGS + case ACTION_FCHFLAGSAT: + rval = fchflagsat(NUM(0), STR(1), + (unsigned long)str2flags(chflags_flags, STR(2)), + (unsigned long)str2flags(fchflagsat_flags, STR(3))); + break; +#endif #ifdef HAS_LCHFLAGS case ACTION_LCHFLAGS: rval = lchflags(STR(0), (int)str2flags(chflags_flags, STR(1)));