vfs_acl.c revision 246412
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 246412 2013-02-06 15:18:46Z pluknet $"); 37116182Sobrien 3854803Srwatson#include <sys/param.h> 3954803Srwatson#include <sys/systm.h> 4054803Srwatson#include <sys/sysproto.h> 41224778Srwatson#include <sys/capability.h> 42177785Skib#include <sys/fcntl.h> 4354803Srwatson#include <sys/kernel.h> 4454803Srwatson#include <sys/malloc.h> 45150262Scsjp#include <sys/mount.h> 4654803Srwatson#include <sys/vnode.h> 4754803Srwatson#include <sys/lock.h> 4882713Sdillon#include <sys/mutex.h> 4954803Srwatson#include <sys/namei.h> 5054803Srwatson#include <sys/file.h> 51108524Salfred#include <sys/filedesc.h> 5254803Srwatson#include <sys/proc.h> 5354803Srwatson#include <sys/sysent.h> 5454803Srwatson#include <sys/acl.h> 5554803Srwatson 56163606Srwatson#include <security/mac/mac_framework.h> 57163606Srwatson 58192586StraszCTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES); 5954803Srwatson 60192586StraszMALLOC_DEFINE(M_ACL, "acl", "Access Control Lists"); 61192586Strasz 6298927Srwatsonstatic int vacl_set_acl(struct thread *td, struct vnode *vp, 6398927Srwatson acl_type_t type, struct acl *aclp); 6498927Srwatsonstatic int vacl_get_acl(struct thread *td, struct vnode *vp, 6598927Srwatson acl_type_t type, struct acl *aclp); 6685582Srwatsonstatic int vacl_aclcheck(struct thread *td, struct vnode *vp, 6798927Srwatson acl_type_t type, struct acl *aclp); 6854803Srwatson 69192586Straszint 70192586Straszacl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest) 71192586Strasz{ 72192586Strasz int i; 73192586Strasz 74192586Strasz if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES) 75192586Strasz return (EINVAL); 76192586Strasz 77192586Strasz bzero(dest, sizeof(*dest)); 78192586Strasz 79192586Strasz dest->acl_cnt = source->acl_cnt; 80192586Strasz dest->acl_maxcnt = ACL_MAX_ENTRIES; 81192586Strasz 82192586Strasz for (i = 0; i < dest->acl_cnt; i++) { 83192586Strasz dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 84192586Strasz dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 85192586Strasz dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 86192586Strasz } 87192586Strasz 88192586Strasz return (0); 89192586Strasz} 90192586Strasz 91192586Straszint 92192586Straszacl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest) 93192586Strasz{ 94192586Strasz int i; 95192586Strasz 96208781Strasz if (source->acl_cnt > OLDACL_MAX_ENTRIES) 97192586Strasz return (EINVAL); 98192586Strasz 99192586Strasz bzero(dest, sizeof(*dest)); 100192586Strasz 101192586Strasz dest->acl_cnt = source->acl_cnt; 102192586Strasz 103192586Strasz for (i = 0; i < dest->acl_cnt; i++) { 104192586Strasz dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 105192586Strasz dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 106192586Strasz dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 107192586Strasz } 108192586Strasz 109192586Strasz return (0); 110192586Strasz} 111192586Strasz 11254803Srwatson/* 113192586Strasz * At one time, "struct ACL" was extended in order to add support for NFSv4 114192586Strasz * ACLs. Instead of creating compatibility versions of all the ACL-related 115192586Strasz * syscalls, they were left intact. It's possible to find out what the code 116192586Strasz * calling these syscalls (libc) expects basing on "type" argument - if it's 117192586Strasz * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were 118192586Strasz * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct 119192586Strasz * oldacl". If it's something else, then it's the new "struct acl". In the 120192586Strasz * latter case, the routines below just copyin/copyout the contents. In the 121192586Strasz * former case, they copyin the "struct oldacl" and convert it to the new 122192586Strasz * format. 123192586Strasz */ 124192586Straszstatic int 125192586Straszacl_copyin(void *user_acl, struct acl *kernel_acl, acl_type_t type) 126192586Strasz{ 127192586Strasz int error; 128192586Strasz struct oldacl old; 129192586Strasz 130192586Strasz switch (type) { 131192586Strasz case ACL_TYPE_ACCESS_OLD: 132192586Strasz case ACL_TYPE_DEFAULT_OLD: 133192586Strasz error = copyin(user_acl, &old, sizeof(old)); 134192586Strasz if (error != 0) 135192586Strasz break; 136192586Strasz acl_copy_oldacl_into_acl(&old, kernel_acl); 137192586Strasz break; 138192586Strasz 139192586Strasz default: 140192586Strasz error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl)); 141192586Strasz if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES) 142192586Strasz return (EINVAL); 143192586Strasz } 144192586Strasz 145192586Strasz return (error); 146192586Strasz} 147192586Strasz 148192586Straszstatic int 149192586Straszacl_copyout(struct acl *kernel_acl, void *user_acl, acl_type_t type) 150192586Strasz{ 151192586Strasz int error; 152192586Strasz struct oldacl old; 153192586Strasz 154192586Strasz switch (type) { 155192586Strasz case ACL_TYPE_ACCESS_OLD: 156192586Strasz case ACL_TYPE_DEFAULT_OLD: 157192586Strasz error = acl_copy_acl_into_oldacl(kernel_acl, &old); 158192586Strasz if (error != 0) 159192586Strasz break; 160192586Strasz 161192586Strasz error = copyout(&old, user_acl, sizeof(old)); 162192586Strasz break; 163192586Strasz 164192586Strasz default: 165197789Strasz if (fuword32((char *)user_acl + 166192586Strasz offsetof(struct acl, acl_maxcnt)) != ACL_MAX_ENTRIES) 167192586Strasz return (EINVAL); 168192586Strasz 169192586Strasz error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl)); 170192586Strasz } 171192586Strasz 172192586Strasz return (error); 173192586Strasz} 174192586Strasz 175192586Strasz/* 176192586Strasz * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" 177200058Strasz * counterpart. It's required for old (pre-NFSv4 ACLs) libc to work 178192586Strasz * with new kernel. Fixing 'type' for old binaries with new libc 179192586Strasz * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold(). 180192586Strasz */ 181192586Straszstatic int 182192586Straszacl_type_unold(int type) 183192586Strasz{ 184192586Strasz switch (type) { 185192586Strasz case ACL_TYPE_ACCESS_OLD: 186192586Strasz return (ACL_TYPE_ACCESS); 187192586Strasz 188192586Strasz case ACL_TYPE_DEFAULT_OLD: 189192586Strasz return (ACL_TYPE_DEFAULT); 190192586Strasz 191192586Strasz default: 192192586Strasz return (type); 193192586Strasz } 194192586Strasz} 195192586Strasz 196192586Strasz/* 197165983Srwatson * These calls wrap the real vnode operations, and are called by the syscall 198165983Srwatson * code once the syscall has converted the path or file descriptor to a vnode 199165983Srwatson * (unlocked). The aclp pointer is assumed still to point to userland, so 200165983Srwatson * this should not be consumed within the kernel except by syscall code. 201165983Srwatson * Other code should directly invoke VOP_{SET,GET}ACL. 20254803Srwatson */ 20354803Srwatson 20454803Srwatson/* 20554803Srwatson * Given a vnode, set its ACL. 20654803Srwatson */ 20754803Srwatsonstatic int 20885582Srwatsonvacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 20956272Srwatson struct acl *aclp) 21054803Srwatson{ 211191249Strasz struct acl *inkernelacl; 21290202Srwatson struct mount *mp; 21354803Srwatson int error; 21454803Srwatson 215191249Strasz inkernelacl = acl_alloc(M_WAITOK); 216192586Strasz error = acl_copyin(aclp, inkernelacl, type); 217198875Strasz if (error != 0) 218191249Strasz goto out; 21990202Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 22090202Srwatson if (error != 0) 221191249Strasz goto out; 222175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 223101122Srwatson#ifdef MAC 224191249Strasz error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 225101122Srwatson if (error != 0) 226191249Strasz goto out_unlock; 227101122Srwatson#endif 228192586Strasz error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, 229192586Strasz td->td_ucred, td); 230101122Srwatson#ifdef MAC 231191249Straszout_unlock: 232101122Srwatson#endif 233175294Sattilio VOP_UNLOCK(vp, 0); 23490202Srwatson vn_finished_write(mp); 235191249Straszout: 236191249Strasz acl_free(inkernelacl); 237198875Strasz return (error); 23854803Srwatson} 23954803Srwatson 24054803Srwatson/* 24154803Srwatson * Given a vnode, get its ACL. 24254803Srwatson */ 24354803Srwatsonstatic int 24485582Srwatsonvacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type, 24554803Srwatson struct acl *aclp) 24654803Srwatson{ 247191249Strasz struct acl *inkernelacl; 24854803Srwatson int error; 24954803Srwatson 250246412Spluknet inkernelacl = acl_alloc(M_WAITOK | M_ZERO); 251175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 252101122Srwatson#ifdef MAC 253172930Srwatson error = mac_vnode_check_getacl(td->td_ucred, vp, type); 254101122Srwatson if (error != 0) 255101122Srwatson goto out; 256101122Srwatson#endif 257192586Strasz error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, 258192586Strasz td->td_ucred, td); 259192586Strasz 260101122Srwatson#ifdef MAC 261101122Srwatsonout: 262101122Srwatson#endif 263175294Sattilio VOP_UNLOCK(vp, 0); 26454803Srwatson if (error == 0) 265192586Strasz error = acl_copyout(inkernelacl, aclp, type); 266191249Strasz acl_free(inkernelacl); 26754803Srwatson return (error); 26854803Srwatson} 26954803Srwatson 27054803Srwatson/* 27154803Srwatson * Given a vnode, delete its ACL. 27254803Srwatson */ 27354803Srwatsonstatic int 27485582Srwatsonvacl_delete(struct thread *td, struct vnode *vp, acl_type_t type) 27554803Srwatson{ 27690202Srwatson struct mount *mp; 27754803Srwatson int error; 27854803Srwatson 27990202Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 280198875Strasz if (error != 0) 28190202Srwatson return (error); 282175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 283101122Srwatson#ifdef MAC 284172930Srwatson error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 285198875Strasz if (error != 0) 286101122Srwatson goto out; 287101122Srwatson#endif 288192586Strasz error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td); 289101122Srwatson#ifdef MAC 290101122Srwatsonout: 291101122Srwatson#endif 292175294Sattilio VOP_UNLOCK(vp, 0); 29390202Srwatson vn_finished_write(mp); 29454803Srwatson return (error); 29554803Srwatson} 29654803Srwatson 29754803Srwatson/* 29854803Srwatson * Given a vnode, check whether an ACL is appropriate for it 29954803Srwatson */ 30054803Srwatsonstatic int 30185582Srwatsonvacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 30254803Srwatson struct acl *aclp) 30354803Srwatson{ 304191249Strasz struct acl *inkernelacl; 30554803Srwatson int error; 30654803Srwatson 307191249Strasz inkernelacl = acl_alloc(M_WAITOK); 308192586Strasz error = acl_copyin(aclp, inkernelacl, type); 309198875Strasz if (error != 0) 310191249Strasz goto out; 311200058Strasz error = VOP_ACLCHECK(vp, acl_type_unold(type), inkernelacl, 312200058Strasz 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 327225617Skmacysys___acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 32854803Srwatson{ 32954803Srwatson struct nameidata nd; 330241896Skib int error; 33154803Srwatson 332241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 33354803Srwatson error = namei(&nd); 33482713Sdillon if (error == 0) { 335107855Salfred error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 33682713Sdillon NDFREE(&nd, 0); 33782713Sdillon } 33854803Srwatson return (error); 33954803Srwatson} 34054803Srwatson 34154803Srwatson/* 342108407Srwatson * Given a file path, get an ACL for it; don't follow links. 343108407Srwatson */ 344108407Srwatsonint 345225617Skmacysys___acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 346108407Srwatson{ 347108407Srwatson struct nameidata nd; 348241896Skib int error; 349108407Srwatson 350241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 351108407Srwatson error = namei(&nd); 352108407Srwatson if (error == 0) { 353108407Srwatson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 354108407Srwatson NDFREE(&nd, 0); 355108407Srwatson } 356108407Srwatson return (error); 357108407Srwatson} 358108407Srwatson 359108407Srwatson/* 360167211Srwatson * Given a file path, set an ACL for it. 36154803Srwatson */ 36254803Srwatsonint 363225617Skmacysys___acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 36454803Srwatson{ 36554803Srwatson struct nameidata nd; 366241896Skib int error; 36754803Srwatson 368241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 36954803Srwatson error = namei(&nd); 37082713Sdillon if (error == 0) { 371107855Salfred error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 37282713Sdillon NDFREE(&nd, 0); 37382713Sdillon } 37454803Srwatson return (error); 37554803Srwatson} 37654803Srwatson 37754803Srwatson/* 378108407Srwatson * Given a file path, set an ACL for it; don't follow links. 379108407Srwatson */ 380108407Srwatsonint 381225617Skmacysys___acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 382108407Srwatson{ 383108407Srwatson struct nameidata nd; 384241896Skib int error; 385108407Srwatson 386241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 387108407Srwatson error = namei(&nd); 388108407Srwatson if (error == 0) { 389108407Srwatson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 390108407Srwatson NDFREE(&nd, 0); 391108407Srwatson } 392108407Srwatson return (error); 393108407Srwatson} 394108407Srwatson 395108407Srwatson/* 396167234Srwatson * Given a file descriptor, get an ACL for it. 39754803Srwatson */ 39854803Srwatsonint 399225617Skmacysys___acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 40054803Srwatson{ 40154803Srwatson struct file *fp; 402241896Skib int error; 40354803Srwatson 404224778Srwatson error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_GET, &fp); 40582713Sdillon if (error == 0) { 406116678Sphk error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 40789306Salfred fdrop(fp, td); 40882713Sdillon } 40982713Sdillon return (error); 41054803Srwatson} 41154803Srwatson 41254803Srwatson/* 413167234Srwatson * Given a file descriptor, set an ACL for it. 41454803Srwatson */ 41554803Srwatsonint 416225617Skmacysys___acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 41754803Srwatson{ 41854803Srwatson struct file *fp; 419241896Skib int error; 42054803Srwatson 421224778Srwatson error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_SET, &fp); 42282713Sdillon if (error == 0) { 423116678Sphk error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 42489306Salfred fdrop(fp, td); 42582713Sdillon } 42682713Sdillon return (error); 42754803Srwatson} 42854803Srwatson 42954803Srwatson/* 43054803Srwatson * Given a file path, delete an ACL from it. 43154803Srwatson */ 43254803Srwatsonint 433225617Skmacysys___acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 43454803Srwatson{ 43554803Srwatson struct nameidata nd; 436241896Skib int error; 43754803Srwatson 438241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 43954803Srwatson error = namei(&nd); 44082713Sdillon if (error == 0) { 441107849Salfred error = vacl_delete(td, nd.ni_vp, uap->type); 44282713Sdillon NDFREE(&nd, 0); 44382713Sdillon } 44454803Srwatson return (error); 44554803Srwatson} 44654803Srwatson 44754803Srwatson/* 448108407Srwatson * Given a file path, delete an ACL from it; don't follow links. 449108407Srwatson */ 450108407Srwatsonint 451225617Skmacysys___acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 452108407Srwatson{ 453108407Srwatson struct nameidata nd; 454241896Skib int error; 455108407Srwatson 456241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 457108407Srwatson error = namei(&nd); 458108407Srwatson if (error == 0) { 459108407Srwatson error = vacl_delete(td, nd.ni_vp, uap->type); 460108407Srwatson NDFREE(&nd, 0); 461108407Srwatson } 462108407Srwatson return (error); 463108407Srwatson} 464108407Srwatson 465108407Srwatson/* 46654803Srwatson * Given a file path, delete an ACL from it. 46754803Srwatson */ 46854803Srwatsonint 469225617Skmacysys___acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 47054803Srwatson{ 47154803Srwatson struct file *fp; 472241896Skib int error; 47354803Srwatson 474224778Srwatson error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_DELETE, 475224778Srwatson &fp); 47682713Sdillon if (error == 0) { 477116678Sphk error = vacl_delete(td, fp->f_vnode, uap->type); 47889306Salfred fdrop(fp, td); 47982713Sdillon } 48054803Srwatson return (error); 48154803Srwatson} 48254803Srwatson 48354803Srwatson/* 484167211Srwatson * Given a file path, check an ACL for it. 48554803Srwatson */ 48654803Srwatsonint 487225617Skmacysys___acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 48854803Srwatson{ 489198875Strasz struct nameidata nd; 490241896Skib int error; 49154803Srwatson 492241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 49354803Srwatson error = namei(&nd); 49482713Sdillon if (error == 0) { 495107855Salfred error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 49682713Sdillon NDFREE(&nd, 0); 49782713Sdillon } 49854803Srwatson return (error); 49954803Srwatson} 50054803Srwatson 50154803Srwatson/* 502108407Srwatson * Given a file path, check an ACL for it; don't follow links. 503108407Srwatson */ 504108407Srwatsonint 505225617Skmacysys___acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 506108407Srwatson{ 507198877Strasz struct nameidata nd; 508241896Skib int error; 509108407Srwatson 510241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 511108407Srwatson error = namei(&nd); 512108407Srwatson if (error == 0) { 513108407Srwatson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 514108407Srwatson NDFREE(&nd, 0); 515108407Srwatson } 516108407Srwatson return (error); 517108407Srwatson} 518108407Srwatson 519108407Srwatson/* 520167211Srwatson * Given a file descriptor, check an ACL for it. 52154803Srwatson */ 52254803Srwatsonint 523225617Skmacysys___acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 52454803Srwatson{ 52554803Srwatson struct file *fp; 526241896Skib int error; 52754803Srwatson 528224778Srwatson error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_CHECK, 529224778Srwatson &fp); 53082713Sdillon if (error == 0) { 531116678Sphk error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 53289306Salfred fdrop(fp, td); 53382713Sdillon } 53482713Sdillon return (error); 53554803Srwatson} 536149811Scsjp 537191249Straszstruct acl * 538191249Straszacl_alloc(int flags) 539191249Strasz{ 540191249Strasz struct acl *aclp; 541191249Strasz 542191266Strasz aclp = malloc(sizeof(*aclp), M_ACL, flags); 543192586Strasz aclp->acl_maxcnt = ACL_MAX_ENTRIES; 544191249Strasz 545191249Strasz return (aclp); 546191249Strasz} 547191249Strasz 548191249Straszvoid 549191249Straszacl_free(struct acl *aclp) 550191249Strasz{ 551191249Strasz 552191266Strasz free(aclp, M_ACL); 553191249Strasz} 554