vfs_acl.c revision 208781
154803Srwatson/*- 2160146Srwatson * Copyright (c) 1999-2006 Robert N. M. Watson 354803Srwatson * All rights reserved. 454803Srwatson * 585845Srwatson * This software was developed by Robert Watson for the TrustedBSD Project. 685845Srwatson * 754803Srwatson * Redistribution and use in source and binary forms, with or without 854803Srwatson * modification, are permitted provided that the following conditions 954803Srwatson * are met: 1054803Srwatson * 1. Redistributions of source code must retain the above copyright 1154803Srwatson * notice, this list of conditions and the following disclaimer. 1254803Srwatson * 2. Redistributions in binary form must reproduce the above copyright 1354803Srwatson * notice, this list of conditions and the following disclaimer in the 1454803Srwatson * documentation and/or other materials provided with the distribution. 1554803Srwatson * 1654803Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1754803Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1854803Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1954803Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2054803Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2154803Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2254803Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2354803Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2454803Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2554803Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2654803Srwatson * SUCH DAMAGE. 2754803Srwatson */ 2854803Srwatson/* 2973890Srwatson * Developed by the TrustedBSD Project. 30160146Srwatson * 31160146Srwatson * ACL system calls and other functions common across different ACL types. 32160146Srwatson * Type-specific routines go into subr_acl_<type>.c. 3354803Srwatson */ 3454803Srwatson 35116182Sobrien#include <sys/cdefs.h> 36116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/vfs_acl.c 208781 2010-06-03 13:45:27Z trasz $"); 37116182Sobrien 3854803Srwatson#include <sys/param.h> 3954803Srwatson#include <sys/systm.h> 4054803Srwatson#include <sys/sysproto.h> 41177785Skib#include <sys/fcntl.h> 4254803Srwatson#include <sys/kernel.h> 4354803Srwatson#include <sys/malloc.h> 44150262Scsjp#include <sys/mount.h> 4554803Srwatson#include <sys/vnode.h> 4654803Srwatson#include <sys/lock.h> 4782713Sdillon#include <sys/mutex.h> 4854803Srwatson#include <sys/namei.h> 4954803Srwatson#include <sys/file.h> 50108524Salfred#include <sys/filedesc.h> 5154803Srwatson#include <sys/proc.h> 5254803Srwatson#include <sys/sysent.h> 5354803Srwatson#include <sys/acl.h> 5454803Srwatson 55163606Srwatson#include <security/mac/mac_framework.h> 56163606Srwatson 57192586StraszCTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES); 5854803Srwatson 59192586StraszMALLOC_DEFINE(M_ACL, "acl", "Access Control Lists"); 60192586Strasz 6198927Srwatsonstatic int vacl_set_acl(struct thread *td, struct vnode *vp, 6298927Srwatson acl_type_t type, struct acl *aclp); 6398927Srwatsonstatic int vacl_get_acl(struct thread *td, struct vnode *vp, 6498927Srwatson acl_type_t type, struct acl *aclp); 6585582Srwatsonstatic int vacl_aclcheck(struct thread *td, struct vnode *vp, 6698927Srwatson acl_type_t type, struct acl *aclp); 6754803Srwatson 68192586Straszint 69192586Straszacl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest) 70192586Strasz{ 71192586Strasz int i; 72192586Strasz 73192586Strasz if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES) 74192586Strasz return (EINVAL); 75192586Strasz 76192586Strasz bzero(dest, sizeof(*dest)); 77192586Strasz 78192586Strasz dest->acl_cnt = source->acl_cnt; 79192586Strasz dest->acl_maxcnt = ACL_MAX_ENTRIES; 80192586Strasz 81192586Strasz for (i = 0; i < dest->acl_cnt; i++) { 82192586Strasz dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 83192586Strasz dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 84192586Strasz dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 85192586Strasz } 86192586Strasz 87192586Strasz return (0); 88192586Strasz} 89192586Strasz 90192586Straszint 91192586Straszacl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest) 92192586Strasz{ 93192586Strasz int i; 94192586Strasz 95208781Strasz if (source->acl_cnt > OLDACL_MAX_ENTRIES) 96192586Strasz return (EINVAL); 97192586Strasz 98192586Strasz bzero(dest, sizeof(*dest)); 99192586Strasz 100192586Strasz dest->acl_cnt = source->acl_cnt; 101192586Strasz 102192586Strasz for (i = 0; i < dest->acl_cnt; i++) { 103192586Strasz dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 104192586Strasz dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 105192586Strasz dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 106192586Strasz } 107192586Strasz 108192586Strasz return (0); 109192586Strasz} 110192586Strasz 11154803Srwatson/* 112192586Strasz * At one time, "struct ACL" was extended in order to add support for NFSv4 113192586Strasz * ACLs. Instead of creating compatibility versions of all the ACL-related 114192586Strasz * syscalls, they were left intact. It's possible to find out what the code 115192586Strasz * calling these syscalls (libc) expects basing on "type" argument - if it's 116192586Strasz * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were 117192586Strasz * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct 118192586Strasz * oldacl". If it's something else, then it's the new "struct acl". In the 119192586Strasz * latter case, the routines below just copyin/copyout the contents. In the 120192586Strasz * former case, they copyin the "struct oldacl" and convert it to the new 121192586Strasz * format. 122192586Strasz */ 123192586Straszstatic int 124192586Straszacl_copyin(void *user_acl, struct acl *kernel_acl, acl_type_t type) 125192586Strasz{ 126192586Strasz int error; 127192586Strasz struct oldacl old; 128192586Strasz 129192586Strasz switch (type) { 130192586Strasz case ACL_TYPE_ACCESS_OLD: 131192586Strasz case ACL_TYPE_DEFAULT_OLD: 132192586Strasz error = copyin(user_acl, &old, sizeof(old)); 133192586Strasz if (error != 0) 134192586Strasz break; 135192586Strasz acl_copy_oldacl_into_acl(&old, kernel_acl); 136192586Strasz break; 137192586Strasz 138192586Strasz default: 139192586Strasz error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl)); 140192586Strasz if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES) 141192586Strasz return (EINVAL); 142192586Strasz } 143192586Strasz 144192586Strasz return (error); 145192586Strasz} 146192586Strasz 147192586Straszstatic int 148192586Straszacl_copyout(struct acl *kernel_acl, void *user_acl, acl_type_t type) 149192586Strasz{ 150192586Strasz int error; 151192586Strasz struct oldacl old; 152192586Strasz 153192586Strasz switch (type) { 154192586Strasz case ACL_TYPE_ACCESS_OLD: 155192586Strasz case ACL_TYPE_DEFAULT_OLD: 156192586Strasz error = acl_copy_acl_into_oldacl(kernel_acl, &old); 157192586Strasz if (error != 0) 158192586Strasz break; 159192586Strasz 160192586Strasz error = copyout(&old, user_acl, sizeof(old)); 161192586Strasz break; 162192586Strasz 163192586Strasz default: 164197789Strasz if (fuword32((char *)user_acl + 165192586Strasz offsetof(struct acl, acl_maxcnt)) != ACL_MAX_ENTRIES) 166192586Strasz return (EINVAL); 167192586Strasz 168192586Strasz error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl)); 169192586Strasz } 170192586Strasz 171192586Strasz return (error); 172192586Strasz} 173192586Strasz 174192586Strasz/* 175192586Strasz * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" 176200058Strasz * counterpart. It's required for old (pre-NFSv4 ACLs) libc to work 177192586Strasz * with new kernel. Fixing 'type' for old binaries with new libc 178192586Strasz * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold(). 179192586Strasz */ 180192586Straszstatic int 181192586Straszacl_type_unold(int type) 182192586Strasz{ 183192586Strasz switch (type) { 184192586Strasz case ACL_TYPE_ACCESS_OLD: 185192586Strasz return (ACL_TYPE_ACCESS); 186192586Strasz 187192586Strasz case ACL_TYPE_DEFAULT_OLD: 188192586Strasz return (ACL_TYPE_DEFAULT); 189192586Strasz 190192586Strasz default: 191192586Strasz return (type); 192192586Strasz } 193192586Strasz} 194192586Strasz 195192586Strasz/* 196165983Srwatson * These calls wrap the real vnode operations, and are called by the syscall 197165983Srwatson * code once the syscall has converted the path or file descriptor to a vnode 198165983Srwatson * (unlocked). The aclp pointer is assumed still to point to userland, so 199165983Srwatson * this should not be consumed within the kernel except by syscall code. 200165983Srwatson * Other code should directly invoke VOP_{SET,GET}ACL. 20154803Srwatson */ 20254803Srwatson 20354803Srwatson/* 20454803Srwatson * Given a vnode, set its ACL. 20554803Srwatson */ 20654803Srwatsonstatic int 20785582Srwatsonvacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 20856272Srwatson struct acl *aclp) 20954803Srwatson{ 210191249Strasz struct acl *inkernelacl; 21190202Srwatson struct mount *mp; 21254803Srwatson int error; 21354803Srwatson 214191249Strasz inkernelacl = acl_alloc(M_WAITOK); 215192586Strasz error = acl_copyin(aclp, inkernelacl, type); 216198875Strasz if (error != 0) 217191249Strasz goto out; 21890202Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 21990202Srwatson if (error != 0) 220191249Strasz goto out; 221175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 222101122Srwatson#ifdef MAC 223191249Strasz error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 224101122Srwatson if (error != 0) 225191249Strasz goto out_unlock; 226101122Srwatson#endif 227192586Strasz error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, 228192586Strasz td->td_ucred, td); 229101122Srwatson#ifdef MAC 230191249Straszout_unlock: 231101122Srwatson#endif 232175294Sattilio VOP_UNLOCK(vp, 0); 23390202Srwatson vn_finished_write(mp); 234191249Straszout: 235191249Strasz acl_free(inkernelacl); 236198875Strasz return (error); 23754803Srwatson} 23854803Srwatson 23954803Srwatson/* 24054803Srwatson * Given a vnode, get its ACL. 24154803Srwatson */ 24254803Srwatsonstatic int 24385582Srwatsonvacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type, 24454803Srwatson struct acl *aclp) 24554803Srwatson{ 246191249Strasz struct acl *inkernelacl; 24754803Srwatson int error; 24854803Srwatson 249191249Strasz inkernelacl = acl_alloc(M_WAITOK); 250175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 251101122Srwatson#ifdef MAC 252172930Srwatson error = mac_vnode_check_getacl(td->td_ucred, vp, type); 253101122Srwatson if (error != 0) 254101122Srwatson goto out; 255101122Srwatson#endif 256192586Strasz error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, 257192586Strasz td->td_ucred, td); 258192586Strasz 259101122Srwatson#ifdef MAC 260101122Srwatsonout: 261101122Srwatson#endif 262175294Sattilio VOP_UNLOCK(vp, 0); 26354803Srwatson if (error == 0) 264192586Strasz error = acl_copyout(inkernelacl, aclp, type); 265191249Strasz acl_free(inkernelacl); 26654803Srwatson return (error); 26754803Srwatson} 26854803Srwatson 26954803Srwatson/* 27054803Srwatson * Given a vnode, delete its ACL. 27154803Srwatson */ 27254803Srwatsonstatic int 27385582Srwatsonvacl_delete(struct thread *td, struct vnode *vp, acl_type_t type) 27454803Srwatson{ 27590202Srwatson struct mount *mp; 27654803Srwatson int error; 27754803Srwatson 27890202Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 279198875Strasz if (error != 0) 28090202Srwatson return (error); 281175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 282101122Srwatson#ifdef MAC 283172930Srwatson error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 284198875Strasz if (error != 0) 285101122Srwatson goto out; 286101122Srwatson#endif 287192586Strasz error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td); 288101122Srwatson#ifdef MAC 289101122Srwatsonout: 290101122Srwatson#endif 291175294Sattilio VOP_UNLOCK(vp, 0); 29290202Srwatson vn_finished_write(mp); 29354803Srwatson return (error); 29454803Srwatson} 29554803Srwatson 29654803Srwatson/* 29754803Srwatson * Given a vnode, check whether an ACL is appropriate for it 29854803Srwatson */ 29954803Srwatsonstatic int 30085582Srwatsonvacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 30154803Srwatson struct acl *aclp) 30254803Srwatson{ 303191249Strasz struct acl *inkernelacl; 30454803Srwatson int error; 30554803Srwatson 306191249Strasz inkernelacl = acl_alloc(M_WAITOK); 307192586Strasz error = acl_copyin(aclp, inkernelacl, type); 308198875Strasz if (error != 0) 309191249Strasz goto out; 310200058Strasz error = VOP_ACLCHECK(vp, acl_type_unold(type), inkernelacl, 311200058Strasz td->td_ucred, td); 312191249Straszout: 313191249Strasz acl_free(inkernelacl); 31454803Srwatson return (error); 31554803Srwatson} 31654803Srwatson 31754803Srwatson/* 318165983Srwatson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't 319165983Srwatson * need to lock, as the vacl_ code will get/release any locks required. 32054803Srwatson */ 32154803Srwatson 32254803Srwatson/* 32354803Srwatson * Given a file path, get an ACL for it 32454803Srwatson */ 32554803Srwatsonint 32685582Srwatson__acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 32754803Srwatson{ 32854803Srwatson struct nameidata nd; 329150262Scsjp int vfslocked, error; 33054803Srwatson 331150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 33254803Srwatson error = namei(&nd); 333150262Scsjp vfslocked = NDHASGIANT(&nd); 33482713Sdillon if (error == 0) { 335107855Salfred error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 33682713Sdillon NDFREE(&nd, 0); 33782713Sdillon } 338150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 33954803Srwatson return (error); 34054803Srwatson} 34154803Srwatson 34254803Srwatson/* 343108407Srwatson * Given a file path, get an ACL for it; don't follow links. 344108407Srwatson */ 345108407Srwatsonint 346108407Srwatson__acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 347108407Srwatson{ 348108407Srwatson struct nameidata nd; 349150262Scsjp int vfslocked, error; 350108407Srwatson 351150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 352108407Srwatson error = namei(&nd); 353150262Scsjp vfslocked = NDHASGIANT(&nd); 354108407Srwatson if (error == 0) { 355108407Srwatson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 356108407Srwatson NDFREE(&nd, 0); 357108407Srwatson } 358150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 359108407Srwatson return (error); 360108407Srwatson} 361108407Srwatson 362108407Srwatson/* 363167211Srwatson * Given a file path, set an ACL for it. 36454803Srwatson */ 36554803Srwatsonint 36685582Srwatson__acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 36754803Srwatson{ 36854803Srwatson struct nameidata nd; 369150262Scsjp int vfslocked, error; 37054803Srwatson 371150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 37254803Srwatson error = namei(&nd); 373150262Scsjp vfslocked = NDHASGIANT(&nd); 37482713Sdillon if (error == 0) { 375107855Salfred error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 37682713Sdillon NDFREE(&nd, 0); 37782713Sdillon } 378150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 37954803Srwatson return (error); 38054803Srwatson} 38154803Srwatson 38254803Srwatson/* 383108407Srwatson * Given a file path, set an ACL for it; don't follow links. 384108407Srwatson */ 385108407Srwatsonint 386108407Srwatson__acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 387108407Srwatson{ 388108407Srwatson struct nameidata nd; 389150262Scsjp int vfslocked, error; 390108407Srwatson 391150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 392108407Srwatson error = namei(&nd); 393150262Scsjp vfslocked = NDHASGIANT(&nd); 394108407Srwatson if (error == 0) { 395108407Srwatson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 396108407Srwatson NDFREE(&nd, 0); 397108407Srwatson } 398150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 399108407Srwatson return (error); 400108407Srwatson} 401108407Srwatson 402108407Srwatson/* 403167234Srwatson * Given a file descriptor, get an ACL for it. 40454803Srwatson */ 40554803Srwatsonint 40685582Srwatson__acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 40754803Srwatson{ 40854803Srwatson struct file *fp; 409150262Scsjp int vfslocked, error; 41054803Srwatson 411107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 41282713Sdillon if (error == 0) { 413150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 414116678Sphk error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 41589306Salfred fdrop(fp, td); 416150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 41782713Sdillon } 41882713Sdillon return (error); 41954803Srwatson} 42054803Srwatson 42154803Srwatson/* 422167234Srwatson * Given a file descriptor, set an ACL for it. 42354803Srwatson */ 42454803Srwatsonint 42585582Srwatson__acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 42654803Srwatson{ 42754803Srwatson struct file *fp; 428150262Scsjp int vfslocked, error; 42954803Srwatson 430107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 43182713Sdillon if (error == 0) { 432150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 433116678Sphk error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 43489306Salfred fdrop(fp, td); 435150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 43682713Sdillon } 43782713Sdillon return (error); 43854803Srwatson} 43954803Srwatson 44054803Srwatson/* 44154803Srwatson * Given a file path, delete an ACL from it. 44254803Srwatson */ 44354803Srwatsonint 44485582Srwatson__acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 44554803Srwatson{ 44654803Srwatson struct nameidata nd; 447150262Scsjp int vfslocked, error; 44854803Srwatson 449150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 45054803Srwatson error = namei(&nd); 451150262Scsjp vfslocked = NDHASGIANT(&nd); 45282713Sdillon if (error == 0) { 453107849Salfred error = vacl_delete(td, nd.ni_vp, uap->type); 45482713Sdillon NDFREE(&nd, 0); 45582713Sdillon } 456150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 45754803Srwatson return (error); 45854803Srwatson} 45954803Srwatson 46054803Srwatson/* 461108407Srwatson * Given a file path, delete an ACL from it; don't follow links. 462108407Srwatson */ 463108407Srwatsonint 464108407Srwatson__acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 465108407Srwatson{ 466108407Srwatson struct nameidata nd; 467150262Scsjp int vfslocked, error; 468108407Srwatson 469150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 470108407Srwatson error = namei(&nd); 471150262Scsjp vfslocked = NDHASGIANT(&nd); 472108407Srwatson if (error == 0) { 473108407Srwatson error = vacl_delete(td, nd.ni_vp, uap->type); 474108407Srwatson NDFREE(&nd, 0); 475108407Srwatson } 476150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 477108407Srwatson return (error); 478108407Srwatson} 479108407Srwatson 480108407Srwatson/* 48154803Srwatson * Given a file path, delete an ACL from it. 48254803Srwatson */ 48354803Srwatsonint 48485582Srwatson__acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 48554803Srwatson{ 48654803Srwatson struct file *fp; 487150262Scsjp int vfslocked, error; 48854803Srwatson 489107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 49082713Sdillon if (error == 0) { 491150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 492116678Sphk error = vacl_delete(td, fp->f_vnode, uap->type); 49389306Salfred fdrop(fp, td); 494150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 49582713Sdillon } 49654803Srwatson return (error); 49754803Srwatson} 49854803Srwatson 49954803Srwatson/* 500167211Srwatson * Given a file path, check an ACL for it. 50154803Srwatson */ 50254803Srwatsonint 50385582Srwatson__acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 50454803Srwatson{ 505198875Strasz struct nameidata nd; 506150262Scsjp int vfslocked, error; 50754803Srwatson 508150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 50954803Srwatson error = namei(&nd); 510150262Scsjp vfslocked = NDHASGIANT(&nd); 51182713Sdillon if (error == 0) { 512107855Salfred error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 51382713Sdillon NDFREE(&nd, 0); 51482713Sdillon } 515150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 51654803Srwatson return (error); 51754803Srwatson} 51854803Srwatson 51954803Srwatson/* 520108407Srwatson * Given a file path, check an ACL for it; don't follow links. 521108407Srwatson */ 522108407Srwatsonint 523108407Srwatson__acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 524108407Srwatson{ 525198877Strasz struct nameidata nd; 526150262Scsjp int vfslocked, error; 527108407Srwatson 528150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 529108407Srwatson error = namei(&nd); 530150262Scsjp vfslocked = NDHASGIANT(&nd); 531108407Srwatson if (error == 0) { 532108407Srwatson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 533108407Srwatson NDFREE(&nd, 0); 534108407Srwatson } 535150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 536108407Srwatson return (error); 537108407Srwatson} 538108407Srwatson 539108407Srwatson/* 540167211Srwatson * Given a file descriptor, check an ACL for it. 54154803Srwatson */ 54254803Srwatsonint 54385582Srwatson__acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 54454803Srwatson{ 54554803Srwatson struct file *fp; 546150262Scsjp int vfslocked, error; 54754803Srwatson 548107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 54982713Sdillon if (error == 0) { 550150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 551116678Sphk error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 55289306Salfred fdrop(fp, td); 553150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 55482713Sdillon } 55582713Sdillon return (error); 55654803Srwatson} 557149811Scsjp 558191249Straszstruct acl * 559191249Straszacl_alloc(int flags) 560191249Strasz{ 561191249Strasz struct acl *aclp; 562191249Strasz 563191266Strasz aclp = malloc(sizeof(*aclp), M_ACL, flags); 564192586Strasz aclp->acl_maxcnt = ACL_MAX_ENTRIES; 565191249Strasz 566191249Strasz return (aclp); 567191249Strasz} 568191249Strasz 569191249Straszvoid 570191249Straszacl_free(struct acl *aclp) 571191249Strasz{ 572191249Strasz 573191266Strasz free(aclp, M_ACL); 574191249Strasz} 575