191f37dcbSRobert Watson /*- 2e4256d1eSRobert Watson * Copyright (c) 1999-2006 Robert N. M. Watson 391f37dcbSRobert Watson * All rights reserved. 491f37dcbSRobert Watson * 56d878543SRobert Watson * This software was developed by Robert Watson for the TrustedBSD Project. 66d878543SRobert Watson * 791f37dcbSRobert Watson * Redistribution and use in source and binary forms, with or without 891f37dcbSRobert Watson * modification, are permitted provided that the following conditions 991f37dcbSRobert Watson * are met: 1091f37dcbSRobert Watson * 1. Redistributions of source code must retain the above copyright 1191f37dcbSRobert Watson * notice, this list of conditions and the following disclaimer. 1291f37dcbSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 1391f37dcbSRobert Watson * notice, this list of conditions and the following disclaimer in the 1491f37dcbSRobert Watson * documentation and/or other materials provided with the distribution. 1591f37dcbSRobert Watson * 1691f37dcbSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1791f37dcbSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1891f37dcbSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1991f37dcbSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2091f37dcbSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2191f37dcbSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2291f37dcbSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2391f37dcbSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2491f37dcbSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2591f37dcbSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2691f37dcbSRobert Watson * SUCH DAMAGE. 2791f37dcbSRobert Watson */ 2891f37dcbSRobert Watson /* 295293465fSRobert Watson * Developed by the TrustedBSD Project. 30e4256d1eSRobert Watson * 31e4256d1eSRobert Watson * ACL system calls and other functions common across different ACL types. 32e4256d1eSRobert Watson * Type-specific routines go into subr_acl_<type>.c. 3391f37dcbSRobert Watson */ 3491f37dcbSRobert Watson 35677b542eSDavid E. O'Brien #include <sys/cdefs.h> 36677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 37677b542eSDavid E. O'Brien 38c86ca022SRobert Watson #include "opt_mac.h" 39c86ca022SRobert Watson 4091f37dcbSRobert Watson #include <sys/param.h> 4191f37dcbSRobert Watson #include <sys/systm.h> 4291f37dcbSRobert Watson #include <sys/sysproto.h> 4391f37dcbSRobert Watson #include <sys/kernel.h> 44c86ca022SRobert Watson #include <sys/mac.h> 4591f37dcbSRobert Watson #include <sys/malloc.h> 4642e7197fSChristian S.J. Peron #include <sys/mount.h> 4791f37dcbSRobert Watson #include <sys/vnode.h> 4891f37dcbSRobert Watson #include <sys/lock.h> 49f708f4d1SMatthew Dillon #include <sys/mutex.h> 5091f37dcbSRobert Watson #include <sys/namei.h> 5191f37dcbSRobert Watson #include <sys/file.h> 5213438f68SAlfred Perlstein #include <sys/filedesc.h> 5391f37dcbSRobert Watson #include <sys/proc.h> 5491f37dcbSRobert Watson #include <sys/sysent.h> 5591f37dcbSRobert Watson #include <sys/acl.h> 5691f37dcbSRobert Watson 57d1dfd921SChristian S.J. Peron #include <vm/uma.h> 5891f37dcbSRobert Watson 59d1dfd921SChristian S.J. Peron uma_zone_t acl_zone; 60cbeb8402SRobert Watson static int vacl_set_acl(struct thread *td, struct vnode *vp, 61cbeb8402SRobert Watson acl_type_t type, struct acl *aclp); 62cbeb8402SRobert Watson static int vacl_get_acl(struct thread *td, struct vnode *vp, 63cbeb8402SRobert Watson acl_type_t type, struct acl *aclp); 64b40ce416SJulian Elischer static int vacl_aclcheck(struct thread *td, struct vnode *vp, 65b114e127SRobert Watson acl_type_t type, struct acl *aclp); 6691f37dcbSRobert Watson 6791f37dcbSRobert Watson /* 6891f37dcbSRobert Watson * These calls wrap the real vnode operations, and are called by the 6991f37dcbSRobert Watson * syscall code once the syscall has converted the path or file 7091f37dcbSRobert Watson * descriptor to a vnode (unlocked). The aclp pointer is assumed 7191f37dcbSRobert Watson * still to point to userland, so this should not be consumed within 7291f37dcbSRobert Watson * the kernel except by syscall code. Other code should directly 7391f37dcbSRobert Watson * invoke VOP_{SET,GET}ACL. 7491f37dcbSRobert Watson */ 7591f37dcbSRobert Watson 7691f37dcbSRobert Watson /* 7791f37dcbSRobert Watson * Given a vnode, set its ACL. 7891f37dcbSRobert Watson */ 7991f37dcbSRobert Watson static int 80b40ce416SJulian Elischer vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 8191f37dcbSRobert Watson struct acl *aclp) 8291f37dcbSRobert Watson { 8391f37dcbSRobert Watson struct acl inkernacl; 844e1123c7SRobert Watson struct mount *mp; 8591f37dcbSRobert Watson int error; 8691f37dcbSRobert Watson 8791f37dcbSRobert Watson error = copyin(aclp, &inkernacl, sizeof(struct acl)); 8891f37dcbSRobert Watson if (error) 8991f37dcbSRobert Watson return(error); 904e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 914e1123c7SRobert Watson if (error != 0) 924e1123c7SRobert Watson return (error); 93a854ed98SJohn Baldwin VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 94b40ce416SJulian Elischer vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 95c86ca022SRobert Watson #ifdef MAC 96c86ca022SRobert Watson error = mac_check_vnode_setacl(td->td_ucred, vp, type, &inkernacl); 97c86ca022SRobert Watson if (error != 0) 98c86ca022SRobert Watson goto out; 99c86ca022SRobert Watson #endif 100a854ed98SJohn Baldwin error = VOP_SETACL(vp, type, &inkernacl, td->td_ucred, td); 101c86ca022SRobert Watson #ifdef MAC 102c86ca022SRobert Watson out: 103c86ca022SRobert Watson #endif 104b40ce416SJulian Elischer VOP_UNLOCK(vp, 0, td); 1054e1123c7SRobert Watson vn_finished_write(mp); 10691f37dcbSRobert Watson return(error); 10791f37dcbSRobert Watson } 10891f37dcbSRobert Watson 10991f37dcbSRobert Watson /* 11091f37dcbSRobert Watson * Given a vnode, get its ACL. 11191f37dcbSRobert Watson */ 11291f37dcbSRobert Watson static int 113b40ce416SJulian Elischer vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type, 11491f37dcbSRobert Watson struct acl *aclp) 11591f37dcbSRobert Watson { 11691f37dcbSRobert Watson struct acl inkernelacl; 11791f37dcbSRobert Watson int error; 11891f37dcbSRobert Watson 119a854ed98SJohn Baldwin VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 120b40ce416SJulian Elischer vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 121c86ca022SRobert Watson #ifdef MAC 122c86ca022SRobert Watson error = mac_check_vnode_getacl(td->td_ucred, vp, type); 123c86ca022SRobert Watson if (error != 0) 124c86ca022SRobert Watson goto out; 125c86ca022SRobert Watson #endif 126a854ed98SJohn Baldwin error = VOP_GETACL(vp, type, &inkernelacl, td->td_ucred, td); 127c86ca022SRobert Watson #ifdef MAC 128c86ca022SRobert Watson out: 129c86ca022SRobert Watson #endif 130b40ce416SJulian Elischer VOP_UNLOCK(vp, 0, td); 13191f37dcbSRobert Watson if (error == 0) 13291f37dcbSRobert Watson error = copyout(&inkernelacl, aclp, sizeof(struct acl)); 13391f37dcbSRobert Watson return (error); 13491f37dcbSRobert Watson } 13591f37dcbSRobert Watson 13691f37dcbSRobert Watson /* 13791f37dcbSRobert Watson * Given a vnode, delete its ACL. 13891f37dcbSRobert Watson */ 13991f37dcbSRobert Watson static int 140b40ce416SJulian Elischer vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type) 14191f37dcbSRobert Watson { 1424e1123c7SRobert Watson struct mount *mp; 14391f37dcbSRobert Watson int error; 14491f37dcbSRobert Watson 1454e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 1464e1123c7SRobert Watson if (error) 1474e1123c7SRobert Watson return (error); 148a854ed98SJohn Baldwin VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 149b40ce416SJulian Elischer vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 150c86ca022SRobert Watson #ifdef MAC 151c86ca022SRobert Watson error = mac_check_vnode_deleteacl(td->td_ucred, vp, type); 152c86ca022SRobert Watson if (error) 153c86ca022SRobert Watson goto out; 154c86ca022SRobert Watson #endif 155c86ca022SRobert Watson error = VOP_SETACL(vp, type, 0, td->td_ucred, td); 156c86ca022SRobert Watson #ifdef MAC 157c86ca022SRobert Watson out: 158c86ca022SRobert Watson #endif 159b40ce416SJulian Elischer VOP_UNLOCK(vp, 0, td); 1604e1123c7SRobert Watson vn_finished_write(mp); 16191f37dcbSRobert Watson return (error); 16291f37dcbSRobert Watson } 16391f37dcbSRobert Watson 16491f37dcbSRobert Watson /* 16591f37dcbSRobert Watson * Given a vnode, check whether an ACL is appropriate for it 16691f37dcbSRobert Watson */ 16791f37dcbSRobert Watson static int 168b40ce416SJulian Elischer vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 16991f37dcbSRobert Watson struct acl *aclp) 17091f37dcbSRobert Watson { 17191f37dcbSRobert Watson struct acl inkernelacl; 17291f37dcbSRobert Watson int error; 17391f37dcbSRobert Watson 17491f37dcbSRobert Watson error = copyin(aclp, &inkernelacl, sizeof(struct acl)); 17591f37dcbSRobert Watson if (error) 17691f37dcbSRobert Watson return(error); 177a854ed98SJohn Baldwin error = VOP_ACLCHECK(vp, type, &inkernelacl, td->td_ucred, td); 17891f37dcbSRobert Watson return (error); 17991f37dcbSRobert Watson } 18091f37dcbSRobert Watson 18191f37dcbSRobert Watson /* 18291f37dcbSRobert Watson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. 18391f37dcbSRobert Watson * Don't need to lock, as the vacl_ code will get/release any locks 18491f37dcbSRobert Watson * required. 18591f37dcbSRobert Watson */ 18691f37dcbSRobert Watson 18791f37dcbSRobert Watson /* 18891f37dcbSRobert Watson * Given a file path, get an ACL for it 189f708f4d1SMatthew Dillon * 190f708f4d1SMatthew Dillon * MPSAFE 19191f37dcbSRobert Watson */ 19291f37dcbSRobert Watson int 193b40ce416SJulian Elischer __acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 19491f37dcbSRobert Watson { 19591f37dcbSRobert Watson struct nameidata nd; 19642e7197fSChristian S.J. Peron int vfslocked, error; 19791f37dcbSRobert Watson 19842e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 19991f37dcbSRobert Watson error = namei(&nd); 20042e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 201f708f4d1SMatthew Dillon if (error == 0) { 202f97182acSAlfred Perlstein error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 20391f37dcbSRobert Watson NDFREE(&nd, 0); 204f708f4d1SMatthew Dillon } 20542e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 20691f37dcbSRobert Watson return (error); 20791f37dcbSRobert Watson } 20891f37dcbSRobert Watson 20991f37dcbSRobert Watson /* 2103c67c23bSRobert Watson * Given a file path, get an ACL for it; don't follow links. 2113c67c23bSRobert Watson * 2123c67c23bSRobert Watson * MPSAFE 2133c67c23bSRobert Watson */ 2143c67c23bSRobert Watson int 2153c67c23bSRobert Watson __acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 2163c67c23bSRobert Watson { 2173c67c23bSRobert Watson struct nameidata nd; 21842e7197fSChristian S.J. Peron int vfslocked, error; 2193c67c23bSRobert Watson 22042e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 2213c67c23bSRobert Watson error = namei(&nd); 22242e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 2233c67c23bSRobert Watson if (error == 0) { 2243c67c23bSRobert Watson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 2253c67c23bSRobert Watson NDFREE(&nd, 0); 2263c67c23bSRobert Watson } 22742e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 2283c67c23bSRobert Watson return (error); 2293c67c23bSRobert Watson } 2303c67c23bSRobert Watson 2313c67c23bSRobert Watson /* 23291f37dcbSRobert Watson * Given a file path, set an ACL for it 233f708f4d1SMatthew Dillon * 234f708f4d1SMatthew Dillon * MPSAFE 23591f37dcbSRobert Watson */ 23691f37dcbSRobert Watson int 237b40ce416SJulian Elischer __acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 23891f37dcbSRobert Watson { 23991f37dcbSRobert Watson struct nameidata nd; 24042e7197fSChristian S.J. Peron int vfslocked, error; 24191f37dcbSRobert Watson 24242e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 24391f37dcbSRobert Watson error = namei(&nd); 24442e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 245f708f4d1SMatthew Dillon if (error == 0) { 246f97182acSAlfred Perlstein error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 24791f37dcbSRobert Watson NDFREE(&nd, 0); 248f708f4d1SMatthew Dillon } 24942e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 25091f37dcbSRobert Watson return (error); 25191f37dcbSRobert Watson } 25291f37dcbSRobert Watson 25391f37dcbSRobert Watson /* 2543c67c23bSRobert Watson * Given a file path, set an ACL for it; don't follow links. 2553c67c23bSRobert Watson * 2563c67c23bSRobert Watson * MPSAFE 2573c67c23bSRobert Watson */ 2583c67c23bSRobert Watson int 2593c67c23bSRobert Watson __acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 2603c67c23bSRobert Watson { 2613c67c23bSRobert Watson struct nameidata nd; 26242e7197fSChristian S.J. Peron int vfslocked, error; 2633c67c23bSRobert Watson 26442e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 2653c67c23bSRobert Watson error = namei(&nd); 26642e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 2673c67c23bSRobert Watson if (error == 0) { 2683c67c23bSRobert Watson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 2693c67c23bSRobert Watson NDFREE(&nd, 0); 2703c67c23bSRobert Watson } 27142e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 2723c67c23bSRobert Watson return (error); 2733c67c23bSRobert Watson } 2743c67c23bSRobert Watson 2753c67c23bSRobert Watson /* 27691f37dcbSRobert Watson * Given a file descriptor, get an ACL for it 277f708f4d1SMatthew Dillon * 278f708f4d1SMatthew Dillon * MPSAFE 27991f37dcbSRobert Watson */ 28091f37dcbSRobert Watson int 281b40ce416SJulian Elischer __acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 28291f37dcbSRobert Watson { 28391f37dcbSRobert Watson struct file *fp; 28442e7197fSChristian S.J. Peron int vfslocked, error; 28591f37dcbSRobert Watson 286d1e405c5SAlfred Perlstein error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 287f708f4d1SMatthew Dillon if (error == 0) { 28842e7197fSChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 2893b6d9652SPoul-Henning Kamp error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 290426da3bcSAlfred Perlstein fdrop(fp, td); 29142e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 292f708f4d1SMatthew Dillon } 29391f37dcbSRobert Watson return (error); 29491f37dcbSRobert Watson } 29591f37dcbSRobert Watson 29691f37dcbSRobert Watson /* 29791f37dcbSRobert Watson * Given a file descriptor, set an ACL for it 298f708f4d1SMatthew Dillon * 299f708f4d1SMatthew Dillon * MPSAFE 30091f37dcbSRobert Watson */ 30191f37dcbSRobert Watson int 302b40ce416SJulian Elischer __acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 30391f37dcbSRobert Watson { 30491f37dcbSRobert Watson struct file *fp; 30542e7197fSChristian S.J. Peron int vfslocked, error; 30691f37dcbSRobert Watson 307d1e405c5SAlfred Perlstein error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 308f708f4d1SMatthew Dillon if (error == 0) { 30942e7197fSChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 3103b6d9652SPoul-Henning Kamp error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 311426da3bcSAlfred Perlstein fdrop(fp, td); 31242e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 313f708f4d1SMatthew Dillon } 31491f37dcbSRobert Watson return (error); 31591f37dcbSRobert Watson } 31691f37dcbSRobert Watson 31791f37dcbSRobert Watson /* 31891f37dcbSRobert Watson * Given a file path, delete an ACL from it. 319f708f4d1SMatthew Dillon * 320f708f4d1SMatthew Dillon * MPSAFE 32191f37dcbSRobert Watson */ 32291f37dcbSRobert Watson int 323b40ce416SJulian Elischer __acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 32491f37dcbSRobert Watson { 32591f37dcbSRobert Watson struct nameidata nd; 32642e7197fSChristian S.J. Peron int vfslocked, error; 32791f37dcbSRobert Watson 32842e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 32991f37dcbSRobert Watson error = namei(&nd); 33042e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 331f708f4d1SMatthew Dillon if (error == 0) { 332d1e405c5SAlfred Perlstein error = vacl_delete(td, nd.ni_vp, uap->type); 33391f37dcbSRobert Watson NDFREE(&nd, 0); 334f708f4d1SMatthew Dillon } 33542e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 33691f37dcbSRobert Watson return (error); 33791f37dcbSRobert Watson } 33891f37dcbSRobert Watson 33991f37dcbSRobert Watson /* 3403c67c23bSRobert Watson * Given a file path, delete an ACL from it; don't follow links. 3413c67c23bSRobert Watson * 3423c67c23bSRobert Watson * MPSAFE 3433c67c23bSRobert Watson */ 3443c67c23bSRobert Watson int 3453c67c23bSRobert Watson __acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 3463c67c23bSRobert Watson { 3473c67c23bSRobert Watson struct nameidata nd; 34842e7197fSChristian S.J. Peron int vfslocked, error; 3493c67c23bSRobert Watson 35042e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 3513c67c23bSRobert Watson error = namei(&nd); 35242e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 3533c67c23bSRobert Watson if (error == 0) { 3543c67c23bSRobert Watson error = vacl_delete(td, nd.ni_vp, uap->type); 3553c67c23bSRobert Watson NDFREE(&nd, 0); 3563c67c23bSRobert Watson } 35742e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 3583c67c23bSRobert Watson return (error); 3593c67c23bSRobert Watson } 3603c67c23bSRobert Watson 3613c67c23bSRobert Watson /* 36291f37dcbSRobert Watson * Given a file path, delete an ACL from it. 363f708f4d1SMatthew Dillon * 364f708f4d1SMatthew Dillon * MPSAFE 36591f37dcbSRobert Watson */ 36691f37dcbSRobert Watson int 367b40ce416SJulian Elischer __acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 36891f37dcbSRobert Watson { 36991f37dcbSRobert Watson struct file *fp; 37042e7197fSChristian S.J. Peron int vfslocked, error; 37191f37dcbSRobert Watson 372d1e405c5SAlfred Perlstein error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 373f708f4d1SMatthew Dillon if (error == 0) { 37442e7197fSChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 3753b6d9652SPoul-Henning Kamp error = vacl_delete(td, fp->f_vnode, uap->type); 376426da3bcSAlfred Perlstein fdrop(fp, td); 37742e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 378f708f4d1SMatthew Dillon } 37991f37dcbSRobert Watson return (error); 38091f37dcbSRobert Watson } 38191f37dcbSRobert Watson 38291f37dcbSRobert Watson /* 38391f37dcbSRobert Watson * Given a file path, check an ACL for it 384f708f4d1SMatthew Dillon * 385f708f4d1SMatthew Dillon * MPSAFE 38691f37dcbSRobert Watson */ 38791f37dcbSRobert Watson int 388b40ce416SJulian Elischer __acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 38991f37dcbSRobert Watson { 39091f37dcbSRobert Watson struct nameidata nd; 39142e7197fSChristian S.J. Peron int vfslocked, error; 39291f37dcbSRobert Watson 39342e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 39491f37dcbSRobert Watson error = namei(&nd); 39542e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 396f708f4d1SMatthew Dillon if (error == 0) { 397f97182acSAlfred Perlstein error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 39891f37dcbSRobert Watson NDFREE(&nd, 0); 399f708f4d1SMatthew Dillon } 40042e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 40191f37dcbSRobert Watson return (error); 40291f37dcbSRobert Watson } 40391f37dcbSRobert Watson 40491f37dcbSRobert Watson /* 4053c67c23bSRobert Watson * Given a file path, check an ACL for it; don't follow links. 4063c67c23bSRobert Watson * 4073c67c23bSRobert Watson * MPSAFE 4083c67c23bSRobert Watson */ 4093c67c23bSRobert Watson int 4103c67c23bSRobert Watson __acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 4113c67c23bSRobert Watson { 4123c67c23bSRobert Watson struct nameidata nd; 41342e7197fSChristian S.J. Peron int vfslocked, error; 4143c67c23bSRobert Watson 41542e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 4163c67c23bSRobert Watson error = namei(&nd); 41742e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 4183c67c23bSRobert Watson if (error == 0) { 4193c67c23bSRobert Watson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 4203c67c23bSRobert Watson NDFREE(&nd, 0); 4213c67c23bSRobert Watson } 42242e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 4233c67c23bSRobert Watson return (error); 4243c67c23bSRobert Watson } 4253c67c23bSRobert Watson 4263c67c23bSRobert Watson /* 42791f37dcbSRobert Watson * Given a file descriptor, check an ACL for it 428f708f4d1SMatthew Dillon * 429f708f4d1SMatthew Dillon * MPSAFE 43091f37dcbSRobert Watson */ 43191f37dcbSRobert Watson int 432b40ce416SJulian Elischer __acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 43391f37dcbSRobert Watson { 43491f37dcbSRobert Watson struct file *fp; 43542e7197fSChristian S.J. Peron int vfslocked, error; 43691f37dcbSRobert Watson 437d1e405c5SAlfred Perlstein error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 438f708f4d1SMatthew Dillon if (error == 0) { 43942e7197fSChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 4403b6d9652SPoul-Henning Kamp error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 441426da3bcSAlfred Perlstein fdrop(fp, td); 44242e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 443f708f4d1SMatthew Dillon } 44491f37dcbSRobert Watson return (error); 44591f37dcbSRobert Watson } 446d1dfd921SChristian S.J. Peron 447d1dfd921SChristian S.J. Peron /* ARGUSED */ 448d1dfd921SChristian S.J. Peron 449d1dfd921SChristian S.J. Peron static void 450d1dfd921SChristian S.J. Peron aclinit(void *dummy __unused) 451d1dfd921SChristian S.J. Peron { 452d1dfd921SChristian S.J. Peron 453d1dfd921SChristian S.J. Peron acl_zone = uma_zcreate("ACL UMA zone", sizeof(struct acl), 454d1dfd921SChristian S.J. Peron NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 455d1dfd921SChristian S.J. Peron } 456d1dfd921SChristian S.J. Peron SYSINIT(acls, SI_SUB_ACL, SI_ORDER_FIRST, aclinit, NULL) 457