Index: coda/coda_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/coda/coda_vfsops.c,v retrieving revision 1.23 diff -u -r1.23 coda_vfsops.c --- coda_vfsops.c 1999/12/15 23:01:33 1.23 +++ coda_vfsops.c 1999/12/18 01:45:40 @@ -534,7 +534,9 @@ vfs_stdfhtovp, vfs_stdcheckexp, vfs_stdvptofh, - vfs_stdinit + vfs_stdinit, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(coda_vfsops, coda, VFCF_NETWORK); Index: conf/files =================================================================== RCS file: /home/ncvs/src/sys/conf/files,v retrieving revision 1.302 diff -u -r1.302 files --- files 1999/12/16 00:19:47 1.302 +++ files 1999/12/18 01:45:41 @@ -328,6 +328,7 @@ kern/link_aout.c standard kern/link_elf.c standard kern/kern_acct.c standard +kern/kern_acl.c standard kern/kern_clock.c standard kern/kern_conf.c standard kern/kern_descrip.c standard Index: fs/hpfs/hpfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/hpfs/hpfs_vfsops.c,v retrieving revision 1.1 diff -u -r1.1 hpfs_vfsops.c --- hpfs_vfsops.c 1999/12/09 19:10:00 1.1 +++ hpfs_vfsops.c 1999/12/18 01:45:41 @@ -738,7 +738,8 @@ hpfs_checkexp, hpfs_vptofh, hpfs_init, - NULL + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(hpfs_vfsops, hpfs, 0); #else /* defined(__NetBSD__) */ Index: gnu/ext2fs/ext2_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/gnu/ext2fs/ext2_vfsops.c,v retrieving revision 1.59 diff -u -r1.59 ext2_vfsops.c --- ext2_vfsops.c 1999/12/15 23:01:43 1.59 +++ ext2_vfsops.c 1999/12/18 01:45:41 @@ -97,6 +97,8 @@ ufs_check_export, ext2_vptofh, ext2_init, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(ext2fs_vfsops, ext2fs, 0); Index: isofs/cd9660/cd9660_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v retrieving revision 1.70 diff -u -r1.70 cd9660_vfsops.c --- cd9660_vfsops.c 1999/12/15 23:01:50 1.70 +++ cd9660_vfsops.c 1999/12/18 01:45:41 @@ -88,6 +88,8 @@ cd9660_checkexp, cd9660_vptofh, cd9660_init, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(cd9660_vfsops, cd9660, VFCF_READONLY); Index: kern/kern_acl.c =================================================================== RCS file: kern_acl.c diff -N kern_acl.c --- /dev/null Sat Dec 18 05:23:22 1999 +++ kern_acl.c Sat Dec 18 05:31:42 1999 @@ -0,0 +1,241 @@ +/*- + * Copyright (c) 1999 Robert N. M. Watson + * All rights reserved. + * + * 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 AUTHOR 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 AUTHOR 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$ + */ + +/* + * Generic routines to support file system ACLs, at a syntactic level + * Semantics are the responsibility of the underlying file system + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static MALLOC_DEFINE(M_ACL, "acl", "access control list"); + +static int vacl_set_acl(struct proc *p, struct vnode *vp, acl_type_t type, + struct acl *aclp); +static int vacl_get_acl(struct proc *p, struct vnode *vp, acl_type_t type, + struct acl *aclp); +static int vacl_aclcheck(struct proc *p, struct vnode *vp, acl_type_t type, + struct acl *aclp); + +/* + * These calls wrap the vnops, but are wrapped by the syscalls. These + * routines assume an acl pointer from userland, but that the vnode is + * already found, locked, etc. + */ +static int +vacl_set_acl(struct proc *p, struct vnode *vp, acl_type_t type, + struct acl *aclp) +{ + struct acl inkernacl; + int error; + + error = copyin(aclp, &inkernacl, sizeof(struct acl)); + if (error) + return(error); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + error = VOP_SETACL(vp, type, &inkernacl, p->p_ucred, p); + VOP_UNLOCK(vp, 0, p); + return(error); +} + + +static int +vacl_get_acl(struct proc *p, struct vnode *vp, acl_type_t type, + struct acl *aclp) +{ + struct acl inkernelacl; + int error; + + error = VOP_GETACL(vp, type, &inkernelacl, p->p_ucred, p); + if (error == 0) + error = copyout(&inkernelacl, aclp, sizeof(struct acl)); + return (error); +} + +static int +vacl_delete_def(struct proc *p, struct vnode *vp) +{ + int error; + + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + error = VOP_SETACL(vp, ACL_TYPE_DEFAULT, 0, p->p_ucred, p); + VOP_UNLOCK(vp, 0, p); + return (error); +} + +static int +vacl_aclcheck(struct proc *p, struct vnode *vp, acl_type_t type, + struct acl *aclp) +{ + struct acl inkernelacl; + int error; + + error = copyin(aclp, &inkernelacl, sizeof(struct acl)); + if (error) + return(error); + error = VOP_ACLCHECK(vp, type, &inkernelacl, p->p_ucred, p); + return (error); +} + +/* + * Syscalls -- in general these convert path/fd into a vnode, acquire + * appropriate locks, and invoke one of the vacl_ routines above to + * invoke the vop_. + */ +int +acl_syscall_get_file(struct proc *p, struct acl_syscall_get_file_args *uap) +{ + struct nameidata nd; + int error; + + /* what flags are required here -- possible not LOCKLEAF? */ + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + error = namei(&nd); + if (error) + return(error); + error = vacl_get_acl(p, nd.ni_vp, SCARG(uap, type), SCARG(uap, aclp)); + NDFREE(&nd, 0); + return (error); +} + +int +acl_syscall_set_file(struct proc *p, struct acl_syscall_set_file_args *uap) +{ + struct nameidata nd; + int error; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + error = namei(&nd); + if (error) + return(error); + error = vacl_set_acl(p, nd.ni_vp, SCARG(uap, type), SCARG(uap, aclp)); + NDFREE(&nd, 0); + return (error); +} + +int +acl_syscall_get_fd(struct proc *p, struct acl_syscall_get_fd_args *uap) +{ + struct file *fp; + int error; + + error = getvnode(p->p_fd, SCARG(uap, filedes), &fp); + if (error) + return(error); + return vacl_get_acl(p, (struct vnode *)fp->f_data, SCARG(uap, type), + SCARG(uap, aclp)); +} + +int +acl_syscall_set_fd(struct proc *p, struct acl_syscall_set_fd_args *uap) +{ + struct file *fp; + int error; + + error = getvnode(p->p_fd, SCARG(uap, filedes), &fp); + if (error) + return(error); + return vacl_set_acl(p, (struct vnode *)fp->f_data, SCARG(uap, type), + SCARG(uap, aclp)); +} + +int +acl_syscall_delete_def_file(struct proc *p, + struct acl_syscall_delete_def_file_args *uap) +{ + struct nameidata nd; + int error; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + error = namei(&nd); + if (error) + return(error); + error = vacl_delete_def(p, nd.ni_vp); + NDFREE(&nd, 0); + return (error); +} + +int +acl_syscall_delete_def_fd(struct proc *p, + struct acl_syscall_delete_def_fd_args *uap) +{ + struct file *fp; + int error; + + error = getvnode(p->p_fd, SCARG(uap, filedes), &fp); + if (error) + return(error); + error = vacl_delete_def(p, (struct vnode *)fp->f_data); + return (error); +} + + +int +acl_syscall_aclcheck_file(struct proc *p, + struct acl_syscall_aclcheck_file_args *uap) +{ + struct nameidata nd; + int error; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + error = namei(&nd); + if (error) + return(error); + error = vacl_aclcheck(p, nd.ni_vp, SCARG(uap, type), SCARG(uap, aclp)); + NDFREE(&nd, 0); + return (error); +} + +int +acl_syscall_aclcheck_fd(struct proc *p, + struct acl_syscall_aclcheck_fd_args *uap) +{ + struct file *fp; + int error; + + error = getvnode(p->p_fd, SCARG(uap, filedes), &fp); + if (error) + return(error); + return vacl_aclcheck(p, (struct vnode *)fp->f_data, SCARG(uap, type), + SCARG(uap, aclp)); +} Index: kern/makesyscalls.sh =================================================================== RCS file: /home/ncvs/src/sys/kern/makesyscalls.sh,v retrieving revision 1.38 diff -u -r1.38 makesyscalls.sh --- makesyscalls.sh 1999/09/10 23:34:30 1.38 +++ makesyscalls.sh 1999/12/18 01:45:41 @@ -112,6 +112,7 @@ printf "#ifndef %s\n", sysproto_h > sysarg printf "#define\t%s\n\n", sysproto_h > sysarg printf "#include \n\n" > sysarg + printf "#include \n\n" > sysarg printf "struct proc;\n\n" > sysarg printf "#define\tPAD_(t)\t(sizeof(register_t) <= sizeof(t) ? \\\n" > sysarg printf "\t\t0 : sizeof(register_t) - sizeof(t))\n\n" > sysarg Index: kern/syscalls.master =================================================================== RCS file: /home/ncvs/src/sys/kern/syscalls.master,v retrieving revision 1.67 diff -u -r1.67 syscalls.master --- syscalls.master 1999/11/17 21:32:33 1.67 +++ syscalls.master 1999/12/18 01:45:41 @@ -485,3 +485,15 @@ 344 STD BSD { int sigreturn(ucontext_t *sigcntxp); } 345 UNIMPL NOHIDE sigtimedwait 346 UNIMPL NOHIDE sigwaitinfo +347 STD BSD { int acl_syscall_get_file(char *path, acl_type_t type, struct acl *aclp); } +348 STD BSD { int acl_syscall_set_file(char *path, acl_type_t type, struct acl *aclp); } +349 STD BSD { int acl_syscall_get_fd(int filedes, acl_type_t type, struct acl *aclp); } +350 STD BSD { int acl_syscall_set_fd(int filedes, acl_type_t type, struct acl *aclp); } +351 STD BSD { int acl_syscall_delete_def_file(char *path); } +352 STD BSD { int acl_syscall_delete_def_fd(int filedes); } +353 STD BSD { int acl_syscall_aclcheck_file(char *path, acl_type_t type, struct acl *aclp); } +354 STD BSD { int acl_syscall_aclcheck_fd(int filedes, acl_type_t type, struct acl *aclp); } +355 STD BSD { int extattrctl(char *path, int cmd, char *attrname, caddr_t arg); } +356 STD BSD { int extattr_set_file(char *path, char *attrname, struct iovec *iovp, u_int iovcnt); } +357 STD BSD { int extattr_get_file(char *path, char *attrname, struct iovec *iovp, u_int iovcnt); } +358 STD BSD { int extattr_rm_file(char *path, char *attrname); } Index: kern/vfs_default.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_default.c,v retrieving revision 1.26 diff -u -r1.26 vfs_default.c --- vfs_default.c 1999/12/15 23:01:59 1.26 +++ vfs_default.c 1999/12/18 01:45:41 @@ -80,6 +80,12 @@ { &vop_revoke_desc, (vop_t *) vop_revoke }, { &vop_strategy_desc, (vop_t *) vop_nostrategy }, { &vop_unlock_desc, (vop_t *) vop_nounlock }, + { &vop_getacl_desc, (vop_t *) vop_eopnotsupp }, + { &vop_setacl_desc, (vop_t *) vop_eopnotsupp }, + { &vop_aclcheck_desc, (vop_t *) vop_eopnotsupp }, + { &vop_getextattr_desc, (vop_t *) vop_eopnotsupp }, + { &vop_setextattr_desc, (vop_t *) vop_eopnotsupp }, + { &vop_rmextattr_desc, (vop_t *) vop_eopnotsupp }, { NULL, NULL } }; @@ -613,6 +619,17 @@ struct vfsconf *vfsp; { return(0); +} + +int +vfs_stdextattrctl(mp, cmd, attrname, arg, p) + struct mount *mp; + int cmd; + char *attrname; + caddr_t arg; + struct proc *p; +{ + return(EOPNOTSUPP); } /* end of vfs default ops */ Index: kern/vfs_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.149 diff -u -r1.149 vfs_syscalls.c --- vfs_syscalls.c 1999/12/15 23:01:59 1.149 +++ vfs_syscalls.c 1999/12/18 02:39:59 @@ -60,13 +60,14 @@ #include #include #include +#include +#include #include - +#include #include #include #include -#include static int change_dir __P((struct nameidata *ndp, struct proc *p)); static void checkdirs __P((struct vnode *olddp)); @@ -3361,4 +3362,168 @@ sp = &sb; } return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); +} + +int +extattrctl(p, uap) + struct proc *p; + struct extattrctl_args *uap; +{ + A + struct nameidata nd; + struct mount *mp; + int error; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if ((error = namei(&nd)) != 0) + return (error); + mp = nd.ni_vp->v_mount; + NDFREE(&nd, 0); + return (VFS_EXTATTRCTL(mp, SCARG(uap, cmd), SCARG(uap, attrname), + SCARG(uap, arg), p)); +} + +int +extattr_set_file(p, uap) + struct proc *p; + B + struct extattr_set_file_args *uap; +{ + struct nameidata nd; + struct uio auio; + struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV]; + char attrname[EXTATTR_MAXNAMELEN]; + u_int iovlen, cnt; + int error, i; + + error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN); + if (error) + return (error); + NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, SCARG(uap, path), + p); + if ((error = namei(&nd)) != 0) + return(error); + iovlen = uap->iovcnt * sizeof(struct iovec); + if (uap->iovcnt > UIO_SMALLIOV) { + if (uap->iovcnt > UIO_MAXIOV) { + error = EINVAL; + goto done; + } + MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); + needfree = iov; + } else + iov = aiov; + auio.uio_iov = iov; + auio.uio_iovcnt = uap->iovcnt; + auio.uio_rw = UIO_WRITE; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_procp = p; + auio.uio_offset = 0; + If ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))) + goto done; + auio.uio_resid = 0; + for (i = 0; i < uap->iovcnt; i++) { + if (iov->iov_len > INT_MAX - auio.uio_resid) { + error = EINVAL; + goto done; + } + auio.uio_resid += iov->iov_len; + iov++; + } + cnt = auio.uio_resid; + error = VOP_SETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred, + p); + if (auio.uio_resid != cnt && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) + error = 0; + cnt -= auio.uio_resid; + p->p_retval[0] = cnt; +done: + if (needfree) + FREE(needfree, M_IOV); + NDFREE(&nd, 0); + return (error); +} + +int +extattr_get_file(p, uap) + struct proc *p; + struct extattr_get_file_args *uap; +{ + struct nameidata nd; + struct uio auio; + struct iovec *iov, *needfree, aiov[UIO_SMALLIOV]; + char attrname[EXTATTR_MAXNAMELEN]; + u_int iovlen, cnt; + int error, i; + + error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN); + if (error) + return (error); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if ((error = namei(&nd)) != 0) + return (error); + iovlen = uap->iovcnt * sizeof (struct iovec); + if (uap->iovcnt > UIO_SMALLIOV) { + if (uap->iovcnt > UIO_MAXIOV) { + vrele(nd.ni_vp); + return (EINVAL); + } + MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); + needfree = iov; + } else { + iov = aiov; + needfree = NULL; + } + auio.uio_iov = iov; + auio.uio_iovcnt = uap->iovcnt; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_procp = p; + auio.uio_offset = 0; + if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))) + goto done; + auio.uio_resid = 0; + for (i = 0; i < uap->iovcnt; i++) { + if (iov->iov_len > INT_MAX - auio.uio_resid) { + error = EINVAL; + goto done; + } + auio.uio_resid += iov->iov_len; + iov++; + } + cnt = auio.uio_resid; + error = VOP_GETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred, + p); + if (auio.uio_resid != cnt && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) + error = 0; + cnt -= auio.uio_resid; + p->p_retval[0] = cnt; +done: + if (needfree) + FREE(needfree, M_IOV); + NDFREE(&nd, 0); + return(error); +} + +int +extattr_rm_file(p, uap) + struct proc *p; + struct extattr_rm_file_args *uap; +{ + struct nameidata nd; + char attrname[EXTATTR_MAXNAMELEN]; + int error; + + error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN); + if (error) + return(error); + NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, SCARG(uap, path), + p); + if ((error = namei(&nd)) != 0) + return(error); + error = VOP_RMEXTATTR(nd.ni_vp, attrname, p->p_cred->pc_ucred, p); + NDFREE(&nd, 0); + return(error); } Index: kern/vnode_if.src =================================================================== RCS file: /home/ncvs/src/sys/kern/vnode_if.src,v retrieving revision 1.27 diff -u -r1.27 vnode_if.src --- vnode_if.src 1999/12/15 23:02:00 1.27 +++ vnode_if.src 1999/12/18 01:45:41 @@ -154,7 +154,7 @@ # vop_getattr { IN struct vnode *vp; - IN struct vattr *vap; + OUT struct vattr *vap; IN struct ucred *cred; IN struct proc *p; }; @@ -483,4 +483,69 @@ vop_bwrite { IN struct vnode *vp; IN struct buf *bp; +}; + +# +#% getacl vp = = = +# +vop_getacl { + IN struct vnode *vp; + IN acl_type_t type; + OUT struct acl *aclp; + IN struct ucred *cred; + IN struct proc *p; +}; + +# +#% setacl vp L L L +# +vop_setacl { + IN struct vnode *vp; + IN acl_type_t type; + IN struct acl *aclp; + IN struct ucred *cred; + IN struct proc *p; +}; + +# +#% aclcheck vp = = = +# +vop_aclcheck { + IN struct vnode *vp; + IN acl_type_t type; + IN struct acl *aclp; + IN struct ucred *cred; + IN struct proc *p; +}; + +# +#% getextattr vp = = = +# +vop_getextattr { + IN struct vnode *vp; + IN char *name; + INOUT struct uio *uio; + IN struct ucred *cred; + IN struct proc *p; +}; + +# +#% setextattr vp L L L +# +vop_setextattr { + IN struct vnode *vp; + IN char *name; + INOUT struct uio *uio; + IN struct ucred *cred; + IN struct proc *p; +}; + +# +#% rmextattr vp L L L +# +vop_rmextattr { + IN struct vnode *vp; + IN char *name; + IN struct ucred *cred; + IN struct proc *p; }; Index: miscfs/devfs/devfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/devfs/devfs_vfsops.c,v retrieving revision 1.41 diff -u -r1.41 devfs_vfsops.c --- devfs_vfsops.c 1999/12/11 16:12:55 1.41 +++ devfs_vfsops.c 1999/12/18 01:45:42 @@ -305,7 +305,9 @@ vfs_stdfhtovp, vfs_stdcheckexp, vfs_stdvptofh, - devfs_init + devfs_init, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(devfs_vfsops, devfs, 0); Index: miscfs/fdesc/fdesc_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/fdesc/fdesc_vfsops.c,v retrieving revision 1.21 diff -u -r1.21 fdesc_vfsops.c --- fdesc_vfsops.c 1999/09/11 00:46:00 1.21 +++ fdesc_vfsops.c 1999/12/18 01:45:42 @@ -227,6 +227,8 @@ vfs_stdcheckexp, vfs_stdvptofh, fdesc_init, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(fdesc_vfsops, fdesc, VFCF_SYNTHETIC); Index: miscfs/kernfs/kernfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/kernfs/kernfs_vfsops.c,v retrieving revision 1.34 diff -u -r1.34 kernfs_vfsops.c --- kernfs_vfsops.c 1999/09/11 00:46:01 1.34 +++ kernfs_vfsops.c 1999/12/18 01:45:42 @@ -255,6 +255,8 @@ vfs_stdcheckexp, vfs_stdvptofh, vfs_stdinit, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(kernfs_vfsops, kernfs, VFCF_SYNTHETIC); Index: miscfs/nullfs/null_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/nullfs/null_vfsops.c,v retrieving revision 1.33 diff -u -r1.33 null_vfsops.c --- null_vfsops.c 1999/12/15 23:02:05 1.33 +++ null_vfsops.c 1999/12/18 01:45:42 @@ -417,6 +417,19 @@ return VFS_VPTOFH(NULLVPTOLOWERVP(vp), fhp); } +static int +nullfs_extattrctl(mp, cmd, attrname, arg, p) + struct mount *mp; + int cmd; + char *attrname; + caddr_t arg; + struct proc *p; +{ + return VFS_EXTATTRCTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, attrname, + arg, p); +} + + static struct vfsops null_vfsops = { nullfs_mount, nullfs_start, @@ -430,6 +443,8 @@ nullfs_checkexp, nullfs_vptofh, nullfs_init, + vfs_stduninit, + nullfs_extattrctl, }; VFS_SET(null_vfsops, null, VFCF_LOOPBACK); Index: miscfs/portal/portal_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/portal/portal_vfsops.c,v retrieving revision 1.25 diff -u -r1.25 portal_vfsops.c --- portal_vfsops.c 1999/09/11 00:46:02 1.25 +++ portal_vfsops.c 1999/12/18 01:45:42 @@ -256,6 +256,8 @@ vfs_stdcheckexp, vfs_stdvptofh, vfs_stdinit, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(portal_vfsops, portal, VFCF_SYNTHETIC); Index: miscfs/procfs/procfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_vfsops.c,v retrieving revision 1.31 diff -u -r1.31 procfs_vfsops.c --- procfs_vfsops.c 1999/12/08 08:59:37 1.31 +++ procfs_vfsops.c 1999/12/18 01:45:42 @@ -172,6 +172,8 @@ vfs_stdcheckexp, vfs_stdvptofh, vfs_stdinit, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(procfs_vfsops, procfs, VFCF_SYNTHETIC); Index: miscfs/umapfs/umap_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/umapfs/umap_vfsops.c,v retrieving revision 1.29 diff -u -r1.29 umap_vfsops.c --- umap_vfsops.c 1999/12/15 23:02:11 1.29 +++ umap_vfsops.c 1999/12/18 01:45:42 @@ -430,6 +430,19 @@ return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp)); } +static int +umapfs_extattrctl(mp, cmd, attrname, arg, p) + struct mount *mp; + int cmd; + char *attrname; + caddr_t arg; + struct proc *p; +{ + return (VFS_EXTATTRCTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, attrname, + arg, p)) +} + + static struct vfsops umap_vfsops = { umapfs_mount, umapfs_start, @@ -443,6 +456,8 @@ umapfs_checkexp, umapfs_vptofh, umapfs_init, + vfs_stduninit, + umapfs_extattrctl, }; VFS_SET(umap_vfsops, umap, VFCF_LOOPBACK); Index: miscfs/union/union_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/union/union_vfsops.c,v retrieving revision 1.38 diff -u -r1.38 union_vfsops.c --- union_vfsops.c 1999/12/15 23:02:13 1.38 +++ union_vfsops.c 1999/12/18 01:45:42 @@ -502,6 +502,8 @@ vfs_stdcheckexp, vfs_stdvptofh, union_init, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(union_vfsops, union, VFCF_LOOPBACK); Index: msdosfs/msdosfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/msdosfs/msdosfs_vfsops.c,v retrieving revision 1.56 diff -u -r1.56 msdosfs_vfsops.c --- msdosfs_vfsops.c 1999/12/15 23:02:15 1.56 +++ msdosfs_vfsops.c 1999/12/18 01:45:42 @@ -986,7 +986,9 @@ msdosfs_fhtovp, msdosfs_checkexp, msdosfs_vptofh, - msdosfs_init + msdosfs_init, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(msdosfs_vfsops, msdos, 0); Index: nfs/nfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/nfs/nfs_vfsops.c,v retrieving revision 1.89 diff -u -r1.89 nfs_vfsops.c --- nfs_vfsops.c 1999/12/11 16:12:59 1.89 +++ nfs_vfsops.c 1999/12/18 01:45:42 @@ -126,6 +126,7 @@ vfs_stdvptofh, /* shouldn't happen */ nfs_init, nfs_uninit, + vfs_stdextattrctl, }; VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK); Index: ntfs/ntfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/ntfs/ntfs_vfsops.c,v retrieving revision 1.18 diff -u -r1.18 ntfs_vfsops.c --- ntfs_vfsops.c 1999/12/15 23:02:23 1.18 +++ ntfs_vfsops.c 1999/12/18 01:45:43 @@ -1008,7 +1008,8 @@ ntfs_checkexp, ntfs_vptofh, ntfs_init, - NULL + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(ntfs_vfsops, ntfs, 0); #elif defined(__NetBSD__) Index: nwfs/nwfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/nwfs/nwfs_vfsops.c,v retrieving revision 1.4 diff -u -r1.4 nwfs_vfsops.c --- nwfs_vfsops.c 1999/12/11 16:13:01 1.4 +++ nwfs_vfsops.c 1999/12/18 01:45:43 @@ -93,7 +93,8 @@ vfs_stdcheckexp, vfs_stdvptofh, /* shouldn't happen */ nwfs_init, - nwfs_uninit + nwfs_uninit, + vfs_stdextattrctl, }; Index: sys/acl.h =================================================================== RCS file: acl.h diff -N acl.h --- /dev/null Sat Dec 18 05:23:22 1999 +++ acl.h Sat Dec 18 04:50:56 1999 @@ -0,0 +1,169 @@ +/*- + * Copyright (c) 1999 Robert N. M. Watson + * All rights reserved. + * + * 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 AUTHOR 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 AUTHOR 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$ + */ +/* + * Userland/kernel interface for Access Control Lists + * + * This code from the FreeBSD POSIX.1e implementation. Not all of the ACL + * code is committed yet; in order to use the library routines listed + * below, you'll need to download libposix1e_acl from the POSIX.1e + * implementation page, or possibly update to a more recent version of + * FreeBSD, as the code may have been committed. + * + * The POSIX.1e implementation page may be reached at: + * http://www.watson.org/fbsd-hardening/posix1e/ + * + * However, all syscalls will pass through to appropriate VFS vnops, so + * file systems implementing the vnops are accessible through the syscalls. + */ + +#ifndef _SYS_ACL_H +#define _SYS_ACL_H + +/* + * POSIX.1e ACL types + */ + +#define MAX_ACL_ENTRIES 32 /* maximum entries in an ACL */ +#define _POSIX_ACL_PATH_MAX MAX_ACL_ENTRIES + +typedef int acl_type_t; +typedef int acl_tag_t; +typedef mode_t acl_perm_t; + +struct acl_entry { + acl_tag_t ae_tag; + uid_t ae_id; + acl_perm_t ae_perm; +}; +typedef struct acl_entry *acl_entry_t; + +struct acl { + int acl_cnt; + struct acl_entry acl_entry[MAX_ACL_ENTRIES]; +}; +typedef struct acl *acl_t; + +/* + * Possible valid values for a_type of acl_entry_t + */ +#define ACL_USER_OBJ 0x00000001 +#define ACL_USER 0x00000002 +#define ACL_GROUP_OBJ 0x00000004 +#define ACL_GROUP 0x00000008 +#define ACL_MASK 0x00000010 +#define ACL_OTHER 0x00000020 +#define ACL_OTHER_OBJ ACL_OTHER +#define ACL_AFS_ID 0x00000040 + +#define ACL_TYPE_ACCESS 0x00000000 +#define ACL_TYPE_DEFAULT 0x00000001 + +/* + * Possible flags in a_perm field + */ +#define ACL_PERM_EXEC 0x0001 +#define ACL_PERM_WRITE 0x0002 +#define ACL_PERM_READ 0x0004 +#define ACL_PERM_NONE 0x0000 +#define ACL_PERM_BITS (ACL_PERM_EXEC | ACL_PERM_WRITE | ACL_PERM_READ) +#define ACL_POSIX1E_BITS (ACL_PERM_EXEC | ACL_PERM_WRITE | ACL_PERM_READ) + +#ifdef KERNEL +/* + * Storage for ACLs and support structures + */ +#ifdef MALLOC_DECLARE +MALLOC_DECLARE(M_ACL); +#endif + +/* + * Dummy declarations so that we can expose acl_access all over the place + * without worrying about including ucred and friends. vnode.h does the + * same thing. + */ +struct ucred; +struct proc; + +/* + * POSIX.1e and generic kernel/vfs semantics functions--not currently in the + * base distribution, but will be soon. + */ +struct vattr; +struct vop_getacl_args; +struct vop_aclcheck_args; + +int posix1e_acl_access(struct acl *a_acl, int a_mode, struct ucred *a_cred, + struct proc *a_p); +void generic_attr_to_posix1e_acl(struct acl *a_acl, struct vattr *vattr); +int generic_vop_getacl(struct vop_getacl_args *ap); +int generic_vop_aclcheck(struct vop_aclcheck_args *ap); +int posix1e_vop_aclcheck(struct vop_aclcheck_args *ap); + +#else /* KERNEL */ + +/* + * Syscall interface -- use the library calls instead as the syscalls + * have strict acl entry ordering requirements + */ +int acl_syscall_get_file(char *path, acl_type_t type, struct acl *aclp); +int acl_syscall_set_file(char *path, acl_type_t type, struct acl *aclp); +int acl_syscall_get_fd(int filedes, acl_type_t type, struct acl *aclp); +int acl_syscall_set_fd(int filedes, acl_type_t type, struct acl *aclp); +int acl_syscall_delete_def_file(const char *path_p); +int acl_syscall_delete_def_fd(int filedes); +int acl_syscall_aclcheck_file(char *path, acl_type_t type, + struct acl *aclp); +int acl_syscall_aclcheck_fd(int filedes, acl_type_t type, + struct acl *aclp); + +/* + * Supported POSIX.1e ACL manipulation and assignment/retrieval API + * These are currently provided by libposix1e_acl, which is not shipped + * with the base distribution, but will be soon. Some of these are + * from POSIX.1e-extensions. + * + * Not all POSIX.1e ACL functions are listed here yet, but more will + * be soon. + */ +int acl_calc_mask(acl_t *acl_p); +int acl_delete_def_file(const char *path_p); +int acl_delete_def_fd(int filedes); +acl_t acl_from_text(const char *buf_p); +acl_t acl_get_fd(int fd, acl_type_t type); +acl_t acl_get_file(const char *path_p, acl_type_t type); +acl_t acl_init(int count); +int acl_set_fd(int fd, acl_t acl, acl_type_t type); +int acl_set_file(const char *path_p, acl_type_t type, acl_t acl); +char *acl_to_text(acl_t acl, ssize_t *len_p); +int acl_valid(acl_t acl); +int acl_valid_file(const char *path_p, acl_type_t type, acl_t acl); +int acl_valid_fd(int fd, acl_type_t type, acl_t acl); +int acl_free(void *obj_p); + +#endif /* KERNEL */ +#endif /* _SYS_ACL_H */ Index: sys/extattr.h =================================================================== RCS file: extattr.h diff -N extattr.h --- /dev/null Sat Dec 18 05:23:22 1999 +++ extattr.h Sat Dec 18 05:22:01 1999 @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 1999 Robert N. M. Watson + * All rights reserved. + * + * 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 AUTHOR 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 AUTHOR 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$ + */ +/* + * Userland/kernel interface for Extended File System Attributes + * + * This code from the FreeBSD POSIX.1e implementation. While the syscalls + * are fully implemented, invoking the VFS vnops and VFS calls as necessary, + * no file systems shipped with this version of FreeBSD implement these + * calls. Extensions to UFS/FFS to support extended attributes are + * available from the POSIX.1e implementation page, or possibly in a more + * recent version of FreeBSD. + * + * The POSIX.1e implementation page may be reached at: + * http://www.watson.org/fbsd-hardening/posix1e/ + */ + +#ifndef _SYS_EXTATTR_H_ +#define _SYS_EXTATTR_H_ + +#define EXTATTR_MAXNAMELEN NAME_MAX + +#ifdef KERNEL + +int extattrctl(char *path, int cmd, char *attrname, caddr_t arg); +int extattr_set_file(char *path, char *attrname, struct iovec *iovp, + u_int iovcnt); +int extattr_get_file(char *path, char *attrname, struct iovec *iovp, + u_int iovcnt); +int extattr_rm_file(char *path, char *attrname); + +#endif /* KERNEL */ +#endif /* _SYS_EXTATTR_H_ */ Index: sys/mount.h =================================================================== RCS file: /home/ncvs/src/sys/sys/mount.h,v retrieving revision 1.86 diff -u -r1.86 mount.h --- mount.h 1999/12/03 02:23:34 1.86 +++ mount.h 1999/12/18 03:21:09 @@ -331,6 +331,9 @@ int (*vfs_vptofh) __P((struct vnode *vp, struct fid *fhp)); int (*vfs_init) __P((struct vfsconf *)); int (*vfs_uninit) __P((struct vfsconf *)); + int (*vfs_extattrctl) __P((struct mount *mp, int cmd, + char *attrname, caddr_t arg, + struct proc *p)); }; #define VFS_MOUNT(MP, PATH, DATA, NDP, P) \ @@ -347,6 +350,8 @@ #define VFS_VPTOFH(VP, FIDP) (*(VP)->v_mount->mnt_op->vfs_vptofh)(VP, FIDP) #define VFS_CHECKEXP(MP, NAM, EXFLG, CRED) \ (*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED) +#define VFS_EXTATTRCTL(MP, C, N, A, P) \ + (*(MP)->mnt_op->vfs_extattrctl)(MP, C, N, A, P) #include @@ -439,6 +444,8 @@ int vfs_stdvptofh __P((struct vnode *vp, struct fid *fhp)); int vfs_stdinit __P((struct vfsconf *)); int vfs_stduninit __P((struct vfsconf *)); +int vfs_stdextattrctl __P((struct mount *mp, int cmd, char *attrname, + caddr_t arg, struct proc *p)); #else /* !KERNEL */ Index: sys/vnode.h =================================================================== RCS file: /home/ncvs/src/sys/sys/vnode.h,v retrieving revision 1.106 diff -u -r1.106 vnode.h --- vnode.h 1999/12/13 02:28:51 1.106 +++ vnode.h 1999/12/18 01:45:43 @@ -40,6 +40,7 @@ #include #include #include +#include #include Index: ufs/ffs/ffs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_vfsops.c,v retrieving revision 1.113 diff -u -r1.113 ffs_vfsops.c --- ffs_vfsops.c 1999/12/15 23:02:30 1.113 +++ ffs_vfsops.c 1999/12/18 01:45:43 @@ -83,6 +83,8 @@ ufs_check_export, ffs_vptofh, ffs_init, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(ufs_vfsops, ufs, 0); Index: ufs/mfs/mfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/ufs/mfs/mfs_vfsops.c,v retrieving revision 1.80 diff -u -r1.80 mfs_vfsops.c --- mfs_vfsops.c 1999/11/26 20:08:44 1.80 +++ mfs_vfsops.c 1999/12/18 01:45:44 @@ -108,6 +108,8 @@ ufs_check_export, ffs_vptofh, mfs_init, + vfs_stduninit, + vfs_stdextattrctl, }; VFS_SET(mfs_vfsops, mfs, 0);