vfs_acl.c revision 198877
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 198877 2009-11-04 08:25:58Z 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 95192586Strasz if (source->acl_cnt < 0 || 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" 176192586Strasz * counterpart. It's required for old (pre-NFS4 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; 310191249Strasz error = VOP_ACLCHECK(vp, type, inkernelacl, td->td_ucred, td); 311191249Straszout: 312191249Strasz acl_free(inkernelacl); 31354803Srwatson return (error); 31454803Srwatson} 31554803Srwatson 31654803Srwatson/* 317165983Srwatson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't 318165983Srwatson * need to lock, as the vacl_ code will get/release any locks required. 31954803Srwatson */ 32054803Srwatson 32154803Srwatson/* 32254803Srwatson * Given a file path, get an ACL for it 32354803Srwatson */ 32454803Srwatsonint 32585582Srwatson__acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 32654803Srwatson{ 32754803Srwatson struct nameidata nd; 328150262Scsjp int vfslocked, error; 32954803Srwatson 330150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 33154803Srwatson error = namei(&nd); 332150262Scsjp vfslocked = NDHASGIANT(&nd); 33382713Sdillon if (error == 0) { 334107855Salfred error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 33582713Sdillon NDFREE(&nd, 0); 33682713Sdillon } 337150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 33854803Srwatson return (error); 33954803Srwatson} 34054803Srwatson 34154803Srwatson/* 342108407Srwatson * Given a file path, get an ACL for it; don't follow links. 343108407Srwatson */ 344108407Srwatsonint 345108407Srwatson__acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 346108407Srwatson{ 347108407Srwatson struct nameidata nd; 348150262Scsjp int vfslocked, error; 349108407Srwatson 350150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 351108407Srwatson error = namei(&nd); 352150262Scsjp vfslocked = NDHASGIANT(&nd); 353108407Srwatson if (error == 0) { 354108407Srwatson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 355108407Srwatson NDFREE(&nd, 0); 356108407Srwatson } 357150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 358108407Srwatson return (error); 359108407Srwatson} 360108407Srwatson 361108407Srwatson/* 362167211Srwatson * Given a file path, set an ACL for it. 36354803Srwatson */ 36454803Srwatsonint 36585582Srwatson__acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 36654803Srwatson{ 36754803Srwatson struct nameidata nd; 368150262Scsjp int vfslocked, error; 36954803Srwatson 370150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 37154803Srwatson error = namei(&nd); 372150262Scsjp vfslocked = NDHASGIANT(&nd); 37382713Sdillon if (error == 0) { 374107855Salfred error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 37582713Sdillon NDFREE(&nd, 0); 37682713Sdillon } 377150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 37854803Srwatson return (error); 37954803Srwatson} 38054803Srwatson 38154803Srwatson/* 382108407Srwatson * Given a file path, set an ACL for it; don't follow links. 383108407Srwatson */ 384108407Srwatsonint 385108407Srwatson__acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 386108407Srwatson{ 387108407Srwatson struct nameidata nd; 388150262Scsjp int vfslocked, error; 389108407Srwatson 390150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 391108407Srwatson error = namei(&nd); 392150262Scsjp vfslocked = NDHASGIANT(&nd); 393108407Srwatson if (error == 0) { 394108407Srwatson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 395108407Srwatson NDFREE(&nd, 0); 396108407Srwatson } 397150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 398108407Srwatson return (error); 399108407Srwatson} 400108407Srwatson 401108407Srwatson/* 402167234Srwatson * Given a file descriptor, get an ACL for it. 40354803Srwatson */ 40454803Srwatsonint 40585582Srwatson__acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 40654803Srwatson{ 40754803Srwatson struct file *fp; 408150262Scsjp int vfslocked, error; 40954803Srwatson 410107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 41182713Sdillon if (error == 0) { 412150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 413116678Sphk error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 41489306Salfred fdrop(fp, td); 415150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 41682713Sdillon } 41782713Sdillon return (error); 41854803Srwatson} 41954803Srwatson 42054803Srwatson/* 421167234Srwatson * Given a file descriptor, set an ACL for it. 42254803Srwatson */ 42354803Srwatsonint 42485582Srwatson__acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 42554803Srwatson{ 42654803Srwatson struct file *fp; 427150262Scsjp int vfslocked, error; 42854803Srwatson 429107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 43082713Sdillon if (error == 0) { 431150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 432116678Sphk error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 43389306Salfred fdrop(fp, td); 434150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 43582713Sdillon } 43682713Sdillon return (error); 43754803Srwatson} 43854803Srwatson 43954803Srwatson/* 44054803Srwatson * Given a file path, delete an ACL from it. 44154803Srwatson */ 44254803Srwatsonint 44385582Srwatson__acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 44454803Srwatson{ 44554803Srwatson struct nameidata nd; 446150262Scsjp int vfslocked, error; 44754803Srwatson 448150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 44954803Srwatson error = namei(&nd); 450150262Scsjp vfslocked = NDHASGIANT(&nd); 45182713Sdillon if (error == 0) { 452107849Salfred error = vacl_delete(td, nd.ni_vp, uap->type); 45382713Sdillon NDFREE(&nd, 0); 45482713Sdillon } 455150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 45654803Srwatson return (error); 45754803Srwatson} 45854803Srwatson 45954803Srwatson/* 460108407Srwatson * Given a file path, delete an ACL from it; don't follow links. 461108407Srwatson */ 462108407Srwatsonint 463108407Srwatson__acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 464108407Srwatson{ 465108407Srwatson struct nameidata nd; 466150262Scsjp int vfslocked, error; 467108407Srwatson 468150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 469108407Srwatson error = namei(&nd); 470150262Scsjp vfslocked = NDHASGIANT(&nd); 471108407Srwatson if (error == 0) { 472108407Srwatson error = vacl_delete(td, nd.ni_vp, uap->type); 473108407Srwatson NDFREE(&nd, 0); 474108407Srwatson } 475150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 476108407Srwatson return (error); 477108407Srwatson} 478108407Srwatson 479108407Srwatson/* 48054803Srwatson * Given a file path, delete an ACL from it. 48154803Srwatson */ 48254803Srwatsonint 48385582Srwatson__acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 48454803Srwatson{ 48554803Srwatson struct file *fp; 486150262Scsjp int vfslocked, error; 48754803Srwatson 488107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 48982713Sdillon if (error == 0) { 490150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 491116678Sphk error = vacl_delete(td, fp->f_vnode, uap->type); 49289306Salfred fdrop(fp, td); 493150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 49482713Sdillon } 49554803Srwatson return (error); 49654803Srwatson} 49754803Srwatson 49854803Srwatson/* 499167211Srwatson * Given a file path, check an ACL for it. 50054803Srwatson */ 50154803Srwatsonint 50285582Srwatson__acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 50354803Srwatson{ 504198875Strasz struct nameidata nd; 505150262Scsjp int vfslocked, error; 50654803Srwatson 507150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 50854803Srwatson error = namei(&nd); 509150262Scsjp vfslocked = NDHASGIANT(&nd); 51082713Sdillon if (error == 0) { 511107855Salfred error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 51282713Sdillon NDFREE(&nd, 0); 51382713Sdillon } 514150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 51554803Srwatson return (error); 51654803Srwatson} 51754803Srwatson 51854803Srwatson/* 519108407Srwatson * Given a file path, check an ACL for it; don't follow links. 520108407Srwatson */ 521108407Srwatsonint 522108407Srwatson__acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 523108407Srwatson{ 524198877Strasz struct nameidata nd; 525150262Scsjp int vfslocked, error; 526108407Srwatson 527150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 528108407Srwatson error = namei(&nd); 529150262Scsjp vfslocked = NDHASGIANT(&nd); 530108407Srwatson if (error == 0) { 531108407Srwatson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 532108407Srwatson NDFREE(&nd, 0); 533108407Srwatson } 534150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 535108407Srwatson return (error); 536108407Srwatson} 537108407Srwatson 538108407Srwatson/* 539167211Srwatson * Given a file descriptor, check an ACL for it. 54054803Srwatson */ 54154803Srwatsonint 54285582Srwatson__acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 54354803Srwatson{ 54454803Srwatson struct file *fp; 545150262Scsjp int vfslocked, error; 54654803Srwatson 547107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 54882713Sdillon if (error == 0) { 549150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 550116678Sphk error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 55189306Salfred fdrop(fp, td); 552150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 55382713Sdillon } 55482713Sdillon return (error); 55554803Srwatson} 556149811Scsjp 557191249Straszstruct acl * 558191249Straszacl_alloc(int flags) 559191249Strasz{ 560191249Strasz struct acl *aclp; 561191249Strasz 562191266Strasz aclp = malloc(sizeof(*aclp), M_ACL, flags); 563192586Strasz aclp->acl_maxcnt = ACL_MAX_ENTRIES; 564191249Strasz 565191249Strasz return (aclp); 566191249Strasz} 567191249Strasz 568191249Straszvoid 569191249Straszacl_free(struct acl *aclp) 570191249Strasz{ 571191249Strasz 572191266Strasz free(aclp, M_ACL); 573191249Strasz} 574