191f37dcbSRobert Watson /*- 2e4256d1eSRobert Watson * Copyright (c) 1999-2006 Robert N. M. Watson 391f37dcbSRobert Watson * All rights reserved. 491f37dcbSRobert Watson * 56d878543SRobert Watson * This software was developed by Robert Watson for the TrustedBSD Project. 66d878543SRobert Watson * 791f37dcbSRobert Watson * Redistribution and use in source and binary forms, with or without 891f37dcbSRobert Watson * modification, are permitted provided that the following conditions 991f37dcbSRobert Watson * are met: 1091f37dcbSRobert Watson * 1. Redistributions of source code must retain the above copyright 1191f37dcbSRobert Watson * notice, this list of conditions and the following disclaimer. 1291f37dcbSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 1391f37dcbSRobert Watson * notice, this list of conditions and the following disclaimer in the 1491f37dcbSRobert Watson * documentation and/or other materials provided with the distribution. 1591f37dcbSRobert Watson * 1691f37dcbSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1791f37dcbSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1891f37dcbSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1991f37dcbSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2091f37dcbSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2191f37dcbSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2291f37dcbSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2391f37dcbSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2491f37dcbSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2591f37dcbSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2691f37dcbSRobert Watson * SUCH DAMAGE. 2791f37dcbSRobert Watson */ 2891f37dcbSRobert Watson /* 295293465fSRobert Watson * Developed by the TrustedBSD Project. 30e4256d1eSRobert Watson * 31e4256d1eSRobert Watson * ACL system calls and other functions common across different ACL types. 32e4256d1eSRobert Watson * Type-specific routines go into subr_acl_<type>.c. 3391f37dcbSRobert Watson */ 3491f37dcbSRobert Watson 35677b542eSDavid E. O'Brien #include <sys/cdefs.h> 36677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 37677b542eSDavid E. O'Brien 3891f37dcbSRobert Watson #include <sys/param.h> 3991f37dcbSRobert Watson #include <sys/systm.h> 4091f37dcbSRobert Watson #include <sys/sysproto.h> 41a9d2f8d8SRobert Watson #include <sys/capability.h> 4257b4252eSKonstantin Belousov #include <sys/fcntl.h> 4391f37dcbSRobert Watson #include <sys/kernel.h> 4491f37dcbSRobert Watson #include <sys/malloc.h> 4542e7197fSChristian S.J. Peron #include <sys/mount.h> 4691f37dcbSRobert Watson #include <sys/vnode.h> 4791f37dcbSRobert Watson #include <sys/lock.h> 48f708f4d1SMatthew Dillon #include <sys/mutex.h> 4991f37dcbSRobert Watson #include <sys/namei.h> 5091f37dcbSRobert Watson #include <sys/file.h> 5113438f68SAlfred Perlstein #include <sys/filedesc.h> 5291f37dcbSRobert Watson #include <sys/proc.h> 5391f37dcbSRobert Watson #include <sys/sysent.h> 5491f37dcbSRobert Watson #include <sys/acl.h> 5591f37dcbSRobert Watson 56aed55708SRobert Watson #include <security/mac/mac_framework.h> 57aed55708SRobert Watson 58ae1add4eSEdward Tomasz Napierala CTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES); 59ae1add4eSEdward Tomasz Napierala 60ae1add4eSEdward Tomasz Napierala MALLOC_DEFINE(M_ACL, "acl", "Access Control Lists"); 6191f37dcbSRobert Watson 62cbeb8402SRobert Watson static int vacl_set_acl(struct thread *td, struct vnode *vp, 63cbeb8402SRobert Watson acl_type_t type, struct acl *aclp); 64cbeb8402SRobert Watson static int vacl_get_acl(struct thread *td, struct vnode *vp, 65cbeb8402SRobert Watson acl_type_t type, struct acl *aclp); 66b40ce416SJulian Elischer static int vacl_aclcheck(struct thread *td, struct vnode *vp, 67b114e127SRobert Watson acl_type_t type, struct acl *aclp); 6891f37dcbSRobert Watson 69ae1add4eSEdward Tomasz Napierala int 70ae1add4eSEdward Tomasz Napierala acl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest) 71ae1add4eSEdward Tomasz Napierala { 72ae1add4eSEdward Tomasz Napierala int i; 73ae1add4eSEdward Tomasz Napierala 74ae1add4eSEdward Tomasz Napierala if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES) 75ae1add4eSEdward Tomasz Napierala return (EINVAL); 76ae1add4eSEdward Tomasz Napierala 77ae1add4eSEdward Tomasz Napierala bzero(dest, sizeof(*dest)); 78ae1add4eSEdward Tomasz Napierala 79ae1add4eSEdward Tomasz Napierala dest->acl_cnt = source->acl_cnt; 80ae1add4eSEdward Tomasz Napierala dest->acl_maxcnt = ACL_MAX_ENTRIES; 81ae1add4eSEdward Tomasz Napierala 82ae1add4eSEdward Tomasz Napierala for (i = 0; i < dest->acl_cnt; i++) { 83ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 84ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 85ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 86ae1add4eSEdward Tomasz Napierala } 87ae1add4eSEdward Tomasz Napierala 88ae1add4eSEdward Tomasz Napierala return (0); 89ae1add4eSEdward Tomasz Napierala } 90ae1add4eSEdward Tomasz Napierala 91ae1add4eSEdward Tomasz Napierala int 92ae1add4eSEdward Tomasz Napierala acl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest) 93ae1add4eSEdward Tomasz Napierala { 94ae1add4eSEdward Tomasz Napierala int i; 95ae1add4eSEdward Tomasz Napierala 96ce9d79aaSEdward Tomasz Napierala if (source->acl_cnt > OLDACL_MAX_ENTRIES) 97ae1add4eSEdward Tomasz Napierala return (EINVAL); 98ae1add4eSEdward Tomasz Napierala 99ae1add4eSEdward Tomasz Napierala bzero(dest, sizeof(*dest)); 100ae1add4eSEdward Tomasz Napierala 101ae1add4eSEdward Tomasz Napierala dest->acl_cnt = source->acl_cnt; 102ae1add4eSEdward Tomasz Napierala 103ae1add4eSEdward Tomasz Napierala for (i = 0; i < dest->acl_cnt; i++) { 104ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 105ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 106ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 107ae1add4eSEdward Tomasz Napierala } 108ae1add4eSEdward Tomasz Napierala 109ae1add4eSEdward Tomasz Napierala return (0); 110ae1add4eSEdward Tomasz Napierala } 111ae1add4eSEdward Tomasz Napierala 112ae1add4eSEdward Tomasz Napierala /* 113ae1add4eSEdward Tomasz Napierala * At one time, "struct ACL" was extended in order to add support for NFSv4 114ae1add4eSEdward Tomasz Napierala * ACLs. Instead of creating compatibility versions of all the ACL-related 115ae1add4eSEdward Tomasz Napierala * syscalls, they were left intact. It's possible to find out what the code 116ae1add4eSEdward Tomasz Napierala * calling these syscalls (libc) expects basing on "type" argument - if it's 117ae1add4eSEdward Tomasz Napierala * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were 118ae1add4eSEdward Tomasz Napierala * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct 119ae1add4eSEdward Tomasz Napierala * oldacl". If it's something else, then it's the new "struct acl". In the 120ae1add4eSEdward Tomasz Napierala * latter case, the routines below just copyin/copyout the contents. In the 121ae1add4eSEdward Tomasz Napierala * former case, they copyin the "struct oldacl" and convert it to the new 122ae1add4eSEdward Tomasz Napierala * format. 123ae1add4eSEdward Tomasz Napierala */ 124ae1add4eSEdward Tomasz Napierala static int 125ae1add4eSEdward Tomasz Napierala acl_copyin(void *user_acl, struct acl *kernel_acl, acl_type_t type) 126ae1add4eSEdward Tomasz Napierala { 127ae1add4eSEdward Tomasz Napierala int error; 128ae1add4eSEdward Tomasz Napierala struct oldacl old; 129ae1add4eSEdward Tomasz Napierala 130ae1add4eSEdward Tomasz Napierala switch (type) { 131ae1add4eSEdward Tomasz Napierala case ACL_TYPE_ACCESS_OLD: 132ae1add4eSEdward Tomasz Napierala case ACL_TYPE_DEFAULT_OLD: 133ae1add4eSEdward Tomasz Napierala error = copyin(user_acl, &old, sizeof(old)); 134ae1add4eSEdward Tomasz Napierala if (error != 0) 135ae1add4eSEdward Tomasz Napierala break; 136ae1add4eSEdward Tomasz Napierala acl_copy_oldacl_into_acl(&old, kernel_acl); 137ae1add4eSEdward Tomasz Napierala break; 138ae1add4eSEdward Tomasz Napierala 139ae1add4eSEdward Tomasz Napierala default: 140ae1add4eSEdward Tomasz Napierala error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl)); 141ae1add4eSEdward Tomasz Napierala if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES) 142ae1add4eSEdward Tomasz Napierala return (EINVAL); 143ae1add4eSEdward Tomasz Napierala } 144ae1add4eSEdward Tomasz Napierala 145ae1add4eSEdward Tomasz Napierala return (error); 146ae1add4eSEdward Tomasz Napierala } 147ae1add4eSEdward Tomasz Napierala 148ae1add4eSEdward Tomasz Napierala static int 149ae1add4eSEdward Tomasz Napierala acl_copyout(struct acl *kernel_acl, void *user_acl, acl_type_t type) 150ae1add4eSEdward Tomasz Napierala { 151ae1add4eSEdward Tomasz Napierala int error; 152ae1add4eSEdward Tomasz Napierala struct oldacl old; 153ae1add4eSEdward Tomasz Napierala 154ae1add4eSEdward Tomasz Napierala switch (type) { 155ae1add4eSEdward Tomasz Napierala case ACL_TYPE_ACCESS_OLD: 156ae1add4eSEdward Tomasz Napierala case ACL_TYPE_DEFAULT_OLD: 157ae1add4eSEdward Tomasz Napierala error = acl_copy_acl_into_oldacl(kernel_acl, &old); 158ae1add4eSEdward Tomasz Napierala if (error != 0) 159ae1add4eSEdward Tomasz Napierala break; 160ae1add4eSEdward Tomasz Napierala 161ae1add4eSEdward Tomasz Napierala error = copyout(&old, user_acl, sizeof(old)); 162ae1add4eSEdward Tomasz Napierala break; 163ae1add4eSEdward Tomasz Napierala 164ae1add4eSEdward Tomasz Napierala default: 165d5e0b215SEdward Tomasz Napierala if (fuword32((char *)user_acl + 166ae1add4eSEdward Tomasz Napierala offsetof(struct acl, acl_maxcnt)) != ACL_MAX_ENTRIES) 167ae1add4eSEdward Tomasz Napierala return (EINVAL); 168ae1add4eSEdward Tomasz Napierala 169ae1add4eSEdward Tomasz Napierala error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl)); 170ae1add4eSEdward Tomasz Napierala } 171ae1add4eSEdward Tomasz Napierala 172ae1add4eSEdward Tomasz Napierala return (error); 173ae1add4eSEdward Tomasz Napierala } 174ae1add4eSEdward Tomasz Napierala 175ae1add4eSEdward Tomasz Napierala /* 176ae1add4eSEdward Tomasz Napierala * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" 1776bb58cddSEdward Tomasz Napierala * counterpart. It's required for old (pre-NFSv4 ACLs) libc to work 178ae1add4eSEdward Tomasz Napierala * with new kernel. Fixing 'type' for old binaries with new libc 179ae1add4eSEdward Tomasz Napierala * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold(). 180ae1add4eSEdward Tomasz Napierala */ 181ae1add4eSEdward Tomasz Napierala static int 182ae1add4eSEdward Tomasz Napierala acl_type_unold(int type) 183ae1add4eSEdward Tomasz Napierala { 184ae1add4eSEdward Tomasz Napierala switch (type) { 185ae1add4eSEdward Tomasz Napierala case ACL_TYPE_ACCESS_OLD: 186ae1add4eSEdward Tomasz Napierala return (ACL_TYPE_ACCESS); 187ae1add4eSEdward Tomasz Napierala 188ae1add4eSEdward Tomasz Napierala case ACL_TYPE_DEFAULT_OLD: 189ae1add4eSEdward Tomasz Napierala return (ACL_TYPE_DEFAULT); 190ae1add4eSEdward Tomasz Napierala 191ae1add4eSEdward Tomasz Napierala default: 192ae1add4eSEdward Tomasz Napierala return (type); 193ae1add4eSEdward Tomasz Napierala } 194ae1add4eSEdward Tomasz Napierala } 195ae1add4eSEdward Tomasz Napierala 19691f37dcbSRobert Watson /* 197b0c521e2SRobert Watson * These calls wrap the real vnode operations, and are called by the syscall 198b0c521e2SRobert Watson * code once the syscall has converted the path or file descriptor to a vnode 199b0c521e2SRobert Watson * (unlocked). The aclp pointer is assumed still to point to userland, so 200b0c521e2SRobert Watson * this should not be consumed within the kernel except by syscall code. 201b0c521e2SRobert Watson * Other code should directly invoke VOP_{SET,GET}ACL. 20291f37dcbSRobert Watson */ 20391f37dcbSRobert Watson 20491f37dcbSRobert Watson /* 20591f37dcbSRobert Watson * Given a vnode, set its ACL. 20691f37dcbSRobert Watson */ 20791f37dcbSRobert Watson static int 208b40ce416SJulian Elischer vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 20991f37dcbSRobert Watson struct acl *aclp) 21091f37dcbSRobert Watson { 211b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 2124e1123c7SRobert Watson struct mount *mp; 21391f37dcbSRobert Watson int error; 21491f37dcbSRobert Watson 215b998d381SEdward Tomasz Napierala inkernelacl = acl_alloc(M_WAITOK); 216ae1add4eSEdward Tomasz Napierala error = acl_copyin(aclp, inkernelacl, type); 217da9ce28eSEdward Tomasz Napierala if (error != 0) 218b998d381SEdward Tomasz Napierala goto out; 2194e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 2204e1123c7SRobert Watson if (error != 0) 221b998d381SEdward Tomasz Napierala goto out; 222cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 223c86ca022SRobert Watson #ifdef MAC 224b998d381SEdward Tomasz Napierala error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 225c86ca022SRobert Watson if (error != 0) 226b998d381SEdward Tomasz Napierala goto out_unlock; 227c86ca022SRobert Watson #endif 228ae1add4eSEdward Tomasz Napierala error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, 229ae1add4eSEdward Tomasz Napierala td->td_ucred, td); 230c86ca022SRobert Watson #ifdef MAC 231b998d381SEdward Tomasz Napierala out_unlock: 232c86ca022SRobert Watson #endif 23322db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 2344e1123c7SRobert Watson vn_finished_write(mp); 235b998d381SEdward Tomasz Napierala out: 236b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 23791f37dcbSRobert Watson return (error); 23891f37dcbSRobert Watson } 23991f37dcbSRobert Watson 24091f37dcbSRobert Watson /* 24191f37dcbSRobert Watson * Given a vnode, get its ACL. 24291f37dcbSRobert Watson */ 24391f37dcbSRobert Watson static int 244b40ce416SJulian Elischer vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type, 24591f37dcbSRobert Watson struct acl *aclp) 24691f37dcbSRobert Watson { 247b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 24891f37dcbSRobert Watson int error; 24991f37dcbSRobert Watson 25023c053d6SSergey Kandaurov inkernelacl = acl_alloc(M_WAITOK | M_ZERO); 251cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 252c86ca022SRobert Watson #ifdef MAC 25330d239bcSRobert Watson error = mac_vnode_check_getacl(td->td_ucred, vp, type); 254c86ca022SRobert Watson if (error != 0) 255c86ca022SRobert Watson goto out; 256c86ca022SRobert Watson #endif 257ae1add4eSEdward Tomasz Napierala error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, 258ae1add4eSEdward Tomasz Napierala td->td_ucred, td); 259ae1add4eSEdward Tomasz Napierala 260c86ca022SRobert Watson #ifdef MAC 261c86ca022SRobert Watson out: 262c86ca022SRobert Watson #endif 26322db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 26491f37dcbSRobert Watson if (error == 0) 265ae1add4eSEdward Tomasz Napierala error = acl_copyout(inkernelacl, aclp, type); 266b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 26791f37dcbSRobert Watson return (error); 26891f37dcbSRobert Watson } 26991f37dcbSRobert Watson 27091f37dcbSRobert Watson /* 27191f37dcbSRobert Watson * Given a vnode, delete its ACL. 27291f37dcbSRobert Watson */ 27391f37dcbSRobert Watson static int 274b40ce416SJulian Elischer vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type) 27591f37dcbSRobert Watson { 2764e1123c7SRobert Watson struct mount *mp; 27791f37dcbSRobert Watson int error; 27891f37dcbSRobert Watson 2794e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 280da9ce28eSEdward Tomasz Napierala if (error != 0) 2814e1123c7SRobert Watson return (error); 282cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 283c86ca022SRobert Watson #ifdef MAC 28430d239bcSRobert Watson error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 285da9ce28eSEdward Tomasz Napierala if (error != 0) 286c86ca022SRobert Watson goto out; 287c86ca022SRobert Watson #endif 288ae1add4eSEdward Tomasz Napierala error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td); 289c86ca022SRobert Watson #ifdef MAC 290c86ca022SRobert Watson out: 291c86ca022SRobert Watson #endif 29222db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 2934e1123c7SRobert Watson vn_finished_write(mp); 29491f37dcbSRobert Watson return (error); 29591f37dcbSRobert Watson } 29691f37dcbSRobert Watson 29791f37dcbSRobert Watson /* 29891f37dcbSRobert Watson * Given a vnode, check whether an ACL is appropriate for it 29991f37dcbSRobert Watson */ 30091f37dcbSRobert Watson static int 301b40ce416SJulian Elischer vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 30291f37dcbSRobert Watson struct acl *aclp) 30391f37dcbSRobert Watson { 304b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 30591f37dcbSRobert Watson int error; 30691f37dcbSRobert Watson 307b998d381SEdward Tomasz Napierala inkernelacl = acl_alloc(M_WAITOK); 308ae1add4eSEdward Tomasz Napierala error = acl_copyin(aclp, inkernelacl, type); 309da9ce28eSEdward Tomasz Napierala if (error != 0) 310b998d381SEdward Tomasz Napierala goto out; 3116bb58cddSEdward Tomasz Napierala error = VOP_ACLCHECK(vp, acl_type_unold(type), inkernelacl, 3126bb58cddSEdward Tomasz Napierala td->td_ucred, td); 313b998d381SEdward Tomasz Napierala out: 314b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 31591f37dcbSRobert Watson return (error); 31691f37dcbSRobert Watson } 31791f37dcbSRobert Watson 31891f37dcbSRobert Watson /* 319b0c521e2SRobert Watson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't 320b0c521e2SRobert Watson * need to lock, as the vacl_ code will get/release any locks required. 32191f37dcbSRobert Watson */ 32291f37dcbSRobert Watson 32391f37dcbSRobert Watson /* 32491f37dcbSRobert Watson * Given a file path, get an ACL for it 32591f37dcbSRobert Watson */ 32691f37dcbSRobert Watson int 3278451d0ddSKip Macy sys___acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 32891f37dcbSRobert Watson { 32991f37dcbSRobert Watson struct nameidata nd; 3305050aa86SKonstantin Belousov int error; 33191f37dcbSRobert Watson 3325050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 33391f37dcbSRobert Watson error = namei(&nd); 334f708f4d1SMatthew Dillon if (error == 0) { 335f97182acSAlfred Perlstein error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 33691f37dcbSRobert Watson NDFREE(&nd, 0); 337f708f4d1SMatthew Dillon } 33891f37dcbSRobert Watson return (error); 33991f37dcbSRobert Watson } 34091f37dcbSRobert Watson 34191f37dcbSRobert Watson /* 3423c67c23bSRobert Watson * Given a file path, get an ACL for it; don't follow links. 3433c67c23bSRobert Watson */ 3443c67c23bSRobert Watson int 3458451d0ddSKip Macy sys___acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 3463c67c23bSRobert Watson { 3473c67c23bSRobert Watson struct nameidata nd; 3485050aa86SKonstantin Belousov int error; 3493c67c23bSRobert Watson 3505050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 3513c67c23bSRobert Watson error = namei(&nd); 3523c67c23bSRobert Watson if (error == 0) { 3533c67c23bSRobert Watson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 3543c67c23bSRobert Watson NDFREE(&nd, 0); 3553c67c23bSRobert Watson } 3563c67c23bSRobert Watson return (error); 3573c67c23bSRobert Watson } 3583c67c23bSRobert Watson 3593c67c23bSRobert Watson /* 3600c14ff0eSRobert Watson * Given a file path, set an ACL for it. 36191f37dcbSRobert Watson */ 36291f37dcbSRobert Watson int 3638451d0ddSKip Macy sys___acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 36491f37dcbSRobert Watson { 36591f37dcbSRobert Watson struct nameidata nd; 3665050aa86SKonstantin Belousov int error; 36791f37dcbSRobert Watson 3685050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 36991f37dcbSRobert Watson error = namei(&nd); 370f708f4d1SMatthew Dillon if (error == 0) { 371f97182acSAlfred Perlstein error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 37291f37dcbSRobert Watson NDFREE(&nd, 0); 373f708f4d1SMatthew Dillon } 37491f37dcbSRobert Watson return (error); 37591f37dcbSRobert Watson } 37691f37dcbSRobert Watson 37791f37dcbSRobert Watson /* 3783c67c23bSRobert Watson * Given a file path, set an ACL for it; don't follow links. 3793c67c23bSRobert Watson */ 3803c67c23bSRobert Watson int 3818451d0ddSKip Macy sys___acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 3823c67c23bSRobert Watson { 3833c67c23bSRobert Watson struct nameidata nd; 3845050aa86SKonstantin Belousov int error; 3853c67c23bSRobert Watson 3865050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 3873c67c23bSRobert Watson error = namei(&nd); 3883c67c23bSRobert Watson if (error == 0) { 3893c67c23bSRobert Watson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 3903c67c23bSRobert Watson NDFREE(&nd, 0); 3913c67c23bSRobert Watson } 3923c67c23bSRobert Watson return (error); 3933c67c23bSRobert Watson } 3943c67c23bSRobert Watson 3953c67c23bSRobert Watson /* 396b5368498SRobert Watson * Given a file descriptor, get an ACL for it. 39791f37dcbSRobert Watson */ 39891f37dcbSRobert Watson int 3998451d0ddSKip Macy sys___acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 40091f37dcbSRobert Watson { 40191f37dcbSRobert Watson struct file *fp; 4025050aa86SKonstantin Belousov int error; 40391f37dcbSRobert Watson 404a9d2f8d8SRobert Watson error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_GET, &fp); 405f708f4d1SMatthew Dillon if (error == 0) { 4063b6d9652SPoul-Henning Kamp error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 407426da3bcSAlfred Perlstein fdrop(fp, td); 408f708f4d1SMatthew Dillon } 40991f37dcbSRobert Watson return (error); 41091f37dcbSRobert Watson } 41191f37dcbSRobert Watson 41291f37dcbSRobert Watson /* 413b5368498SRobert Watson * Given a file descriptor, set an ACL for it. 41491f37dcbSRobert Watson */ 41591f37dcbSRobert Watson int 4168451d0ddSKip Macy sys___acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 41791f37dcbSRobert Watson { 41891f37dcbSRobert Watson struct file *fp; 4195050aa86SKonstantin Belousov int error; 42091f37dcbSRobert Watson 421a9d2f8d8SRobert Watson error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_SET, &fp); 422f708f4d1SMatthew Dillon if (error == 0) { 4233b6d9652SPoul-Henning Kamp error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 424426da3bcSAlfred Perlstein fdrop(fp, td); 425f708f4d1SMatthew Dillon } 42691f37dcbSRobert Watson return (error); 42791f37dcbSRobert Watson } 42891f37dcbSRobert Watson 42991f37dcbSRobert Watson /* 43091f37dcbSRobert Watson * Given a file path, delete an ACL from it. 43191f37dcbSRobert Watson */ 43291f37dcbSRobert Watson int 4338451d0ddSKip Macy sys___acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 43491f37dcbSRobert Watson { 43591f37dcbSRobert Watson struct nameidata nd; 4365050aa86SKonstantin Belousov int error; 43791f37dcbSRobert Watson 4385050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 43991f37dcbSRobert Watson error = namei(&nd); 440f708f4d1SMatthew Dillon if (error == 0) { 441d1e405c5SAlfred Perlstein error = vacl_delete(td, nd.ni_vp, uap->type); 44291f37dcbSRobert Watson NDFREE(&nd, 0); 443f708f4d1SMatthew Dillon } 44491f37dcbSRobert Watson return (error); 44591f37dcbSRobert Watson } 44691f37dcbSRobert Watson 44791f37dcbSRobert Watson /* 4483c67c23bSRobert Watson * Given a file path, delete an ACL from it; don't follow links. 4493c67c23bSRobert Watson */ 4503c67c23bSRobert Watson int 4518451d0ddSKip Macy sys___acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 4523c67c23bSRobert Watson { 4533c67c23bSRobert Watson struct nameidata nd; 4545050aa86SKonstantin Belousov int error; 4553c67c23bSRobert Watson 4565050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 4573c67c23bSRobert Watson error = namei(&nd); 4583c67c23bSRobert Watson if (error == 0) { 4593c67c23bSRobert Watson error = vacl_delete(td, nd.ni_vp, uap->type); 4603c67c23bSRobert Watson NDFREE(&nd, 0); 4613c67c23bSRobert Watson } 4623c67c23bSRobert Watson return (error); 4633c67c23bSRobert Watson } 4643c67c23bSRobert Watson 4653c67c23bSRobert Watson /* 46691f37dcbSRobert Watson * Given a file path, delete an ACL from it. 46791f37dcbSRobert Watson */ 46891f37dcbSRobert Watson int 4698451d0ddSKip Macy sys___acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 47091f37dcbSRobert Watson { 47191f37dcbSRobert Watson struct file *fp; 4725050aa86SKonstantin Belousov int error; 47391f37dcbSRobert Watson 474a9d2f8d8SRobert Watson error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_DELETE, 475a9d2f8d8SRobert Watson &fp); 476f708f4d1SMatthew Dillon if (error == 0) { 4773b6d9652SPoul-Henning Kamp error = vacl_delete(td, fp->f_vnode, uap->type); 478426da3bcSAlfred Perlstein fdrop(fp, td); 479f708f4d1SMatthew Dillon } 48091f37dcbSRobert Watson return (error); 48191f37dcbSRobert Watson } 48291f37dcbSRobert Watson 48391f37dcbSRobert Watson /* 4840c14ff0eSRobert Watson * Given a file path, check an ACL for it. 48591f37dcbSRobert Watson */ 48691f37dcbSRobert Watson int 4878451d0ddSKip Macy sys___acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 48891f37dcbSRobert Watson { 48991f37dcbSRobert Watson struct nameidata nd; 4905050aa86SKonstantin Belousov int error; 49191f37dcbSRobert Watson 4925050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 49391f37dcbSRobert Watson error = namei(&nd); 494f708f4d1SMatthew Dillon if (error == 0) { 495f97182acSAlfred Perlstein error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 49691f37dcbSRobert Watson NDFREE(&nd, 0); 497f708f4d1SMatthew Dillon } 49891f37dcbSRobert Watson return (error); 49991f37dcbSRobert Watson } 50091f37dcbSRobert Watson 50191f37dcbSRobert Watson /* 5023c67c23bSRobert Watson * Given a file path, check an ACL for it; don't follow links. 5033c67c23bSRobert Watson */ 5043c67c23bSRobert Watson int 5058451d0ddSKip Macy sys___acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 5063c67c23bSRobert Watson { 5077a172809SEdward Tomasz Napierala struct nameidata nd; 5085050aa86SKonstantin Belousov int error; 5093c67c23bSRobert Watson 5105050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 5113c67c23bSRobert Watson error = namei(&nd); 5123c67c23bSRobert Watson if (error == 0) { 5133c67c23bSRobert Watson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 5143c67c23bSRobert Watson NDFREE(&nd, 0); 5153c67c23bSRobert Watson } 5163c67c23bSRobert Watson return (error); 5173c67c23bSRobert Watson } 5183c67c23bSRobert Watson 5193c67c23bSRobert Watson /* 5200c14ff0eSRobert Watson * Given a file descriptor, check an ACL for it. 52191f37dcbSRobert Watson */ 52291f37dcbSRobert Watson int 5238451d0ddSKip Macy sys___acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 52491f37dcbSRobert Watson { 52591f37dcbSRobert Watson struct file *fp; 5265050aa86SKonstantin Belousov int error; 52791f37dcbSRobert Watson 528a9d2f8d8SRobert Watson error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_CHECK, 529a9d2f8d8SRobert Watson &fp); 530f708f4d1SMatthew Dillon if (error == 0) { 5313b6d9652SPoul-Henning Kamp error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 532426da3bcSAlfred Perlstein fdrop(fp, td); 533f708f4d1SMatthew Dillon } 53491f37dcbSRobert Watson return (error); 53591f37dcbSRobert Watson } 536d1dfd921SChristian S.J. Peron 537b998d381SEdward Tomasz Napierala struct acl * 538b998d381SEdward Tomasz Napierala acl_alloc(int flags) 539b998d381SEdward Tomasz Napierala { 540b998d381SEdward Tomasz Napierala struct acl *aclp; 541b998d381SEdward Tomasz Napierala 542e0ee7589SEdward Tomasz Napierala aclp = malloc(sizeof(*aclp), M_ACL, flags); 543ae1add4eSEdward Tomasz Napierala aclp->acl_maxcnt = ACL_MAX_ENTRIES; 544b998d381SEdward Tomasz Napierala 545b998d381SEdward Tomasz Napierala return (aclp); 546b998d381SEdward Tomasz Napierala } 547b998d381SEdward Tomasz Napierala 548b998d381SEdward Tomasz Napierala void 549b998d381SEdward Tomasz Napierala acl_free(struct acl *aclp) 550b998d381SEdward Tomasz Napierala { 551b998d381SEdward Tomasz Napierala 552e0ee7589SEdward Tomasz Napierala free(aclp, M_ACL); 553b998d381SEdward Tomasz Napierala } 554