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> 414a144410SRobert Watson #include <sys/capsicum.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 { 1510a2c94b8SKonstantin Belousov uint32_t am; 152ae1add4eSEdward Tomasz Napierala int error; 153ae1add4eSEdward Tomasz Napierala struct oldacl old; 154ae1add4eSEdward Tomasz Napierala 155ae1add4eSEdward Tomasz Napierala switch (type) { 156ae1add4eSEdward Tomasz Napierala case ACL_TYPE_ACCESS_OLD: 157ae1add4eSEdward Tomasz Napierala case ACL_TYPE_DEFAULT_OLD: 158ae1add4eSEdward Tomasz Napierala error = acl_copy_acl_into_oldacl(kernel_acl, &old); 159ae1add4eSEdward Tomasz Napierala if (error != 0) 160ae1add4eSEdward Tomasz Napierala break; 161ae1add4eSEdward Tomasz Napierala 162ae1add4eSEdward Tomasz Napierala error = copyout(&old, user_acl, sizeof(old)); 163ae1add4eSEdward Tomasz Napierala break; 164ae1add4eSEdward Tomasz Napierala 165ae1add4eSEdward Tomasz Napierala default: 1660a2c94b8SKonstantin Belousov error = fueword32((char *)user_acl + 1670a2c94b8SKonstantin Belousov offsetof(struct acl, acl_maxcnt), &am); 1680a2c94b8SKonstantin Belousov if (error == -1) 1690a2c94b8SKonstantin Belousov return (EFAULT); 1700a2c94b8SKonstantin Belousov if (am != ACL_MAX_ENTRIES) 171ae1add4eSEdward Tomasz Napierala return (EINVAL); 172ae1add4eSEdward Tomasz Napierala 173ae1add4eSEdward Tomasz Napierala error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl)); 174ae1add4eSEdward Tomasz Napierala } 175ae1add4eSEdward Tomasz Napierala 176ae1add4eSEdward Tomasz Napierala return (error); 177ae1add4eSEdward Tomasz Napierala } 178ae1add4eSEdward Tomasz Napierala 179ae1add4eSEdward Tomasz Napierala /* 180ae1add4eSEdward Tomasz Napierala * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" 1816bb58cddSEdward Tomasz Napierala * counterpart. It's required for old (pre-NFSv4 ACLs) libc to work 182ae1add4eSEdward Tomasz Napierala * with new kernel. Fixing 'type' for old binaries with new libc 183ae1add4eSEdward Tomasz Napierala * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold(). 184ae1add4eSEdward Tomasz Napierala */ 185ae1add4eSEdward Tomasz Napierala static int 186ae1add4eSEdward Tomasz Napierala acl_type_unold(int type) 187ae1add4eSEdward Tomasz Napierala { 188ae1add4eSEdward Tomasz Napierala switch (type) { 189ae1add4eSEdward Tomasz Napierala case ACL_TYPE_ACCESS_OLD: 190ae1add4eSEdward Tomasz Napierala return (ACL_TYPE_ACCESS); 191ae1add4eSEdward Tomasz Napierala 192ae1add4eSEdward Tomasz Napierala case ACL_TYPE_DEFAULT_OLD: 193ae1add4eSEdward Tomasz Napierala return (ACL_TYPE_DEFAULT); 194ae1add4eSEdward Tomasz Napierala 195ae1add4eSEdward Tomasz Napierala default: 196ae1add4eSEdward Tomasz Napierala return (type); 197ae1add4eSEdward Tomasz Napierala } 198ae1add4eSEdward Tomasz Napierala } 199ae1add4eSEdward Tomasz Napierala 20091f37dcbSRobert Watson /* 201b0c521e2SRobert Watson * These calls wrap the real vnode operations, and are called by the syscall 202b0c521e2SRobert Watson * code once the syscall has converted the path or file descriptor to a vnode 203b0c521e2SRobert Watson * (unlocked). The aclp pointer is assumed still to point to userland, so 204b0c521e2SRobert Watson * this should not be consumed within the kernel except by syscall code. 205b0c521e2SRobert Watson * Other code should directly invoke VOP_{SET,GET}ACL. 20691f37dcbSRobert Watson */ 20791f37dcbSRobert Watson 20891f37dcbSRobert Watson /* 20991f37dcbSRobert Watson * Given a vnode, set its ACL. 21091f37dcbSRobert Watson */ 21191f37dcbSRobert Watson static int 212b40ce416SJulian Elischer vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 21391f37dcbSRobert Watson struct acl *aclp) 21491f37dcbSRobert Watson { 215b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 2164e1123c7SRobert Watson struct mount *mp; 21791f37dcbSRobert Watson int error; 21891f37dcbSRobert Watson 219b998d381SEdward Tomasz Napierala inkernelacl = acl_alloc(M_WAITOK); 220ae1add4eSEdward Tomasz Napierala error = acl_copyin(aclp, inkernelacl, type); 221da9ce28eSEdward Tomasz Napierala if (error != 0) 222b998d381SEdward Tomasz Napierala goto out; 2234e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 2244e1123c7SRobert Watson if (error != 0) 225b998d381SEdward Tomasz Napierala goto out; 226cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 227c86ca022SRobert Watson #ifdef MAC 228b998d381SEdward Tomasz Napierala error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 229c86ca022SRobert Watson if (error != 0) 230b998d381SEdward Tomasz Napierala goto out_unlock; 231c86ca022SRobert Watson #endif 232ae1add4eSEdward Tomasz Napierala error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, 233ae1add4eSEdward Tomasz Napierala td->td_ucred, td); 234c86ca022SRobert Watson #ifdef MAC 235b998d381SEdward Tomasz Napierala out_unlock: 236c86ca022SRobert Watson #endif 23722db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 2384e1123c7SRobert Watson vn_finished_write(mp); 239b998d381SEdward Tomasz Napierala out: 240b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 24191f37dcbSRobert Watson return (error); 24291f37dcbSRobert Watson } 24391f37dcbSRobert Watson 24491f37dcbSRobert Watson /* 24591f37dcbSRobert Watson * Given a vnode, get its ACL. 24691f37dcbSRobert Watson */ 24791f37dcbSRobert Watson static int 248b40ce416SJulian Elischer vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type, 24991f37dcbSRobert Watson struct acl *aclp) 25091f37dcbSRobert Watson { 251b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 25291f37dcbSRobert Watson int error; 25391f37dcbSRobert Watson 25423c053d6SSergey Kandaurov inkernelacl = acl_alloc(M_WAITOK | M_ZERO); 255cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 256c86ca022SRobert Watson #ifdef MAC 25730d239bcSRobert Watson error = mac_vnode_check_getacl(td->td_ucred, vp, type); 258c86ca022SRobert Watson if (error != 0) 259c86ca022SRobert Watson goto out; 260c86ca022SRobert Watson #endif 261ae1add4eSEdward Tomasz Napierala error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, 262ae1add4eSEdward Tomasz Napierala td->td_ucred, td); 263ae1add4eSEdward Tomasz Napierala 264c86ca022SRobert Watson #ifdef MAC 265c86ca022SRobert Watson out: 266c86ca022SRobert Watson #endif 26722db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 26891f37dcbSRobert Watson if (error == 0) 269ae1add4eSEdward Tomasz Napierala error = acl_copyout(inkernelacl, aclp, type); 270b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 27191f37dcbSRobert Watson return (error); 27291f37dcbSRobert Watson } 27391f37dcbSRobert Watson 27491f37dcbSRobert Watson /* 27591f37dcbSRobert Watson * Given a vnode, delete its ACL. 27691f37dcbSRobert Watson */ 27791f37dcbSRobert Watson static int 278b40ce416SJulian Elischer vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type) 27991f37dcbSRobert Watson { 2804e1123c7SRobert Watson struct mount *mp; 28191f37dcbSRobert Watson int error; 28291f37dcbSRobert Watson 2834e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 284da9ce28eSEdward Tomasz Napierala if (error != 0) 2854e1123c7SRobert Watson return (error); 286cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 287c86ca022SRobert Watson #ifdef MAC 28830d239bcSRobert Watson error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 289da9ce28eSEdward Tomasz Napierala if (error != 0) 290c86ca022SRobert Watson goto out; 291c86ca022SRobert Watson #endif 292ae1add4eSEdward Tomasz Napierala error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td); 293c86ca022SRobert Watson #ifdef MAC 294c86ca022SRobert Watson out: 295c86ca022SRobert Watson #endif 29622db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 2974e1123c7SRobert Watson vn_finished_write(mp); 29891f37dcbSRobert Watson return (error); 29991f37dcbSRobert Watson } 30091f37dcbSRobert Watson 30191f37dcbSRobert Watson /* 30291f37dcbSRobert Watson * Given a vnode, check whether an ACL is appropriate for it 30391f37dcbSRobert Watson */ 30491f37dcbSRobert Watson static int 305b40ce416SJulian Elischer vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 30691f37dcbSRobert Watson struct acl *aclp) 30791f37dcbSRobert Watson { 308b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 30991f37dcbSRobert Watson int error; 31091f37dcbSRobert Watson 311b998d381SEdward Tomasz Napierala inkernelacl = acl_alloc(M_WAITOK); 312ae1add4eSEdward Tomasz Napierala error = acl_copyin(aclp, inkernelacl, type); 313da9ce28eSEdward Tomasz Napierala if (error != 0) 314b998d381SEdward Tomasz Napierala goto out; 3156bb58cddSEdward Tomasz Napierala error = VOP_ACLCHECK(vp, acl_type_unold(type), inkernelacl, 3166bb58cddSEdward Tomasz Napierala td->td_ucred, td); 317b998d381SEdward Tomasz Napierala out: 318b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 31991f37dcbSRobert Watson return (error); 32091f37dcbSRobert Watson } 32191f37dcbSRobert Watson 32291f37dcbSRobert Watson /* 323b0c521e2SRobert Watson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't 324b0c521e2SRobert Watson * need to lock, as the vacl_ code will get/release any locks required. 32591f37dcbSRobert Watson */ 32691f37dcbSRobert Watson 32791f37dcbSRobert Watson /* 32891f37dcbSRobert Watson * Given a file path, get an ACL for it 32991f37dcbSRobert Watson */ 33091f37dcbSRobert Watson int 3318451d0ddSKip Macy sys___acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 33291f37dcbSRobert Watson { 33391f37dcbSRobert Watson struct nameidata nd; 3345050aa86SKonstantin Belousov int error; 33591f37dcbSRobert Watson 3365050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 33791f37dcbSRobert Watson error = namei(&nd); 338f708f4d1SMatthew Dillon if (error == 0) { 339f97182acSAlfred Perlstein error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 34091f37dcbSRobert Watson NDFREE(&nd, 0); 341f708f4d1SMatthew Dillon } 34291f37dcbSRobert Watson return (error); 34391f37dcbSRobert Watson } 34491f37dcbSRobert Watson 34591f37dcbSRobert Watson /* 3463c67c23bSRobert Watson * Given a file path, get an ACL for it; don't follow links. 3473c67c23bSRobert Watson */ 3483c67c23bSRobert Watson int 3498451d0ddSKip Macy sys___acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 3503c67c23bSRobert Watson { 3513c67c23bSRobert Watson struct nameidata nd; 3525050aa86SKonstantin Belousov int error; 3533c67c23bSRobert Watson 3545050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 3553c67c23bSRobert Watson error = namei(&nd); 3563c67c23bSRobert Watson if (error == 0) { 3573c67c23bSRobert Watson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 3583c67c23bSRobert Watson NDFREE(&nd, 0); 3593c67c23bSRobert Watson } 3603c67c23bSRobert Watson return (error); 3613c67c23bSRobert Watson } 3623c67c23bSRobert Watson 3633c67c23bSRobert Watson /* 3640c14ff0eSRobert Watson * Given a file path, set an ACL for it. 36591f37dcbSRobert Watson */ 36691f37dcbSRobert Watson int 3678451d0ddSKip Macy sys___acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 36891f37dcbSRobert Watson { 36991f37dcbSRobert Watson struct nameidata nd; 3705050aa86SKonstantin Belousov int error; 37191f37dcbSRobert Watson 3725050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 37391f37dcbSRobert Watson error = namei(&nd); 374f708f4d1SMatthew Dillon if (error == 0) { 375f97182acSAlfred Perlstein error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 37691f37dcbSRobert Watson NDFREE(&nd, 0); 377f708f4d1SMatthew Dillon } 37891f37dcbSRobert Watson return (error); 37991f37dcbSRobert Watson } 38091f37dcbSRobert Watson 38191f37dcbSRobert Watson /* 3823c67c23bSRobert Watson * Given a file path, set an ACL for it; don't follow links. 3833c67c23bSRobert Watson */ 3843c67c23bSRobert Watson int 3858451d0ddSKip Macy sys___acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 3863c67c23bSRobert Watson { 3873c67c23bSRobert Watson struct nameidata nd; 3885050aa86SKonstantin Belousov int error; 3893c67c23bSRobert Watson 3905050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 3913c67c23bSRobert Watson error = namei(&nd); 3923c67c23bSRobert Watson if (error == 0) { 3933c67c23bSRobert Watson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 3943c67c23bSRobert Watson NDFREE(&nd, 0); 3953c67c23bSRobert Watson } 3963c67c23bSRobert Watson return (error); 3973c67c23bSRobert Watson } 3983c67c23bSRobert Watson 3993c67c23bSRobert Watson /* 400b5368498SRobert Watson * Given a file descriptor, get an ACL for it. 40191f37dcbSRobert Watson */ 40291f37dcbSRobert Watson int 4038451d0ddSKip Macy sys___acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 40491f37dcbSRobert Watson { 40591f37dcbSRobert Watson struct file *fp; 4067008be5bSPawel Jakub Dawidek cap_rights_t rights; 4075050aa86SKonstantin Belousov int error; 40891f37dcbSRobert Watson 4097008be5bSPawel Jakub Dawidek error = getvnode(td->td_proc->p_fd, uap->filedes, 4107008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_ACL_GET), &fp); 411f708f4d1SMatthew Dillon if (error == 0) { 4123b6d9652SPoul-Henning Kamp error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 413426da3bcSAlfred Perlstein fdrop(fp, td); 414f708f4d1SMatthew Dillon } 41591f37dcbSRobert Watson return (error); 41691f37dcbSRobert Watson } 41791f37dcbSRobert Watson 41891f37dcbSRobert Watson /* 419b5368498SRobert Watson * Given a file descriptor, set an ACL for it. 42091f37dcbSRobert Watson */ 42191f37dcbSRobert Watson int 4228451d0ddSKip Macy sys___acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 42391f37dcbSRobert Watson { 42491f37dcbSRobert Watson struct file *fp; 4257008be5bSPawel Jakub Dawidek cap_rights_t rights; 4265050aa86SKonstantin Belousov int error; 42791f37dcbSRobert Watson 4287008be5bSPawel Jakub Dawidek error = getvnode(td->td_proc->p_fd, uap->filedes, 4297008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_ACL_SET), &fp); 430f708f4d1SMatthew Dillon if (error == 0) { 4313b6d9652SPoul-Henning Kamp error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 432426da3bcSAlfred Perlstein fdrop(fp, td); 433f708f4d1SMatthew Dillon } 43491f37dcbSRobert Watson return (error); 43591f37dcbSRobert Watson } 43691f37dcbSRobert Watson 43791f37dcbSRobert Watson /* 43891f37dcbSRobert Watson * Given a file path, delete an ACL from it. 43991f37dcbSRobert Watson */ 44091f37dcbSRobert Watson int 4418451d0ddSKip Macy sys___acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 44291f37dcbSRobert Watson { 44391f37dcbSRobert Watson struct nameidata nd; 4445050aa86SKonstantin Belousov int error; 44591f37dcbSRobert Watson 4465050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 44791f37dcbSRobert Watson error = namei(&nd); 448f708f4d1SMatthew Dillon if (error == 0) { 449d1e405c5SAlfred Perlstein error = vacl_delete(td, nd.ni_vp, uap->type); 45091f37dcbSRobert Watson NDFREE(&nd, 0); 451f708f4d1SMatthew Dillon } 45291f37dcbSRobert Watson return (error); 45391f37dcbSRobert Watson } 45491f37dcbSRobert Watson 45591f37dcbSRobert Watson /* 4563c67c23bSRobert Watson * Given a file path, delete an ACL from it; don't follow links. 4573c67c23bSRobert Watson */ 4583c67c23bSRobert Watson int 4598451d0ddSKip Macy sys___acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 4603c67c23bSRobert Watson { 4613c67c23bSRobert Watson struct nameidata nd; 4625050aa86SKonstantin Belousov int error; 4633c67c23bSRobert Watson 4645050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 4653c67c23bSRobert Watson error = namei(&nd); 4663c67c23bSRobert Watson if (error == 0) { 4673c67c23bSRobert Watson error = vacl_delete(td, nd.ni_vp, uap->type); 4683c67c23bSRobert Watson NDFREE(&nd, 0); 4693c67c23bSRobert Watson } 4703c67c23bSRobert Watson return (error); 4713c67c23bSRobert Watson } 4723c67c23bSRobert Watson 4733c67c23bSRobert Watson /* 47491f37dcbSRobert Watson * Given a file path, delete an ACL from it. 47591f37dcbSRobert Watson */ 47691f37dcbSRobert Watson int 4778451d0ddSKip Macy sys___acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 47891f37dcbSRobert Watson { 47991f37dcbSRobert Watson struct file *fp; 4807008be5bSPawel Jakub Dawidek cap_rights_t rights; 4815050aa86SKonstantin Belousov int error; 48291f37dcbSRobert Watson 4837008be5bSPawel Jakub Dawidek error = getvnode(td->td_proc->p_fd, uap->filedes, 4847008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_ACL_DELETE), &fp); 485f708f4d1SMatthew Dillon if (error == 0) { 4863b6d9652SPoul-Henning Kamp error = vacl_delete(td, fp->f_vnode, uap->type); 487426da3bcSAlfred Perlstein fdrop(fp, td); 488f708f4d1SMatthew Dillon } 48991f37dcbSRobert Watson return (error); 49091f37dcbSRobert Watson } 49191f37dcbSRobert Watson 49291f37dcbSRobert Watson /* 4930c14ff0eSRobert Watson * Given a file path, check an ACL for it. 49491f37dcbSRobert Watson */ 49591f37dcbSRobert Watson int 4968451d0ddSKip Macy sys___acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 49791f37dcbSRobert Watson { 49891f37dcbSRobert Watson struct nameidata nd; 4995050aa86SKonstantin Belousov int error; 50091f37dcbSRobert Watson 5015050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 50291f37dcbSRobert Watson error = namei(&nd); 503f708f4d1SMatthew Dillon if (error == 0) { 504f97182acSAlfred Perlstein error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 50591f37dcbSRobert Watson NDFREE(&nd, 0); 506f708f4d1SMatthew Dillon } 50791f37dcbSRobert Watson return (error); 50891f37dcbSRobert Watson } 50991f37dcbSRobert Watson 51091f37dcbSRobert Watson /* 5113c67c23bSRobert Watson * Given a file path, check an ACL for it; don't follow links. 5123c67c23bSRobert Watson */ 5133c67c23bSRobert Watson int 5148451d0ddSKip Macy sys___acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 5153c67c23bSRobert Watson { 5167a172809SEdward Tomasz Napierala struct nameidata nd; 5175050aa86SKonstantin Belousov int error; 5183c67c23bSRobert Watson 5195050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 5203c67c23bSRobert Watson error = namei(&nd); 5213c67c23bSRobert Watson if (error == 0) { 5223c67c23bSRobert Watson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 5233c67c23bSRobert Watson NDFREE(&nd, 0); 5243c67c23bSRobert Watson } 5253c67c23bSRobert Watson return (error); 5263c67c23bSRobert Watson } 5273c67c23bSRobert Watson 5283c67c23bSRobert Watson /* 5290c14ff0eSRobert Watson * Given a file descriptor, check an ACL for it. 53091f37dcbSRobert Watson */ 53191f37dcbSRobert Watson int 5328451d0ddSKip Macy sys___acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 53391f37dcbSRobert Watson { 53491f37dcbSRobert Watson struct file *fp; 5357008be5bSPawel Jakub Dawidek cap_rights_t rights; 5365050aa86SKonstantin Belousov int error; 53791f37dcbSRobert Watson 5387008be5bSPawel Jakub Dawidek error = getvnode(td->td_proc->p_fd, uap->filedes, 5397008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_ACL_CHECK), &fp); 540f708f4d1SMatthew Dillon if (error == 0) { 5413b6d9652SPoul-Henning Kamp error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 542426da3bcSAlfred Perlstein fdrop(fp, td); 543f708f4d1SMatthew Dillon } 54491f37dcbSRobert Watson return (error); 54591f37dcbSRobert Watson } 546d1dfd921SChristian S.J. Peron 547b998d381SEdward Tomasz Napierala struct acl * 548b998d381SEdward Tomasz Napierala acl_alloc(int flags) 549b998d381SEdward Tomasz Napierala { 550b998d381SEdward Tomasz Napierala struct acl *aclp; 551b998d381SEdward Tomasz Napierala 552e0ee7589SEdward Tomasz Napierala aclp = malloc(sizeof(*aclp), M_ACL, flags); 5538ddc3590SEdward Tomasz Napierala if (aclp == NULL) 5548ddc3590SEdward Tomasz Napierala return (NULL); 5558ddc3590SEdward Tomasz Napierala 556ae1add4eSEdward Tomasz Napierala aclp->acl_maxcnt = ACL_MAX_ENTRIES; 557b998d381SEdward Tomasz Napierala 558b998d381SEdward Tomasz Napierala return (aclp); 559b998d381SEdward Tomasz Napierala } 560b998d381SEdward Tomasz Napierala 561b998d381SEdward Tomasz Napierala void 562b998d381SEdward Tomasz Napierala acl_free(struct acl *aclp) 563b998d381SEdward Tomasz Napierala { 564b998d381SEdward Tomasz Napierala 565e0ee7589SEdward Tomasz Napierala free(aclp, M_ACL); 566b998d381SEdward Tomasz Napierala } 567