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> 4357b4252eSKonstantin Belousov #include <sys/fcntl.h> 4491f37dcbSRobert Watson #include <sys/kernel.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 57aed55708SRobert Watson #include <security/mac/mac_framework.h> 58aed55708SRobert Watson 59d1dfd921SChristian S.J. Peron #include <vm/uma.h> 6091f37dcbSRobert Watson 61d1dfd921SChristian S.J. Peron uma_zone_t acl_zone; 62cbeb8402SRobert Watson static int vacl_set_acl(struct thread *td, struct vnode *vp, 63cbeb8402SRobert Watson acl_type_t type, struct acl *aclp); 64cbeb8402SRobert Watson static int vacl_get_acl(struct thread *td, struct vnode *vp, 65cbeb8402SRobert Watson acl_type_t type, struct acl *aclp); 66b40ce416SJulian Elischer static int vacl_aclcheck(struct thread *td, struct vnode *vp, 67b114e127SRobert Watson acl_type_t type, struct acl *aclp); 6891f37dcbSRobert Watson 6991f37dcbSRobert Watson /* 70b0c521e2SRobert Watson * These calls wrap the real vnode operations, and are called by the syscall 71b0c521e2SRobert Watson * code once the syscall has converted the path or file descriptor to a vnode 72b0c521e2SRobert Watson * (unlocked). The aclp pointer is assumed still to point to userland, so 73b0c521e2SRobert Watson * this should not be consumed within the kernel except by syscall code. 74b0c521e2SRobert Watson * Other code should directly invoke VOP_{SET,GET}ACL. 7591f37dcbSRobert Watson */ 7691f37dcbSRobert Watson 7791f37dcbSRobert Watson /* 7891f37dcbSRobert Watson * Given a vnode, set its ACL. 7991f37dcbSRobert Watson */ 8091f37dcbSRobert Watson static int 81b40ce416SJulian Elischer vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 8291f37dcbSRobert Watson struct acl *aclp) 8391f37dcbSRobert Watson { 84b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 854e1123c7SRobert Watson struct mount *mp; 8691f37dcbSRobert Watson int error; 8791f37dcbSRobert Watson 88b998d381SEdward Tomasz Napierala inkernelacl = acl_alloc(M_WAITOK); 89b998d381SEdward Tomasz Napierala error = copyin(aclp, inkernelacl, sizeof(struct acl)); 9091f37dcbSRobert Watson if (error) 91b998d381SEdward Tomasz Napierala goto out; 924e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 934e1123c7SRobert Watson if (error != 0) 94b998d381SEdward Tomasz Napierala goto out; 95cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 96c86ca022SRobert Watson #ifdef MAC 97b998d381SEdward Tomasz Napierala error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 98c86ca022SRobert Watson if (error != 0) 99b998d381SEdward Tomasz Napierala goto out_unlock; 100c86ca022SRobert Watson #endif 101b998d381SEdward Tomasz Napierala error = VOP_SETACL(vp, type, inkernelacl, td->td_ucred, td); 102c86ca022SRobert Watson #ifdef MAC 103b998d381SEdward Tomasz Napierala out_unlock: 104c86ca022SRobert Watson #endif 10522db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 1064e1123c7SRobert Watson vn_finished_write(mp); 107b998d381SEdward Tomasz Napierala out: 108b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 10991f37dcbSRobert Watson return(error); 11091f37dcbSRobert Watson } 11191f37dcbSRobert Watson 11291f37dcbSRobert Watson /* 11391f37dcbSRobert Watson * Given a vnode, get its ACL. 11491f37dcbSRobert Watson */ 11591f37dcbSRobert Watson static int 116b40ce416SJulian Elischer vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type, 11791f37dcbSRobert Watson struct acl *aclp) 11891f37dcbSRobert Watson { 119b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 12091f37dcbSRobert Watson int error; 12191f37dcbSRobert Watson 122b998d381SEdward Tomasz Napierala inkernelacl = acl_alloc(M_WAITOK); 123cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 124c86ca022SRobert Watson #ifdef MAC 12530d239bcSRobert Watson error = mac_vnode_check_getacl(td->td_ucred, vp, type); 126c86ca022SRobert Watson if (error != 0) 127c86ca022SRobert Watson goto out; 128c86ca022SRobert Watson #endif 129b998d381SEdward Tomasz Napierala error = VOP_GETACL(vp, type, inkernelacl, td->td_ucred, td); 130c86ca022SRobert Watson #ifdef MAC 131c86ca022SRobert Watson out: 132c86ca022SRobert Watson #endif 13322db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 13491f37dcbSRobert Watson if (error == 0) 135b998d381SEdward Tomasz Napierala error = copyout(inkernelacl, aclp, sizeof(struct acl)); 136b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 13791f37dcbSRobert Watson return (error); 13891f37dcbSRobert Watson } 13991f37dcbSRobert Watson 14091f37dcbSRobert Watson /* 14191f37dcbSRobert Watson * Given a vnode, delete its ACL. 14291f37dcbSRobert Watson */ 14391f37dcbSRobert Watson static int 144b40ce416SJulian Elischer vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type) 14591f37dcbSRobert Watson { 1464e1123c7SRobert Watson struct mount *mp; 14791f37dcbSRobert Watson int error; 14891f37dcbSRobert Watson 1494e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 1504e1123c7SRobert Watson if (error) 1514e1123c7SRobert Watson return (error); 152cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 153c86ca022SRobert Watson #ifdef MAC 15430d239bcSRobert Watson error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 155c86ca022SRobert Watson if (error) 156c86ca022SRobert Watson goto out; 157c86ca022SRobert Watson #endif 158c86ca022SRobert Watson error = VOP_SETACL(vp, type, 0, td->td_ucred, td); 159c86ca022SRobert Watson #ifdef MAC 160c86ca022SRobert Watson out: 161c86ca022SRobert Watson #endif 16222db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 1634e1123c7SRobert Watson vn_finished_write(mp); 16491f37dcbSRobert Watson return (error); 16591f37dcbSRobert Watson } 16691f37dcbSRobert Watson 16791f37dcbSRobert Watson /* 16891f37dcbSRobert Watson * Given a vnode, check whether an ACL is appropriate for it 16991f37dcbSRobert Watson */ 17091f37dcbSRobert Watson static int 171b40ce416SJulian Elischer vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 17291f37dcbSRobert Watson struct acl *aclp) 17391f37dcbSRobert Watson { 174b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 17591f37dcbSRobert Watson int error; 17691f37dcbSRobert Watson 177b998d381SEdward Tomasz Napierala inkernelacl = acl_alloc(M_WAITOK); 178b998d381SEdward Tomasz Napierala error = copyin(aclp, inkernelacl, sizeof(struct acl)); 17991f37dcbSRobert Watson if (error) 180b998d381SEdward Tomasz Napierala goto out; 181b998d381SEdward Tomasz Napierala error = VOP_ACLCHECK(vp, type, inkernelacl, td->td_ucred, td); 182b998d381SEdward Tomasz Napierala out: 183b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 18491f37dcbSRobert Watson return (error); 18591f37dcbSRobert Watson } 18691f37dcbSRobert Watson 18791f37dcbSRobert Watson /* 188b0c521e2SRobert Watson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't 189b0c521e2SRobert Watson * need to lock, as the vacl_ code will get/release any locks required. 19091f37dcbSRobert Watson */ 19191f37dcbSRobert Watson 19291f37dcbSRobert Watson /* 19391f37dcbSRobert Watson * Given a file path, get an ACL for it 19491f37dcbSRobert Watson */ 19591f37dcbSRobert Watson int 196b40ce416SJulian Elischer __acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 19791f37dcbSRobert Watson { 19891f37dcbSRobert Watson struct nameidata nd; 19942e7197fSChristian S.J. Peron int vfslocked, error; 20091f37dcbSRobert Watson 20142e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 20291f37dcbSRobert Watson error = namei(&nd); 20342e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 204f708f4d1SMatthew Dillon if (error == 0) { 205f97182acSAlfred Perlstein error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 20691f37dcbSRobert Watson NDFREE(&nd, 0); 207f708f4d1SMatthew Dillon } 20842e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 20991f37dcbSRobert Watson return (error); 21091f37dcbSRobert Watson } 21191f37dcbSRobert Watson 21291f37dcbSRobert Watson /* 2133c67c23bSRobert Watson * Given a file path, get an ACL for it; don't follow links. 2143c67c23bSRobert Watson */ 2153c67c23bSRobert Watson int 2163c67c23bSRobert Watson __acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 2173c67c23bSRobert Watson { 2183c67c23bSRobert Watson struct nameidata nd; 21942e7197fSChristian S.J. Peron int vfslocked, error; 2203c67c23bSRobert Watson 22142e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 2223c67c23bSRobert Watson error = namei(&nd); 22342e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 2243c67c23bSRobert Watson if (error == 0) { 2253c67c23bSRobert Watson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 2263c67c23bSRobert Watson NDFREE(&nd, 0); 2273c67c23bSRobert Watson } 22842e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 2293c67c23bSRobert Watson return (error); 2303c67c23bSRobert Watson } 2313c67c23bSRobert Watson 2323c67c23bSRobert Watson /* 2330c14ff0eSRobert Watson * Given a file path, set an ACL for it. 23491f37dcbSRobert Watson */ 23591f37dcbSRobert Watson int 236b40ce416SJulian Elischer __acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 23791f37dcbSRobert Watson { 23891f37dcbSRobert Watson struct nameidata nd; 23942e7197fSChristian S.J. Peron int vfslocked, error; 24091f37dcbSRobert Watson 24142e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 24291f37dcbSRobert Watson error = namei(&nd); 24342e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 244f708f4d1SMatthew Dillon if (error == 0) { 245f97182acSAlfred Perlstein error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 24691f37dcbSRobert Watson NDFREE(&nd, 0); 247f708f4d1SMatthew Dillon } 24842e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 24991f37dcbSRobert Watson return (error); 25091f37dcbSRobert Watson } 25191f37dcbSRobert Watson 25291f37dcbSRobert Watson /* 2533c67c23bSRobert Watson * Given a file path, set an ACL for it; don't follow links. 2543c67c23bSRobert Watson */ 2553c67c23bSRobert Watson int 2563c67c23bSRobert Watson __acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 2573c67c23bSRobert Watson { 2583c67c23bSRobert Watson struct nameidata nd; 25942e7197fSChristian S.J. Peron int vfslocked, error; 2603c67c23bSRobert Watson 26142e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 2623c67c23bSRobert Watson error = namei(&nd); 26342e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 2643c67c23bSRobert Watson if (error == 0) { 2653c67c23bSRobert Watson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 2663c67c23bSRobert Watson NDFREE(&nd, 0); 2673c67c23bSRobert Watson } 26842e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 2693c67c23bSRobert Watson return (error); 2703c67c23bSRobert Watson } 2713c67c23bSRobert Watson 2723c67c23bSRobert Watson /* 273b5368498SRobert Watson * Given a file descriptor, get an ACL for it. 27491f37dcbSRobert Watson */ 27591f37dcbSRobert Watson int 276b40ce416SJulian Elischer __acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 27791f37dcbSRobert Watson { 27891f37dcbSRobert Watson struct file *fp; 27942e7197fSChristian S.J. Peron int vfslocked, error; 28091f37dcbSRobert Watson 281d1e405c5SAlfred Perlstein error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 282f708f4d1SMatthew Dillon if (error == 0) { 28342e7197fSChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 2843b6d9652SPoul-Henning Kamp error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 285426da3bcSAlfred Perlstein fdrop(fp, td); 28642e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 287f708f4d1SMatthew Dillon } 28891f37dcbSRobert Watson return (error); 28991f37dcbSRobert Watson } 29091f37dcbSRobert Watson 29191f37dcbSRobert Watson /* 292b5368498SRobert Watson * Given a file descriptor, set an ACL for it. 29391f37dcbSRobert Watson */ 29491f37dcbSRobert Watson int 295b40ce416SJulian Elischer __acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 29691f37dcbSRobert Watson { 29791f37dcbSRobert Watson struct file *fp; 29842e7197fSChristian S.J. Peron int vfslocked, error; 29991f37dcbSRobert Watson 300d1e405c5SAlfred Perlstein error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 301f708f4d1SMatthew Dillon if (error == 0) { 30242e7197fSChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 3033b6d9652SPoul-Henning Kamp error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 304426da3bcSAlfred Perlstein fdrop(fp, td); 30542e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 306f708f4d1SMatthew Dillon } 30791f37dcbSRobert Watson return (error); 30891f37dcbSRobert Watson } 30991f37dcbSRobert Watson 31091f37dcbSRobert Watson /* 31191f37dcbSRobert Watson * Given a file path, delete an ACL from it. 31291f37dcbSRobert Watson */ 31391f37dcbSRobert Watson int 314b40ce416SJulian Elischer __acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 31591f37dcbSRobert Watson { 31691f37dcbSRobert Watson struct nameidata nd; 31742e7197fSChristian S.J. Peron int vfslocked, error; 31891f37dcbSRobert Watson 31942e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 32091f37dcbSRobert Watson error = namei(&nd); 32142e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 322f708f4d1SMatthew Dillon if (error == 0) { 323d1e405c5SAlfred Perlstein error = vacl_delete(td, nd.ni_vp, uap->type); 32491f37dcbSRobert Watson NDFREE(&nd, 0); 325f708f4d1SMatthew Dillon } 32642e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 32791f37dcbSRobert Watson return (error); 32891f37dcbSRobert Watson } 32991f37dcbSRobert Watson 33091f37dcbSRobert Watson /* 3313c67c23bSRobert Watson * Given a file path, delete an ACL from it; don't follow links. 3323c67c23bSRobert Watson */ 3333c67c23bSRobert Watson int 3343c67c23bSRobert Watson __acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 3353c67c23bSRobert Watson { 3363c67c23bSRobert Watson struct nameidata nd; 33742e7197fSChristian S.J. Peron int vfslocked, error; 3383c67c23bSRobert Watson 33942e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 3403c67c23bSRobert Watson error = namei(&nd); 34142e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 3423c67c23bSRobert Watson if (error == 0) { 3433c67c23bSRobert Watson error = vacl_delete(td, nd.ni_vp, uap->type); 3443c67c23bSRobert Watson NDFREE(&nd, 0); 3453c67c23bSRobert Watson } 34642e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 3473c67c23bSRobert Watson return (error); 3483c67c23bSRobert Watson } 3493c67c23bSRobert Watson 3503c67c23bSRobert Watson /* 35191f37dcbSRobert Watson * Given a file path, delete an ACL from it. 35291f37dcbSRobert Watson */ 35391f37dcbSRobert Watson int 354b40ce416SJulian Elischer __acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 35591f37dcbSRobert Watson { 35691f37dcbSRobert Watson struct file *fp; 35742e7197fSChristian S.J. Peron int vfslocked, error; 35891f37dcbSRobert Watson 359d1e405c5SAlfred Perlstein error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 360f708f4d1SMatthew Dillon if (error == 0) { 36142e7197fSChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 3623b6d9652SPoul-Henning Kamp error = vacl_delete(td, fp->f_vnode, uap->type); 363426da3bcSAlfred Perlstein fdrop(fp, td); 36442e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 365f708f4d1SMatthew Dillon } 36691f37dcbSRobert Watson return (error); 36791f37dcbSRobert Watson } 36891f37dcbSRobert Watson 36991f37dcbSRobert Watson /* 3700c14ff0eSRobert Watson * Given a file path, check an ACL for it. 37191f37dcbSRobert Watson */ 37291f37dcbSRobert Watson int 373b40ce416SJulian Elischer __acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 37491f37dcbSRobert Watson { 37591f37dcbSRobert Watson struct nameidata nd; 37642e7197fSChristian S.J. Peron int vfslocked, error; 37791f37dcbSRobert Watson 37842e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 37991f37dcbSRobert Watson error = namei(&nd); 38042e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 381f708f4d1SMatthew Dillon if (error == 0) { 382f97182acSAlfred Perlstein error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 38391f37dcbSRobert Watson NDFREE(&nd, 0); 384f708f4d1SMatthew Dillon } 38542e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 38691f37dcbSRobert Watson return (error); 38791f37dcbSRobert Watson } 38891f37dcbSRobert Watson 38991f37dcbSRobert Watson /* 3903c67c23bSRobert Watson * Given a file path, check an ACL for it; don't follow links. 3913c67c23bSRobert Watson */ 3923c67c23bSRobert Watson int 3933c67c23bSRobert Watson __acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 3943c67c23bSRobert Watson { 3953c67c23bSRobert Watson struct nameidata nd; 39642e7197fSChristian S.J. Peron int vfslocked, error; 3973c67c23bSRobert Watson 39842e7197fSChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 3993c67c23bSRobert Watson error = namei(&nd); 40042e7197fSChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 4013c67c23bSRobert Watson if (error == 0) { 4023c67c23bSRobert Watson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 4033c67c23bSRobert Watson NDFREE(&nd, 0); 4043c67c23bSRobert Watson } 40542e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 4063c67c23bSRobert Watson return (error); 4073c67c23bSRobert Watson } 4083c67c23bSRobert Watson 4093c67c23bSRobert Watson /* 4100c14ff0eSRobert Watson * Given a file descriptor, check an ACL for it. 41191f37dcbSRobert Watson */ 41291f37dcbSRobert Watson int 413b40ce416SJulian Elischer __acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 41491f37dcbSRobert Watson { 41591f37dcbSRobert Watson struct file *fp; 41642e7197fSChristian S.J. Peron int vfslocked, error; 41791f37dcbSRobert Watson 418d1e405c5SAlfred Perlstein error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 419f708f4d1SMatthew Dillon if (error == 0) { 42042e7197fSChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 4213b6d9652SPoul-Henning Kamp error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 422426da3bcSAlfred Perlstein fdrop(fp, td); 42342e7197fSChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 424f708f4d1SMatthew Dillon } 42591f37dcbSRobert Watson return (error); 42691f37dcbSRobert Watson } 427d1dfd921SChristian S.J. Peron 428b998d381SEdward Tomasz Napierala struct acl * 429b998d381SEdward Tomasz Napierala acl_alloc(int flags) 430b998d381SEdward Tomasz Napierala { 431b998d381SEdward Tomasz Napierala struct acl *aclp; 432b998d381SEdward Tomasz Napierala 433b998d381SEdward Tomasz Napierala aclp = uma_zalloc(acl_zone, flags); 434b998d381SEdward Tomasz Napierala 435b998d381SEdward Tomasz Napierala return (aclp); 436b998d381SEdward Tomasz Napierala } 437b998d381SEdward Tomasz Napierala 438b998d381SEdward Tomasz Napierala void 439b998d381SEdward Tomasz Napierala acl_free(struct acl *aclp) 440b998d381SEdward Tomasz Napierala { 441b998d381SEdward Tomasz Napierala 442b998d381SEdward Tomasz Napierala uma_zfree(acl_zone, aclp); 443b998d381SEdward Tomasz Napierala } 444b998d381SEdward Tomasz Napierala 445d1dfd921SChristian S.J. Peron /* ARGUSED */ 446d1dfd921SChristian S.J. Peron 447d1dfd921SChristian S.J. Peron static void 448d1dfd921SChristian S.J. Peron aclinit(void *dummy __unused) 449d1dfd921SChristian S.J. Peron { 450d1dfd921SChristian S.J. Peron 451d1dfd921SChristian S.J. Peron acl_zone = uma_zcreate("ACL UMA zone", sizeof(struct acl), 452d1dfd921SChristian S.J. Peron NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 453d1dfd921SChristian S.J. Peron } 454237fdd78SRobert Watson SYSINIT(acls, SI_SUB_ACL, SI_ORDER_FIRST, aclinit, NULL); 455