vfs_acl.c revision 192586
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 192586 2009-05-22 15:56:43Z trasz $"); 37116182Sobrien 38101122Srwatson#include "opt_mac.h" 39101122Srwatson 4054803Srwatson#include <sys/param.h> 4154803Srwatson#include <sys/systm.h> 4254803Srwatson#include <sys/sysproto.h> 43177785Skib#include <sys/fcntl.h> 4454803Srwatson#include <sys/kernel.h> 4554803Srwatson#include <sys/malloc.h> 46150262Scsjp#include <sys/mount.h> 4754803Srwatson#include <sys/vnode.h> 4854803Srwatson#include <sys/lock.h> 4982713Sdillon#include <sys/mutex.h> 5054803Srwatson#include <sys/namei.h> 5154803Srwatson#include <sys/file.h> 52108524Salfred#include <sys/filedesc.h> 5354803Srwatson#include <sys/proc.h> 5454803Srwatson#include <sys/sysent.h> 5554803Srwatson#include <sys/acl.h> 5654803Srwatson 57163606Srwatson#include <security/mac/mac_framework.h> 58163606Srwatson 59192586StraszCTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES); 6054803Srwatson 61192586StraszMALLOC_DEFINE(M_ACL, "acl", "Access Control Lists"); 62192586Strasz 6398927Srwatsonstatic int vacl_set_acl(struct thread *td, struct vnode *vp, 6498927Srwatson acl_type_t type, struct acl *aclp); 6598927Srwatsonstatic int vacl_get_acl(struct thread *td, struct vnode *vp, 6698927Srwatson acl_type_t type, struct acl *aclp); 6785582Srwatsonstatic int vacl_aclcheck(struct thread *td, struct vnode *vp, 6898927Srwatson acl_type_t type, struct acl *aclp); 6954803Srwatson 70192586Straszint 71192586Straszacl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest) 72192586Strasz{ 73192586Strasz int i; 74192586Strasz 75192586Strasz if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES) 76192586Strasz return (EINVAL); 77192586Strasz 78192586Strasz bzero(dest, sizeof(*dest)); 79192586Strasz 80192586Strasz dest->acl_cnt = source->acl_cnt; 81192586Strasz dest->acl_maxcnt = ACL_MAX_ENTRIES; 82192586Strasz 83192586Strasz for (i = 0; i < dest->acl_cnt; i++) { 84192586Strasz dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 85192586Strasz dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 86192586Strasz dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 87192586Strasz } 88192586Strasz 89192586Strasz return (0); 90192586Strasz} 91192586Strasz 92192586Straszint 93192586Straszacl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest) 94192586Strasz{ 95192586Strasz int i; 96192586Strasz 97192586Strasz if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES) 98192586Strasz return (EINVAL); 99192586Strasz 100192586Strasz bzero(dest, sizeof(*dest)); 101192586Strasz 102192586Strasz dest->acl_cnt = source->acl_cnt; 103192586Strasz 104192586Strasz for (i = 0; i < dest->acl_cnt; i++) { 105192586Strasz dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 106192586Strasz dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 107192586Strasz dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 108192586Strasz } 109192586Strasz 110192586Strasz return (0); 111192586Strasz} 112192586Strasz 11354803Srwatson/* 114192586Strasz * At one time, "struct ACL" was extended in order to add support for NFSv4 115192586Strasz * ACLs. Instead of creating compatibility versions of all the ACL-related 116192586Strasz * syscalls, they were left intact. It's possible to find out what the code 117192586Strasz * calling these syscalls (libc) expects basing on "type" argument - if it's 118192586Strasz * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were 119192586Strasz * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct 120192586Strasz * oldacl". If it's something else, then it's the new "struct acl". In the 121192586Strasz * latter case, the routines below just copyin/copyout the contents. In the 122192586Strasz * former case, they copyin the "struct oldacl" and convert it to the new 123192586Strasz * format. 124192586Strasz */ 125192586Straszstatic int 126192586Straszacl_copyin(void *user_acl, struct acl *kernel_acl, acl_type_t type) 127192586Strasz{ 128192586Strasz int error; 129192586Strasz struct oldacl old; 130192586Strasz 131192586Strasz switch (type) { 132192586Strasz case ACL_TYPE_ACCESS_OLD: 133192586Strasz case ACL_TYPE_DEFAULT_OLD: 134192586Strasz error = copyin(user_acl, &old, sizeof(old)); 135192586Strasz if (error != 0) 136192586Strasz break; 137192586Strasz acl_copy_oldacl_into_acl(&old, kernel_acl); 138192586Strasz break; 139192586Strasz 140192586Strasz default: 141192586Strasz error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl)); 142192586Strasz if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES) 143192586Strasz return (EINVAL); 144192586Strasz } 145192586Strasz 146192586Strasz return (error); 147192586Strasz} 148192586Strasz 149192586Straszstatic int 150192586Straszacl_copyout(struct acl *kernel_acl, void *user_acl, acl_type_t type) 151192586Strasz{ 152192586Strasz int error; 153192586Strasz struct oldacl old; 154192586Strasz 155192586Strasz switch (type) { 156192586Strasz case ACL_TYPE_ACCESS_OLD: 157192586Strasz case ACL_TYPE_DEFAULT_OLD: 158192586Strasz error = acl_copy_acl_into_oldacl(kernel_acl, &old); 159192586Strasz if (error != 0) 160192586Strasz break; 161192586Strasz 162192586Strasz error = copyout(&old, user_acl, sizeof(old)); 163192586Strasz break; 164192586Strasz 165192586Strasz default: 166192586Strasz if (fuword((char *)user_acl + 167192586Strasz offsetof(struct acl, acl_maxcnt)) != ACL_MAX_ENTRIES) 168192586Strasz return (EINVAL); 169192586Strasz 170192586Strasz error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl)); 171192586Strasz } 172192586Strasz 173192586Strasz return (error); 174192586Strasz} 175192586Strasz 176192586Strasz/* 177192586Strasz * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" 178192586Strasz * counterpart. It's required for old (pre-NFS4 ACLs) libc to work 179192586Strasz * with new kernel. Fixing 'type' for old binaries with new libc 180192586Strasz * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold(). 181192586Strasz */ 182192586Straszstatic int 183192586Straszacl_type_unold(int type) 184192586Strasz{ 185192586Strasz switch (type) { 186192586Strasz case ACL_TYPE_ACCESS_OLD: 187192586Strasz return (ACL_TYPE_ACCESS); 188192586Strasz 189192586Strasz case ACL_TYPE_DEFAULT_OLD: 190192586Strasz return (ACL_TYPE_DEFAULT); 191192586Strasz 192192586Strasz default: 193192586Strasz return (type); 194192586Strasz } 195192586Strasz} 196192586Strasz 197192586Strasz/* 198165983Srwatson * These calls wrap the real vnode operations, and are called by the syscall 199165983Srwatson * code once the syscall has converted the path or file descriptor to a vnode 200165983Srwatson * (unlocked). The aclp pointer is assumed still to point to userland, so 201165983Srwatson * this should not be consumed within the kernel except by syscall code. 202165983Srwatson * Other code should directly invoke VOP_{SET,GET}ACL. 20354803Srwatson */ 20454803Srwatson 20554803Srwatson/* 20654803Srwatson * Given a vnode, set its ACL. 20754803Srwatson */ 20854803Srwatsonstatic int 20985582Srwatsonvacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 21056272Srwatson struct acl *aclp) 21154803Srwatson{ 212191249Strasz struct acl *inkernelacl; 21390202Srwatson struct mount *mp; 21454803Srwatson int error; 21554803Srwatson 216191249Strasz inkernelacl = acl_alloc(M_WAITOK); 217192586Strasz error = acl_copyin(aclp, inkernelacl, type); 21854803Srwatson if (error) 219191249Strasz goto out; 22090202Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 22190202Srwatson if (error != 0) 222191249Strasz goto out; 223175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 224101122Srwatson#ifdef MAC 225191249Strasz error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 226101122Srwatson if (error != 0) 227191249Strasz goto out_unlock; 228101122Srwatson#endif 229192586Strasz error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, 230192586Strasz td->td_ucred, td); 231101122Srwatson#ifdef MAC 232191249Straszout_unlock: 233101122Srwatson#endif 234175294Sattilio VOP_UNLOCK(vp, 0); 23590202Srwatson vn_finished_write(mp); 236191249Straszout: 237191249Strasz acl_free(inkernelacl); 23871699Sjhb return(error); 23954803Srwatson} 24054803Srwatson 24154803Srwatson/* 24254803Srwatson * Given a vnode, get its ACL. 24354803Srwatson */ 24454803Srwatsonstatic int 24585582Srwatsonvacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type, 24654803Srwatson struct acl *aclp) 24754803Srwatson{ 248191249Strasz struct acl *inkernelacl; 24954803Srwatson int error; 25054803Srwatson 251191249Strasz inkernelacl = acl_alloc(M_WAITOK); 252175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 253101122Srwatson#ifdef MAC 254172930Srwatson error = mac_vnode_check_getacl(td->td_ucred, vp, type); 255101122Srwatson if (error != 0) 256101122Srwatson goto out; 257101122Srwatson#endif 258192586Strasz error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, 259192586Strasz td->td_ucred, td); 260192586Strasz 261101122Srwatson#ifdef MAC 262101122Srwatsonout: 263101122Srwatson#endif 264175294Sattilio VOP_UNLOCK(vp, 0); 26554803Srwatson if (error == 0) 266192586Strasz error = acl_copyout(inkernelacl, aclp, type); 267191249Strasz acl_free(inkernelacl); 26854803Srwatson return (error); 26954803Srwatson} 27054803Srwatson 27154803Srwatson/* 27254803Srwatson * Given a vnode, delete its ACL. 27354803Srwatson */ 27454803Srwatsonstatic int 27585582Srwatsonvacl_delete(struct thread *td, struct vnode *vp, acl_type_t type) 27654803Srwatson{ 27790202Srwatson struct mount *mp; 27854803Srwatson int error; 27954803Srwatson 28090202Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 28190202Srwatson if (error) 28290202Srwatson return (error); 283175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 284101122Srwatson#ifdef MAC 285172930Srwatson error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 286101122Srwatson if (error) 287101122Srwatson goto out; 288101122Srwatson#endif 289192586Strasz error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td); 290101122Srwatson#ifdef MAC 291101122Srwatsonout: 292101122Srwatson#endif 293175294Sattilio VOP_UNLOCK(vp, 0); 29490202Srwatson vn_finished_write(mp); 29554803Srwatson return (error); 29654803Srwatson} 29754803Srwatson 29854803Srwatson/* 29954803Srwatson * Given a vnode, check whether an ACL is appropriate for it 30054803Srwatson */ 30154803Srwatsonstatic int 30285582Srwatsonvacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 30354803Srwatson struct acl *aclp) 30454803Srwatson{ 305191249Strasz struct acl *inkernelacl; 30654803Srwatson int error; 30754803Srwatson 308191249Strasz inkernelacl = acl_alloc(M_WAITOK); 309192586Strasz error = acl_copyin(aclp, inkernelacl, type); 31054803Srwatson if (error) 311191249Strasz goto out; 312191249Strasz error = VOP_ACLCHECK(vp, type, inkernelacl, td->td_ucred, td); 313191249Straszout: 314191249Strasz acl_free(inkernelacl); 31554803Srwatson return (error); 31654803Srwatson} 31754803Srwatson 31854803Srwatson/* 319165983Srwatson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't 320165983Srwatson * need to lock, as the vacl_ code will get/release any locks required. 32154803Srwatson */ 32254803Srwatson 32354803Srwatson/* 32454803Srwatson * Given a file path, get an ACL for it 32554803Srwatson */ 32654803Srwatsonint 32785582Srwatson__acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 32854803Srwatson{ 32954803Srwatson struct nameidata nd; 330150262Scsjp int vfslocked, error; 33154803Srwatson 332150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 33354803Srwatson error = namei(&nd); 334150262Scsjp vfslocked = NDHASGIANT(&nd); 33582713Sdillon if (error == 0) { 336107855Salfred error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 33782713Sdillon NDFREE(&nd, 0); 33882713Sdillon } 339150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 34054803Srwatson return (error); 34154803Srwatson} 34254803Srwatson 34354803Srwatson/* 344108407Srwatson * Given a file path, get an ACL for it; don't follow links. 345108407Srwatson */ 346108407Srwatsonint 347108407Srwatson__acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 348108407Srwatson{ 349108407Srwatson struct nameidata nd; 350150262Scsjp int vfslocked, error; 351108407Srwatson 352150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 353108407Srwatson error = namei(&nd); 354150262Scsjp vfslocked = NDHASGIANT(&nd); 355108407Srwatson if (error == 0) { 356108407Srwatson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 357108407Srwatson NDFREE(&nd, 0); 358108407Srwatson } 359150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 360108407Srwatson return (error); 361108407Srwatson} 362108407Srwatson 363108407Srwatson/* 364167211Srwatson * Given a file path, set an ACL for it. 36554803Srwatson */ 36654803Srwatsonint 36785582Srwatson__acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 36854803Srwatson{ 36954803Srwatson struct nameidata nd; 370150262Scsjp int vfslocked, error; 37154803Srwatson 372150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 37354803Srwatson error = namei(&nd); 374150262Scsjp vfslocked = NDHASGIANT(&nd); 37582713Sdillon if (error == 0) { 376107855Salfred error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 37782713Sdillon NDFREE(&nd, 0); 37882713Sdillon } 379150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 38054803Srwatson return (error); 38154803Srwatson} 38254803Srwatson 38354803Srwatson/* 384108407Srwatson * Given a file path, set an ACL for it; don't follow links. 385108407Srwatson */ 386108407Srwatsonint 387108407Srwatson__acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 388108407Srwatson{ 389108407Srwatson struct nameidata nd; 390150262Scsjp int vfslocked, error; 391108407Srwatson 392150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 393108407Srwatson error = namei(&nd); 394150262Scsjp vfslocked = NDHASGIANT(&nd); 395108407Srwatson if (error == 0) { 396108407Srwatson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 397108407Srwatson NDFREE(&nd, 0); 398108407Srwatson } 399150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 400108407Srwatson return (error); 401108407Srwatson} 402108407Srwatson 403108407Srwatson/* 404167234Srwatson * Given a file descriptor, get an ACL for it. 40554803Srwatson */ 40654803Srwatsonint 40785582Srwatson__acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 40854803Srwatson{ 40954803Srwatson struct file *fp; 410150262Scsjp int vfslocked, error; 41154803Srwatson 412107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 41382713Sdillon if (error == 0) { 414150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 415116678Sphk error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 41689306Salfred fdrop(fp, td); 417150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 41882713Sdillon } 41982713Sdillon return (error); 42054803Srwatson} 42154803Srwatson 42254803Srwatson/* 423167234Srwatson * Given a file descriptor, set an ACL for it. 42454803Srwatson */ 42554803Srwatsonint 42685582Srwatson__acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 42754803Srwatson{ 42854803Srwatson struct file *fp; 429150262Scsjp int vfslocked, error; 43054803Srwatson 431107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 43282713Sdillon if (error == 0) { 433150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 434116678Sphk error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 43589306Salfred fdrop(fp, td); 436150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 43782713Sdillon } 43882713Sdillon return (error); 43954803Srwatson} 44054803Srwatson 44154803Srwatson/* 44254803Srwatson * Given a file path, delete an ACL from it. 44354803Srwatson */ 44454803Srwatsonint 44585582Srwatson__acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 44654803Srwatson{ 44754803Srwatson struct nameidata nd; 448150262Scsjp int vfslocked, error; 44954803Srwatson 450150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 45154803Srwatson error = namei(&nd); 452150262Scsjp vfslocked = NDHASGIANT(&nd); 45382713Sdillon if (error == 0) { 454107849Salfred error = vacl_delete(td, nd.ni_vp, uap->type); 45582713Sdillon NDFREE(&nd, 0); 45682713Sdillon } 457150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 45854803Srwatson return (error); 45954803Srwatson} 46054803Srwatson 46154803Srwatson/* 462108407Srwatson * Given a file path, delete an ACL from it; don't follow links. 463108407Srwatson */ 464108407Srwatsonint 465108407Srwatson__acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 466108407Srwatson{ 467108407Srwatson struct nameidata nd; 468150262Scsjp int vfslocked, error; 469108407Srwatson 470150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 471108407Srwatson error = namei(&nd); 472150262Scsjp vfslocked = NDHASGIANT(&nd); 473108407Srwatson if (error == 0) { 474108407Srwatson error = vacl_delete(td, nd.ni_vp, uap->type); 475108407Srwatson NDFREE(&nd, 0); 476108407Srwatson } 477150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 478108407Srwatson return (error); 479108407Srwatson} 480108407Srwatson 481108407Srwatson/* 48254803Srwatson * Given a file path, delete an ACL from it. 48354803Srwatson */ 48454803Srwatsonint 48585582Srwatson__acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 48654803Srwatson{ 48754803Srwatson struct file *fp; 488150262Scsjp int vfslocked, error; 48954803Srwatson 490107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 49182713Sdillon if (error == 0) { 492150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 493116678Sphk error = vacl_delete(td, fp->f_vnode, uap->type); 49489306Salfred fdrop(fp, td); 495150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 49682713Sdillon } 49754803Srwatson return (error); 49854803Srwatson} 49954803Srwatson 50054803Srwatson/* 501167211Srwatson * Given a file path, check an ACL for it. 50254803Srwatson */ 50354803Srwatsonint 50485582Srwatson__acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 50554803Srwatson{ 50654803Srwatson struct nameidata nd; 507150262Scsjp int vfslocked, error; 50854803Srwatson 509150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); 51054803Srwatson error = namei(&nd); 511150262Scsjp vfslocked = NDHASGIANT(&nd); 51282713Sdillon if (error == 0) { 513107855Salfred error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 51482713Sdillon NDFREE(&nd, 0); 51582713Sdillon } 516150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 51754803Srwatson return (error); 51854803Srwatson} 51954803Srwatson 52054803Srwatson/* 521108407Srwatson * Given a file path, check an ACL for it; don't follow links. 522108407Srwatson */ 523108407Srwatsonint 524108407Srwatson__acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 525108407Srwatson{ 526108407Srwatson struct nameidata nd; 527150262Scsjp int vfslocked, error; 528108407Srwatson 529150262Scsjp NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td); 530108407Srwatson error = namei(&nd); 531150262Scsjp vfslocked = NDHASGIANT(&nd); 532108407Srwatson if (error == 0) { 533108407Srwatson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 534108407Srwatson NDFREE(&nd, 0); 535108407Srwatson } 536150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 537108407Srwatson return (error); 538108407Srwatson} 539108407Srwatson 540108407Srwatson/* 541167211Srwatson * Given a file descriptor, check an ACL for it. 54254803Srwatson */ 54354803Srwatsonint 54485582Srwatson__acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 54554803Srwatson{ 54654803Srwatson struct file *fp; 547150262Scsjp int vfslocked, error; 54854803Srwatson 549107849Salfred error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); 55082713Sdillon if (error == 0) { 551150262Scsjp vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 552116678Sphk error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 55389306Salfred fdrop(fp, td); 554150262Scsjp VFS_UNLOCK_GIANT(vfslocked); 55582713Sdillon } 55682713Sdillon return (error); 55754803Srwatson} 558149811Scsjp 559191249Straszstruct acl * 560191249Straszacl_alloc(int flags) 561191249Strasz{ 562191249Strasz struct acl *aclp; 563191249Strasz 564191266Strasz aclp = malloc(sizeof(*aclp), M_ACL, flags); 565192586Strasz aclp->acl_maxcnt = ACL_MAX_ENTRIES; 566191249Strasz 567191249Strasz return (aclp); 568191249Strasz} 569191249Strasz 570191249Straszvoid 571191249Straszacl_free(struct acl *aclp) 572191249Strasz{ 573191249Strasz 574191266Strasz free(aclp, M_ACL); 575191249Strasz} 576