diff options
author | rwatson <rwatson@FreeBSD.org> | 1999-12-19 06:08:07 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 1999-12-19 06:08:07 +0000 |
commit | 4b6baecfc724bac12be9de99924e828b1e68046e (patch) | |
tree | ccf64e27cf5f979dcaaf7e55bb2a486df8b3f567 /sys/kern | |
parent | 114c517da1a1c0bab8d9fa884b67102ec0768fa1 (diff) | |
download | FreeBSD-src-4b6baecfc724bac12be9de99924e828b1e68046e.zip FreeBSD-src-4b6baecfc724bac12be9de99924e828b1e68046e.tar.gz |
Second pass commit to introduce new ACL and Extended Attribute system
calls, vnops, vfsops, both in /kern, and to individual file systems that
require a vfsop_ array entry.
Reviewed by: eivind
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/init_sysent.c | 14 | ||||
-rw-r--r-- | sys/kern/kern_acl.c | 281 | ||||
-rw-r--r-- | sys/kern/makesyscalls.sh | 1 | ||||
-rw-r--r-- | sys/kern/subr_acl_posix1e.c | 281 | ||||
-rw-r--r-- | sys/kern/syscalls.c | 14 | ||||
-rw-r--r-- | sys/kern/vfs_acl.c | 281 | ||||
-rw-r--r-- | sys/kern/vfs_default.c | 16 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 195 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 195 | ||||
-rw-r--r-- | sys/kern/vnode_if.src | 57 |
10 files changed, 1328 insertions, 7 deletions
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 5e54940..addde32 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: src/sys/kern/syscalls.master,v 1.67 1999/11/17 21:32:33 brian Exp + * created from FreeBSD: src/sys/kern/syscalls.master,v 1.68 1999/12/19 05:54:46 rwatson Exp */ #include "opt_compat.h" @@ -367,4 +367,16 @@ struct sysent sysent[] = { { 1, (sy_call_t *)sigreturn }, /* 344 = sigreturn */ { 0, (sy_call_t *)nosys }, /* 345 = sigtimedwait */ { 0, (sy_call_t *)nosys }, /* 346 = sigwaitinfo */ + { 3, (sy_call_t *)acl_syscall_get_file }, /* 347 = acl_syscall_get_file */ + { 3, (sy_call_t *)acl_syscall_set_file }, /* 348 = acl_syscall_set_file */ + { 3, (sy_call_t *)acl_syscall_get_fd }, /* 349 = acl_syscall_get_fd */ + { 3, (sy_call_t *)acl_syscall_set_fd }, /* 350 = acl_syscall_set_fd */ + { 2, (sy_call_t *)acl_syscall_delete_file }, /* 351 = acl_syscall_delete_file */ + { 2, (sy_call_t *)acl_syscall_delete_fd }, /* 352 = acl_syscall_delete_fd */ + { 3, (sy_call_t *)acl_syscall_aclcheck_file }, /* 353 = acl_syscall_aclcheck_file */ + { 3, (sy_call_t *)acl_syscall_aclcheck_fd }, /* 354 = acl_syscall_aclcheck_fd */ + { 4, (sy_call_t *)extattrctl }, /* 355 = extattrctl */ + { 4, (sy_call_t *)extattr_set_file }, /* 356 = extattr_set_file */ + { 4, (sy_call_t *)extattr_get_file }, /* 357 = extattr_get_file */ + { 2, (sy_call_t *)extattr_delete_file }, /* 358 = extattr_delete_file */ }; diff --git a/sys/kern/kern_acl.c b/sys/kern/kern_acl.c new file mode 100644 index 0000000..5df8d6a --- /dev/null +++ b/sys/kern/kern_acl.c @@ -0,0 +1,281 @@ +/*- + * 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 <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/vnode.h> +#include <sys/lock.h> +#include <sys/namei.h> +#include <sys/file.h> +#include <sys/proc.h> +#include <sys/sysent.h> +#include <sys/errno.h> +#include <sys/stat.h> +#include <sys/acl.h> +#include <vm/vm_zone.h> + +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 real vnode operations, and are called by the + * syscall code once the syscall has converted the path or file + * descriptor to a vnode (unlocked). The aclp pointer is assumed + * still to point to userland, so this should not be consumed within + * the kernel except by syscall code. Other code should directly + * invoke VOP_{SET,GET}ACL. + */ + +/* + * Given a vnode, set its ACL. + */ +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); +} + +/* + * Given a vnode, get its ACL. + */ +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); +} + +/* + * Given a vnode, delete its ACL. + */ +static int +vacl_delete(struct proc *p, struct vnode *vp, acl_type_t type) +{ + 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); +} + +/* + * Given a vnode, check whether an ACL is appropriate for it + */ +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 -- convert the path/fd to a vnode, and call vacl_whatever. + * Don't need to lock, as the vacl_ code will get/release any locks + * required. + */ + +/* + * Given a file path, get an ACL for it + */ +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); +} + +/* + * Given a file path, set an ACL for it + */ +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); +} + +/* + * Given a file descriptor, get an ACL for it + */ +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)); +} + +/* + * Given a file descriptor, set an ACL for it + */ +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)); +} + +/* + * Given a file path, delete an ACL from it. + */ +int +acl_syscall_delete_file(struct proc *p, + struct acl_syscall_delete_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(p, nd.ni_vp, SCARG(uap, type)); + NDFREE(&nd, 0); + return (error); +} + +/* + * Given a file path, delete an ACL from it. + */ +int +acl_syscall_delete_fd(struct proc *p, + struct acl_syscall_delete_fd_args *uap) +{ + struct file *fp; + int error; + + error = getvnode(p->p_fd, SCARG(uap, filedes), &fp); + if (error) + return(error); + error = vacl_delete(p, (struct vnode *)fp->f_data, SCARG(uap, type)); + return (error); +} + +/* + * Given a file path, check an ACL for it + */ +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); +} + +/* + * Given a file descriptor, check an ACL for it + */ +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)); +} diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh index f8e2726..bdbd5c6 100644 --- a/sys/kern/makesyscalls.sh +++ b/sys/kern/makesyscalls.sh @@ -112,6 +112,7 @@ s/\$//g printf "#ifndef %s\n", sysproto_h > sysarg printf "#define\t%s\n\n", sysproto_h > sysarg printf "#include <sys/signal.h>\n\n" > sysarg + printf "#include <sys/acl.h>\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 diff --git a/sys/kern/subr_acl_posix1e.c b/sys/kern/subr_acl_posix1e.c new file mode 100644 index 0000000..5df8d6a --- /dev/null +++ b/sys/kern/subr_acl_posix1e.c @@ -0,0 +1,281 @@ +/*- + * 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 <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/vnode.h> +#include <sys/lock.h> +#include <sys/namei.h> +#include <sys/file.h> +#include <sys/proc.h> +#include <sys/sysent.h> +#include <sys/errno.h> +#include <sys/stat.h> +#include <sys/acl.h> +#include <vm/vm_zone.h> + +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 real vnode operations, and are called by the + * syscall code once the syscall has converted the path or file + * descriptor to a vnode (unlocked). The aclp pointer is assumed + * still to point to userland, so this should not be consumed within + * the kernel except by syscall code. Other code should directly + * invoke VOP_{SET,GET}ACL. + */ + +/* + * Given a vnode, set its ACL. + */ +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); +} + +/* + * Given a vnode, get its ACL. + */ +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); +} + +/* + * Given a vnode, delete its ACL. + */ +static int +vacl_delete(struct proc *p, struct vnode *vp, acl_type_t type) +{ + 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); +} + +/* + * Given a vnode, check whether an ACL is appropriate for it + */ +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 -- convert the path/fd to a vnode, and call vacl_whatever. + * Don't need to lock, as the vacl_ code will get/release any locks + * required. + */ + +/* + * Given a file path, get an ACL for it + */ +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); +} + +/* + * Given a file path, set an ACL for it + */ +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); +} + +/* + * Given a file descriptor, get an ACL for it + */ +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)); +} + +/* + * Given a file descriptor, set an ACL for it + */ +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)); +} + +/* + * Given a file path, delete an ACL from it. + */ +int +acl_syscall_delete_file(struct proc *p, + struct acl_syscall_delete_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(p, nd.ni_vp, SCARG(uap, type)); + NDFREE(&nd, 0); + return (error); +} + +/* + * Given a file path, delete an ACL from it. + */ +int +acl_syscall_delete_fd(struct proc *p, + struct acl_syscall_delete_fd_args *uap) +{ + struct file *fp; + int error; + + error = getvnode(p->p_fd, SCARG(uap, filedes), &fp); + if (error) + return(error); + error = vacl_delete(p, (struct vnode *)fp->f_data, SCARG(uap, type)); + return (error); +} + +/* + * Given a file path, check an ACL for it + */ +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); +} + +/* + * Given a file descriptor, check an ACL for it + */ +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)); +} diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 9fe3e56..a0c55e4 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: src/sys/kern/syscalls.master,v 1.67 1999/11/17 21:32:33 brian Exp + * created from FreeBSD: src/sys/kern/syscalls.master,v 1.68 1999/12/19 05:54:46 rwatson Exp */ char *syscallnames[] = { @@ -354,4 +354,16 @@ char *syscallnames[] = { "sigreturn", /* 344 = sigreturn */ "#345", /* 345 = sigtimedwait */ "#346", /* 346 = sigwaitinfo */ + "acl_syscall_get_file", /* 347 = acl_syscall_get_file */ + "acl_syscall_set_file", /* 348 = acl_syscall_set_file */ + "acl_syscall_get_fd", /* 349 = acl_syscall_get_fd */ + "acl_syscall_set_fd", /* 350 = acl_syscall_set_fd */ + "acl_syscall_delete_file", /* 351 = acl_syscall_delete_file */ + "acl_syscall_delete_fd", /* 352 = acl_syscall_delete_fd */ + "acl_syscall_aclcheck_file", /* 353 = acl_syscall_aclcheck_file */ + "acl_syscall_aclcheck_fd", /* 354 = acl_syscall_aclcheck_fd */ + "extattrctl", /* 355 = extattrctl */ + "extattr_set_file", /* 356 = extattr_set_file */ + "extattr_get_file", /* 357 = extattr_get_file */ + "extattr_delete_file", /* 358 = extattr_delete_file */ }; diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c new file mode 100644 index 0000000..5df8d6a --- /dev/null +++ b/sys/kern/vfs_acl.c @@ -0,0 +1,281 @@ +/*- + * 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 <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/vnode.h> +#include <sys/lock.h> +#include <sys/namei.h> +#include <sys/file.h> +#include <sys/proc.h> +#include <sys/sysent.h> +#include <sys/errno.h> +#include <sys/stat.h> +#include <sys/acl.h> +#include <vm/vm_zone.h> + +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 real vnode operations, and are called by the + * syscall code once the syscall has converted the path or file + * descriptor to a vnode (unlocked). The aclp pointer is assumed + * still to point to userland, so this should not be consumed within + * the kernel except by syscall code. Other code should directly + * invoke VOP_{SET,GET}ACL. + */ + +/* + * Given a vnode, set its ACL. + */ +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); +} + +/* + * Given a vnode, get its ACL. + */ +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); +} + +/* + * Given a vnode, delete its ACL. + */ +static int +vacl_delete(struct proc *p, struct vnode *vp, acl_type_t type) +{ + 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); +} + +/* + * Given a vnode, check whether an ACL is appropriate for it + */ +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 -- convert the path/fd to a vnode, and call vacl_whatever. + * Don't need to lock, as the vacl_ code will get/release any locks + * required. + */ + +/* + * Given a file path, get an ACL for it + */ +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); +} + +/* + * Given a file path, set an ACL for it + */ +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); +} + +/* + * Given a file descriptor, get an ACL for it + */ +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)); +} + +/* + * Given a file descriptor, set an ACL for it + */ +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)); +} + +/* + * Given a file path, delete an ACL from it. + */ +int +acl_syscall_delete_file(struct proc *p, + struct acl_syscall_delete_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(p, nd.ni_vp, SCARG(uap, type)); + NDFREE(&nd, 0); + return (error); +} + +/* + * Given a file path, delete an ACL from it. + */ +int +acl_syscall_delete_fd(struct proc *p, + struct acl_syscall_delete_fd_args *uap) +{ + struct file *fp; + int error; + + error = getvnode(p->p_fd, SCARG(uap, filedes), &fp); + if (error) + return(error); + error = vacl_delete(p, (struct vnode *)fp->f_data, SCARG(uap, type)); + return (error); +} + +/* + * Given a file path, check an ACL for it + */ +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); +} + +/* + * Given a file descriptor, check an ACL for it + */ +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)); +} diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 35df911..92642ff 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -80,6 +80,11 @@ static struct vnodeopv_entry_desc default_vnodeop_entries[] = { { &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 }, { NULL, NULL } }; @@ -615,4 +620,15 @@ vfs_stduninit (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 */ diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 1de7cf1..4f8878c 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -60,13 +60,14 @@ #include <sys/vnode.h> #include <sys/proc.h> #include <sys/dirent.h> +#include <sys/extattr.h> +#include <machine/limits.h> #include <miscfs/union/union.h> - +#include <sys/sysctl.h> #include <vm/vm.h> #include <vm/vm_object.h> #include <vm/vm_zone.h> -#include <sys/sysctl.h> static int change_dir __P((struct nameidata *ndp, struct proc *p)); static void checkdirs __P((struct vnode *olddp)); @@ -3362,3 +3363,193 @@ fhstatfs(p, uap) } return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); } + +/* + * Syscall to push extended attribute configuration information into the + * VFS. Accepts a path, which it converts to a mountpoint, as well as + * a command (int cmd), and attribute name and misc data. For now, the + * attribute name is left in userspace for consumption by the VFS_op. + * It will probably be changed to be copied into sysspace by the + * syscall in the future, once issues with various consumers of the + * attribute code have raised their hands. + * + * Currently this is used only by UFS Extended Attributes. + */ +int +extattrctl(p, uap) + struct proc *p; + struct extattrctl_args *uap; +{ + 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)); +} + +/* + * Syscall to set a named extended attribute on a file or directory. + * Accepts attribute name, and a uio structure pointing to the data to set. + * The uio is consumed in the style of writev(). The real work happens + * in VOP_SETEXTATTR(). + */ +int +extattr_set_file(p, uap) + struct proc *p; + 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); +} + +/* + * Syscall to get a named extended attribute on a file or directory. + * Accepts attribute name, and a uio structure pointing to a buffer for the + * data. The uio is consumed in the style of readv(). The real work + * happens in VOP_GETEXTATTR(); + */ +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) { + NDFREE(&nd, 0); + 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); +} + +/* + * Syscall to delete a named extended attribute from a file or directory. + * Accepts attribute name. The real work happens in VOP_SETEXTATTR(). + */ +int +extattr_delete_file(p, uap) + struct proc *p; + struct extattr_delete_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_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_cred->pc_ucred, + p); + NDFREE(&nd, 0); + return(error); +} diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 1de7cf1..4f8878c 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -60,13 +60,14 @@ #include <sys/vnode.h> #include <sys/proc.h> #include <sys/dirent.h> +#include <sys/extattr.h> +#include <machine/limits.h> #include <miscfs/union/union.h> - +#include <sys/sysctl.h> #include <vm/vm.h> #include <vm/vm_object.h> #include <vm/vm_zone.h> -#include <sys/sysctl.h> static int change_dir __P((struct nameidata *ndp, struct proc *p)); static void checkdirs __P((struct vnode *olddp)); @@ -3362,3 +3363,193 @@ fhstatfs(p, uap) } return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); } + +/* + * Syscall to push extended attribute configuration information into the + * VFS. Accepts a path, which it converts to a mountpoint, as well as + * a command (int cmd), and attribute name and misc data. For now, the + * attribute name is left in userspace for consumption by the VFS_op. + * It will probably be changed to be copied into sysspace by the + * syscall in the future, once issues with various consumers of the + * attribute code have raised their hands. + * + * Currently this is used only by UFS Extended Attributes. + */ +int +extattrctl(p, uap) + struct proc *p; + struct extattrctl_args *uap; +{ + 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)); +} + +/* + * Syscall to set a named extended attribute on a file or directory. + * Accepts attribute name, and a uio structure pointing to the data to set. + * The uio is consumed in the style of writev(). The real work happens + * in VOP_SETEXTATTR(). + */ +int +extattr_set_file(p, uap) + struct proc *p; + 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); +} + +/* + * Syscall to get a named extended attribute on a file or directory. + * Accepts attribute name, and a uio structure pointing to a buffer for the + * data. The uio is consumed in the style of readv(). The real work + * happens in VOP_GETEXTATTR(); + */ +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) { + NDFREE(&nd, 0); + 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); +} + +/* + * Syscall to delete a named extended attribute from a file or directory. + * Accepts attribute name. The real work happens in VOP_SETEXTATTR(). + */ +int +extattr_delete_file(p, uap) + struct proc *p; + struct extattr_delete_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_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_cred->pc_ucred, + p); + NDFREE(&nd, 0); + return(error); +} diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index bbfe4d4..479cc92 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -154,7 +154,7 @@ vop_access { # vop_getattr { IN struct vnode *vp; - IN struct vattr *vap; + OUT struct vattr *vap; IN struct ucred *cred; IN struct proc *p; }; @@ -484,3 +484,58 @@ 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; +}; |