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$"); 37116182Sobrien 3854803Srwatson#include <sys/param.h> 3954803Srwatson#include <sys/systm.h> 4054803Srwatson#include <sys/sysproto.h> 41280258Srwatson#include <sys/capsicum.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{ 151274648Skib uint32_t am; 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: 166274648Skib error = fueword32((char *)user_acl + 167274648Skib offsetof(struct acl, acl_maxcnt), &am); 168274648Skib if (error == -1) 169274648Skib return (EFAULT); 170274648Skib if (am != ACL_MAX_ENTRIES) 171192586Strasz return (EINVAL); 172192586Strasz 173192586Strasz error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl)); 174192586Strasz } 175192586Strasz 176192586Strasz return (error); 177192586Strasz} 178192586Strasz 179192586Strasz/* 180192586Strasz * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" 181200058Strasz * counterpart. It's required for old (pre-NFSv4 ACLs) libc to work 182192586Strasz * with new kernel. Fixing 'type' for old binaries with new libc 183192586Strasz * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold(). 184192586Strasz */ 185192586Straszstatic int 186192586Straszacl_type_unold(int type) 187192586Strasz{ 188192586Strasz switch (type) { 189192586Strasz case ACL_TYPE_ACCESS_OLD: 190192586Strasz return (ACL_TYPE_ACCESS); 191192586Strasz 192192586Strasz case ACL_TYPE_DEFAULT_OLD: 193192586Strasz return (ACL_TYPE_DEFAULT); 194192586Strasz 195192586Strasz default: 196192586Strasz return (type); 197192586Strasz } 198192586Strasz} 199192586Strasz 200192586Strasz/* 201165983Srwatson * These calls wrap the real vnode operations, and are called by the syscall 202165983Srwatson * code once the syscall has converted the path or file descriptor to a vnode 203165983Srwatson * (unlocked). The aclp pointer is assumed still to point to userland, so 204165983Srwatson * this should not be consumed within the kernel except by syscall code. 205165983Srwatson * Other code should directly invoke VOP_{SET,GET}ACL. 20654803Srwatson */ 20754803Srwatson 20854803Srwatson/* 20954803Srwatson * Given a vnode, set its ACL. 21054803Srwatson */ 21154803Srwatsonstatic int 21285582Srwatsonvacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 21356272Srwatson struct acl *aclp) 21454803Srwatson{ 215191249Strasz struct acl *inkernelacl; 21690202Srwatson struct mount *mp; 21754803Srwatson int error; 21854803Srwatson 219191249Strasz inkernelacl = acl_alloc(M_WAITOK); 220192586Strasz error = acl_copyin(aclp, inkernelacl, type); 221198875Strasz if (error != 0) 222191249Strasz goto out; 22390202Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 22490202Srwatson if (error != 0) 225191249Strasz goto out; 226175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 227101122Srwatson#ifdef MAC 228191249Strasz error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 229101122Srwatson if (error != 0) 230191249Strasz goto out_unlock; 231101122Srwatson#endif 232192586Strasz error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, 233192586Strasz td->td_ucred, td); 234101122Srwatson#ifdef MAC 235191249Straszout_unlock: 236101122Srwatson#endif 237175294Sattilio VOP_UNLOCK(vp, 0); 23890202Srwatson vn_finished_write(mp); 239191249Straszout: 240191249Strasz acl_free(inkernelacl); 241198875Strasz return (error); 24254803Srwatson} 24354803Srwatson 24454803Srwatson/* 24554803Srwatson * Given a vnode, get its ACL. 24654803Srwatson */ 24754803Srwatsonstatic int 24885582Srwatsonvacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type, 24954803Srwatson struct acl *aclp) 25054803Srwatson{ 251191249Strasz struct acl *inkernelacl; 25254803Srwatson int error; 25354803Srwatson 254246412Spluknet inkernelacl = acl_alloc(M_WAITOK | M_ZERO); 255175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 256101122Srwatson#ifdef MAC 257172930Srwatson error = mac_vnode_check_getacl(td->td_ucred, vp, type); 258101122Srwatson if (error != 0) 259101122Srwatson goto out; 260101122Srwatson#endif 261192586Strasz error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, 262192586Strasz td->td_ucred, td); 263192586Strasz 264101122Srwatson#ifdef MAC 265101122Srwatsonout: 266101122Srwatson#endif 267175294Sattilio VOP_UNLOCK(vp, 0); 26854803Srwatson if (error == 0) 269192586Strasz error = acl_copyout(inkernelacl, aclp, type); 270191249Strasz acl_free(inkernelacl); 27154803Srwatson return (error); 27254803Srwatson} 27354803Srwatson 27454803Srwatson/* 27554803Srwatson * Given a vnode, delete its ACL. 27654803Srwatson */ 27754803Srwatsonstatic int 27885582Srwatsonvacl_delete(struct thread *td, struct vnode *vp, acl_type_t type) 27954803Srwatson{ 28090202Srwatson struct mount *mp; 28154803Srwatson int error; 28254803Srwatson 28390202Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 284198875Strasz if (error != 0) 28590202Srwatson return (error); 286175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 287101122Srwatson#ifdef MAC 288172930Srwatson error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 289198875Strasz if (error != 0) 290101122Srwatson goto out; 291101122Srwatson#endif 292192586Strasz error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td); 293101122Srwatson#ifdef MAC 294101122Srwatsonout: 295101122Srwatson#endif 296175294Sattilio VOP_UNLOCK(vp, 0); 29790202Srwatson vn_finished_write(mp); 29854803Srwatson return (error); 29954803Srwatson} 30054803Srwatson 30154803Srwatson/* 30254803Srwatson * Given a vnode, check whether an ACL is appropriate for it 30354803Srwatson */ 30454803Srwatsonstatic int 30585582Srwatsonvacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 30654803Srwatson struct acl *aclp) 30754803Srwatson{ 308191249Strasz struct acl *inkernelacl; 30954803Srwatson int error; 31054803Srwatson 311191249Strasz inkernelacl = acl_alloc(M_WAITOK); 312192586Strasz error = acl_copyin(aclp, inkernelacl, type); 313198875Strasz if (error != 0) 314191249Strasz goto out; 315200058Strasz error = VOP_ACLCHECK(vp, acl_type_unold(type), inkernelacl, 316200058Strasz td->td_ucred, td); 317191249Straszout: 318191249Strasz acl_free(inkernelacl); 31954803Srwatson return (error); 32054803Srwatson} 32154803Srwatson 32254803Srwatson/* 323165983Srwatson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't 324165983Srwatson * need to lock, as the vacl_ code will get/release any locks required. 32554803Srwatson */ 32654803Srwatson 32754803Srwatson/* 32854803Srwatson * Given a file path, get an ACL for it 32954803Srwatson */ 33054803Srwatsonint 331225617Skmacysys___acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 33254803Srwatson{ 33354803Srwatson struct nameidata nd; 334241896Skib int error; 33554803Srwatson 336241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 33754803Srwatson error = namei(&nd); 33882713Sdillon if (error == 0) { 339107855Salfred error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 34082713Sdillon NDFREE(&nd, 0); 34182713Sdillon } 34254803Srwatson return (error); 34354803Srwatson} 34454803Srwatson 34554803Srwatson/* 346108407Srwatson * Given a file path, get an ACL for it; don't follow links. 347108407Srwatson */ 348108407Srwatsonint 349225617Skmacysys___acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 350108407Srwatson{ 351108407Srwatson struct nameidata nd; 352241896Skib int error; 353108407Srwatson 354241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 355108407Srwatson error = namei(&nd); 356108407Srwatson if (error == 0) { 357108407Srwatson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 358108407Srwatson NDFREE(&nd, 0); 359108407Srwatson } 360108407Srwatson return (error); 361108407Srwatson} 362108407Srwatson 363108407Srwatson/* 364167211Srwatson * Given a file path, set an ACL for it. 36554803Srwatson */ 36654803Srwatsonint 367225617Skmacysys___acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 36854803Srwatson{ 36954803Srwatson struct nameidata nd; 370241896Skib int error; 37154803Srwatson 372241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 37354803Srwatson error = namei(&nd); 37482713Sdillon if (error == 0) { 375107855Salfred error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 37682713Sdillon NDFREE(&nd, 0); 37782713Sdillon } 37854803Srwatson return (error); 37954803Srwatson} 38054803Srwatson 38154803Srwatson/* 382108407Srwatson * Given a file path, set an ACL for it; don't follow links. 383108407Srwatson */ 384108407Srwatsonint 385225617Skmacysys___acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 386108407Srwatson{ 387108407Srwatson struct nameidata nd; 388241896Skib int error; 389108407Srwatson 390241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 391108407Srwatson error = namei(&nd); 392108407Srwatson if (error == 0) { 393108407Srwatson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 394108407Srwatson NDFREE(&nd, 0); 395108407Srwatson } 396108407Srwatson return (error); 397108407Srwatson} 398108407Srwatson 399108407Srwatson/* 400167234Srwatson * Given a file descriptor, get an ACL for it. 40154803Srwatson */ 40254803Srwatsonint 403225617Skmacysys___acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 40454803Srwatson{ 40554803Srwatson struct file *fp; 406255219Spjd cap_rights_t rights; 407241896Skib int error; 40854803Srwatson 409255219Spjd error = getvnode(td->td_proc->p_fd, uap->filedes, 410255219Spjd cap_rights_init(&rights, CAP_ACL_GET), &fp); 41182713Sdillon if (error == 0) { 412116678Sphk error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 41389306Salfred fdrop(fp, td); 41482713Sdillon } 41582713Sdillon return (error); 41654803Srwatson} 41754803Srwatson 41854803Srwatson/* 419167234Srwatson * Given a file descriptor, set an ACL for it. 42054803Srwatson */ 42154803Srwatsonint 422225617Skmacysys___acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 42354803Srwatson{ 42454803Srwatson struct file *fp; 425255219Spjd cap_rights_t rights; 426241896Skib int error; 42754803Srwatson 428255219Spjd error = getvnode(td->td_proc->p_fd, uap->filedes, 429255219Spjd cap_rights_init(&rights, CAP_ACL_SET), &fp); 43082713Sdillon if (error == 0) { 431116678Sphk error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 43289306Salfred fdrop(fp, td); 43382713Sdillon } 43482713Sdillon return (error); 43554803Srwatson} 43654803Srwatson 43754803Srwatson/* 43854803Srwatson * Given a file path, delete an ACL from it. 43954803Srwatson */ 44054803Srwatsonint 441225617Skmacysys___acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 44254803Srwatson{ 44354803Srwatson struct nameidata nd; 444241896Skib int error; 44554803Srwatson 446241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 44754803Srwatson error = namei(&nd); 44882713Sdillon if (error == 0) { 449107849Salfred error = vacl_delete(td, nd.ni_vp, uap->type); 45082713Sdillon NDFREE(&nd, 0); 45182713Sdillon } 45254803Srwatson return (error); 45354803Srwatson} 45454803Srwatson 45554803Srwatson/* 456108407Srwatson * Given a file path, delete an ACL from it; don't follow links. 457108407Srwatson */ 458108407Srwatsonint 459225617Skmacysys___acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 460108407Srwatson{ 461108407Srwatson struct nameidata nd; 462241896Skib int error; 463108407Srwatson 464241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 465108407Srwatson error = namei(&nd); 466108407Srwatson if (error == 0) { 467108407Srwatson error = vacl_delete(td, nd.ni_vp, uap->type); 468108407Srwatson NDFREE(&nd, 0); 469108407Srwatson } 470108407Srwatson return (error); 471108407Srwatson} 472108407Srwatson 473108407Srwatson/* 47454803Srwatson * Given a file path, delete an ACL from it. 47554803Srwatson */ 47654803Srwatsonint 477225617Skmacysys___acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 47854803Srwatson{ 47954803Srwatson struct file *fp; 480255219Spjd cap_rights_t rights; 481241896Skib int error; 48254803Srwatson 483255219Spjd error = getvnode(td->td_proc->p_fd, uap->filedes, 484255219Spjd cap_rights_init(&rights, CAP_ACL_DELETE), &fp); 48582713Sdillon if (error == 0) { 486116678Sphk error = vacl_delete(td, fp->f_vnode, uap->type); 48789306Salfred fdrop(fp, td); 48882713Sdillon } 48954803Srwatson return (error); 49054803Srwatson} 49154803Srwatson 49254803Srwatson/* 493167211Srwatson * Given a file path, check an ACL for it. 49454803Srwatson */ 49554803Srwatsonint 496225617Skmacysys___acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 49754803Srwatson{ 498198875Strasz struct nameidata nd; 499241896Skib int error; 50054803Srwatson 501241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 50254803Srwatson error = namei(&nd); 50382713Sdillon if (error == 0) { 504107855Salfred error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 50582713Sdillon NDFREE(&nd, 0); 50682713Sdillon } 50754803Srwatson return (error); 50854803Srwatson} 50954803Srwatson 51054803Srwatson/* 511108407Srwatson * Given a file path, check an ACL for it; don't follow links. 512108407Srwatson */ 513108407Srwatsonint 514225617Skmacysys___acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 515108407Srwatson{ 516198877Strasz struct nameidata nd; 517241896Skib int error; 518108407Srwatson 519241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 520108407Srwatson error = namei(&nd); 521108407Srwatson if (error == 0) { 522108407Srwatson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 523108407Srwatson NDFREE(&nd, 0); 524108407Srwatson } 525108407Srwatson return (error); 526108407Srwatson} 527108407Srwatson 528108407Srwatson/* 529167211Srwatson * Given a file descriptor, check an ACL for it. 53054803Srwatson */ 53154803Srwatsonint 532225617Skmacysys___acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 53354803Srwatson{ 53454803Srwatson struct file *fp; 535255219Spjd cap_rights_t rights; 536241896Skib int error; 53754803Srwatson 538255219Spjd error = getvnode(td->td_proc->p_fd, uap->filedes, 539255219Spjd cap_rights_init(&rights, CAP_ACL_CHECK), &fp); 54082713Sdillon if (error == 0) { 541116678Sphk error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 54289306Salfred fdrop(fp, td); 54382713Sdillon } 54482713Sdillon return (error); 54554803Srwatson} 546149811Scsjp 547191249Straszstruct acl * 548191249Straszacl_alloc(int flags) 549191249Strasz{ 550191249Strasz struct acl *aclp; 551191249Strasz 552191266Strasz aclp = malloc(sizeof(*aclp), M_ACL, flags); 553254135Strasz if (aclp == NULL) 554254135Strasz return (NULL); 555254135Strasz 556192586Strasz aclp->acl_maxcnt = ACL_MAX_ENTRIES; 557191249Strasz 558191249Strasz return (aclp); 559191249Strasz} 560191249Strasz 561191249Straszvoid 562191249Straszacl_free(struct acl *aclp) 563191249Strasz{ 564191249Strasz 565191266Strasz free(aclp, M_ACL); 566191249Strasz} 567