191f37dcbSRobert Watson /*- 2*8a36da99SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*8a36da99SPedro F. Giffuni * 4f9070809SRobert Watson * Copyright (c) 1999-2006, 2016-2017 Robert N. M. Watson 591f37dcbSRobert Watson * All rights reserved. 691f37dcbSRobert Watson * 76d878543SRobert Watson * This software was developed by Robert Watson for the TrustedBSD Project. 86d878543SRobert Watson * 9f9070809SRobert Watson * Portions of this software were developed by BAE Systems, the University of 10f9070809SRobert Watson * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL 11f9070809SRobert Watson * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent 12f9070809SRobert Watson * Computing (TC) research program. 13f9070809SRobert Watson * 1491f37dcbSRobert Watson * Redistribution and use in source and binary forms, with or without 1591f37dcbSRobert Watson * modification, are permitted provided that the following conditions 1691f37dcbSRobert Watson * are met: 1791f37dcbSRobert Watson * 1. Redistributions of source code must retain the above copyright 1891f37dcbSRobert Watson * notice, this list of conditions and the following disclaimer. 1991f37dcbSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 2091f37dcbSRobert Watson * notice, this list of conditions and the following disclaimer in the 2191f37dcbSRobert Watson * documentation and/or other materials provided with the distribution. 2291f37dcbSRobert Watson * 2391f37dcbSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2491f37dcbSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2591f37dcbSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2691f37dcbSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2791f37dcbSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2891f37dcbSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2991f37dcbSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3091f37dcbSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3191f37dcbSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3291f37dcbSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3391f37dcbSRobert Watson * SUCH DAMAGE. 3491f37dcbSRobert Watson */ 3591f37dcbSRobert Watson /* 365293465fSRobert Watson * Developed by the TrustedBSD Project. 37e4256d1eSRobert Watson * 38e4256d1eSRobert Watson * ACL system calls and other functions common across different ACL types. 39e4256d1eSRobert Watson * Type-specific routines go into subr_acl_<type>.c. 4091f37dcbSRobert Watson */ 4191f37dcbSRobert Watson 42677b542eSDavid E. O'Brien #include <sys/cdefs.h> 43677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 44677b542eSDavid E. O'Brien 4591f37dcbSRobert Watson #include <sys/param.h> 4691f37dcbSRobert Watson #include <sys/systm.h> 4791f37dcbSRobert Watson #include <sys/sysproto.h> 484a144410SRobert Watson #include <sys/capsicum.h> 4957b4252eSKonstantin Belousov #include <sys/fcntl.h> 5091f37dcbSRobert Watson #include <sys/kernel.h> 5191f37dcbSRobert Watson #include <sys/malloc.h> 5242e7197fSChristian S.J. Peron #include <sys/mount.h> 5391f37dcbSRobert Watson #include <sys/vnode.h> 5491f37dcbSRobert Watson #include <sys/lock.h> 55f708f4d1SMatthew Dillon #include <sys/mutex.h> 5691f37dcbSRobert Watson #include <sys/namei.h> 5791f37dcbSRobert Watson #include <sys/file.h> 5813438f68SAlfred Perlstein #include <sys/filedesc.h> 5991f37dcbSRobert Watson #include <sys/proc.h> 6091f37dcbSRobert Watson #include <sys/sysent.h> 6191f37dcbSRobert Watson #include <sys/acl.h> 6291f37dcbSRobert Watson 63f9070809SRobert Watson #include <security/audit/audit.h> 64aed55708SRobert Watson #include <security/mac/mac_framework.h> 65aed55708SRobert Watson 66ae1add4eSEdward Tomasz Napierala CTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES); 67ae1add4eSEdward Tomasz Napierala 68ae1add4eSEdward Tomasz Napierala MALLOC_DEFINE(M_ACL, "acl", "Access Control Lists"); 6991f37dcbSRobert Watson 70cbeb8402SRobert Watson static int vacl_set_acl(struct thread *td, struct vnode *vp, 71cbeb8402SRobert Watson acl_type_t type, struct acl *aclp); 72cbeb8402SRobert Watson static int vacl_get_acl(struct thread *td, struct vnode *vp, 73cbeb8402SRobert Watson acl_type_t type, struct acl *aclp); 74b40ce416SJulian Elischer static int vacl_aclcheck(struct thread *td, struct vnode *vp, 75b114e127SRobert Watson acl_type_t type, struct acl *aclp); 7691f37dcbSRobert Watson 77ae1add4eSEdward Tomasz Napierala int 78ae1add4eSEdward Tomasz Napierala acl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest) 79ae1add4eSEdward Tomasz Napierala { 80ae1add4eSEdward Tomasz Napierala int i; 81ae1add4eSEdward Tomasz Napierala 82ae1add4eSEdward Tomasz Napierala if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES) 83ae1add4eSEdward Tomasz Napierala return (EINVAL); 84ae1add4eSEdward Tomasz Napierala 85ae1add4eSEdward Tomasz Napierala bzero(dest, sizeof(*dest)); 86ae1add4eSEdward Tomasz Napierala 87ae1add4eSEdward Tomasz Napierala dest->acl_cnt = source->acl_cnt; 88ae1add4eSEdward Tomasz Napierala dest->acl_maxcnt = ACL_MAX_ENTRIES; 89ae1add4eSEdward Tomasz Napierala 90ae1add4eSEdward Tomasz Napierala for (i = 0; i < dest->acl_cnt; i++) { 91ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 92ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 93ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 94ae1add4eSEdward Tomasz Napierala } 95ae1add4eSEdward Tomasz Napierala 96ae1add4eSEdward Tomasz Napierala return (0); 97ae1add4eSEdward Tomasz Napierala } 98ae1add4eSEdward Tomasz Napierala 99ae1add4eSEdward Tomasz Napierala int 100ae1add4eSEdward Tomasz Napierala acl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest) 101ae1add4eSEdward Tomasz Napierala { 102ae1add4eSEdward Tomasz Napierala int i; 103ae1add4eSEdward Tomasz Napierala 104ce9d79aaSEdward Tomasz Napierala if (source->acl_cnt > OLDACL_MAX_ENTRIES) 105ae1add4eSEdward Tomasz Napierala return (EINVAL); 106ae1add4eSEdward Tomasz Napierala 107ae1add4eSEdward Tomasz Napierala bzero(dest, sizeof(*dest)); 108ae1add4eSEdward Tomasz Napierala 109ae1add4eSEdward Tomasz Napierala dest->acl_cnt = source->acl_cnt; 110ae1add4eSEdward Tomasz Napierala 111ae1add4eSEdward Tomasz Napierala for (i = 0; i < dest->acl_cnt; i++) { 112ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 113ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 114ae1add4eSEdward Tomasz Napierala dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 115ae1add4eSEdward Tomasz Napierala } 116ae1add4eSEdward Tomasz Napierala 117ae1add4eSEdward Tomasz Napierala return (0); 118ae1add4eSEdward Tomasz Napierala } 119ae1add4eSEdward Tomasz Napierala 120ae1add4eSEdward Tomasz Napierala /* 121ae1add4eSEdward Tomasz Napierala * At one time, "struct ACL" was extended in order to add support for NFSv4 122ae1add4eSEdward Tomasz Napierala * ACLs. Instead of creating compatibility versions of all the ACL-related 123ae1add4eSEdward Tomasz Napierala * syscalls, they were left intact. It's possible to find out what the code 124ae1add4eSEdward Tomasz Napierala * calling these syscalls (libc) expects basing on "type" argument - if it's 125ae1add4eSEdward Tomasz Napierala * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were 126ae1add4eSEdward Tomasz Napierala * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct 127ae1add4eSEdward Tomasz Napierala * oldacl". If it's something else, then it's the new "struct acl". In the 128ae1add4eSEdward Tomasz Napierala * latter case, the routines below just copyin/copyout the contents. In the 129ae1add4eSEdward Tomasz Napierala * former case, they copyin the "struct oldacl" and convert it to the new 130ae1add4eSEdward Tomasz Napierala * format. 131ae1add4eSEdward Tomasz Napierala */ 132ae1add4eSEdward Tomasz Napierala static int 133ae1add4eSEdward Tomasz Napierala acl_copyin(void *user_acl, struct acl *kernel_acl, acl_type_t type) 134ae1add4eSEdward Tomasz Napierala { 135ae1add4eSEdward Tomasz Napierala int error; 136ae1add4eSEdward Tomasz Napierala struct oldacl old; 137ae1add4eSEdward Tomasz Napierala 138ae1add4eSEdward Tomasz Napierala switch (type) { 139ae1add4eSEdward Tomasz Napierala case ACL_TYPE_ACCESS_OLD: 140ae1add4eSEdward Tomasz Napierala case ACL_TYPE_DEFAULT_OLD: 141ae1add4eSEdward Tomasz Napierala error = copyin(user_acl, &old, sizeof(old)); 142ae1add4eSEdward Tomasz Napierala if (error != 0) 143ae1add4eSEdward Tomasz Napierala break; 144ae1add4eSEdward Tomasz Napierala acl_copy_oldacl_into_acl(&old, kernel_acl); 145ae1add4eSEdward Tomasz Napierala break; 146ae1add4eSEdward Tomasz Napierala 147ae1add4eSEdward Tomasz Napierala default: 148ae1add4eSEdward Tomasz Napierala error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl)); 149ae1add4eSEdward Tomasz Napierala if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES) 150ae1add4eSEdward Tomasz Napierala return (EINVAL); 151ae1add4eSEdward Tomasz Napierala } 152ae1add4eSEdward Tomasz Napierala 153ae1add4eSEdward Tomasz Napierala return (error); 154ae1add4eSEdward Tomasz Napierala } 155ae1add4eSEdward Tomasz Napierala 156ae1add4eSEdward Tomasz Napierala static int 157ae1add4eSEdward Tomasz Napierala acl_copyout(struct acl *kernel_acl, void *user_acl, acl_type_t type) 158ae1add4eSEdward Tomasz Napierala { 1590a2c94b8SKonstantin Belousov uint32_t am; 160ae1add4eSEdward Tomasz Napierala int error; 161ae1add4eSEdward Tomasz Napierala struct oldacl old; 162ae1add4eSEdward Tomasz Napierala 163ae1add4eSEdward Tomasz Napierala switch (type) { 164ae1add4eSEdward Tomasz Napierala case ACL_TYPE_ACCESS_OLD: 165ae1add4eSEdward Tomasz Napierala case ACL_TYPE_DEFAULT_OLD: 166ae1add4eSEdward Tomasz Napierala error = acl_copy_acl_into_oldacl(kernel_acl, &old); 167ae1add4eSEdward Tomasz Napierala if (error != 0) 168ae1add4eSEdward Tomasz Napierala break; 169ae1add4eSEdward Tomasz Napierala 170ae1add4eSEdward Tomasz Napierala error = copyout(&old, user_acl, sizeof(old)); 171ae1add4eSEdward Tomasz Napierala break; 172ae1add4eSEdward Tomasz Napierala 173ae1add4eSEdward Tomasz Napierala default: 1740a2c94b8SKonstantin Belousov error = fueword32((char *)user_acl + 1750a2c94b8SKonstantin Belousov offsetof(struct acl, acl_maxcnt), &am); 1760a2c94b8SKonstantin Belousov if (error == -1) 1770a2c94b8SKonstantin Belousov return (EFAULT); 1780a2c94b8SKonstantin Belousov if (am != ACL_MAX_ENTRIES) 179ae1add4eSEdward Tomasz Napierala return (EINVAL); 180ae1add4eSEdward Tomasz Napierala 181ae1add4eSEdward Tomasz Napierala error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl)); 182ae1add4eSEdward Tomasz Napierala } 183ae1add4eSEdward Tomasz Napierala 184ae1add4eSEdward Tomasz Napierala return (error); 185ae1add4eSEdward Tomasz Napierala } 186ae1add4eSEdward Tomasz Napierala 187ae1add4eSEdward Tomasz Napierala /* 188ae1add4eSEdward Tomasz Napierala * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" 1896bb58cddSEdward Tomasz Napierala * counterpart. It's required for old (pre-NFSv4 ACLs) libc to work 190ae1add4eSEdward Tomasz Napierala * with new kernel. Fixing 'type' for old binaries with new libc 191ae1add4eSEdward Tomasz Napierala * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold(). 192ae1add4eSEdward Tomasz Napierala */ 193ae1add4eSEdward Tomasz Napierala static int 194ae1add4eSEdward Tomasz Napierala acl_type_unold(int type) 195ae1add4eSEdward Tomasz Napierala { 196ae1add4eSEdward Tomasz Napierala switch (type) { 197ae1add4eSEdward Tomasz Napierala case ACL_TYPE_ACCESS_OLD: 198ae1add4eSEdward Tomasz Napierala return (ACL_TYPE_ACCESS); 199ae1add4eSEdward Tomasz Napierala 200ae1add4eSEdward Tomasz Napierala case ACL_TYPE_DEFAULT_OLD: 201ae1add4eSEdward Tomasz Napierala return (ACL_TYPE_DEFAULT); 202ae1add4eSEdward Tomasz Napierala 203ae1add4eSEdward Tomasz Napierala default: 204ae1add4eSEdward Tomasz Napierala return (type); 205ae1add4eSEdward Tomasz Napierala } 206ae1add4eSEdward Tomasz Napierala } 207ae1add4eSEdward Tomasz Napierala 20891f37dcbSRobert Watson /* 209b0c521e2SRobert Watson * These calls wrap the real vnode operations, and are called by the syscall 210b0c521e2SRobert Watson * code once the syscall has converted the path or file descriptor to a vnode 211b0c521e2SRobert Watson * (unlocked). The aclp pointer is assumed still to point to userland, so 212b0c521e2SRobert Watson * this should not be consumed within the kernel except by syscall code. 213b0c521e2SRobert Watson * Other code should directly invoke VOP_{SET,GET}ACL. 21491f37dcbSRobert Watson */ 21591f37dcbSRobert Watson 21691f37dcbSRobert Watson /* 21791f37dcbSRobert Watson * Given a vnode, set its ACL. 21891f37dcbSRobert Watson */ 21991f37dcbSRobert Watson static int 220b40ce416SJulian Elischer vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 22191f37dcbSRobert Watson struct acl *aclp) 22291f37dcbSRobert Watson { 223b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 2244e1123c7SRobert Watson struct mount *mp; 22591f37dcbSRobert Watson int error; 22691f37dcbSRobert Watson 227f9070809SRobert Watson AUDIT_ARG_VALUE(type); 228b998d381SEdward Tomasz Napierala inkernelacl = acl_alloc(M_WAITOK); 229ae1add4eSEdward Tomasz Napierala error = acl_copyin(aclp, inkernelacl, type); 230da9ce28eSEdward Tomasz Napierala if (error != 0) 231b998d381SEdward Tomasz Napierala goto out; 2324e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 2334e1123c7SRobert Watson if (error != 0) 234b998d381SEdward Tomasz Napierala goto out; 235cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 236f9070809SRobert Watson AUDIT_ARG_VNODE1(vp); 237c86ca022SRobert Watson #ifdef MAC 238b998d381SEdward Tomasz Napierala error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 239c86ca022SRobert Watson if (error != 0) 240b998d381SEdward Tomasz Napierala goto out_unlock; 241c86ca022SRobert Watson #endif 242ae1add4eSEdward Tomasz Napierala error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, 243ae1add4eSEdward Tomasz Napierala td->td_ucred, td); 244c86ca022SRobert Watson #ifdef MAC 245b998d381SEdward Tomasz Napierala out_unlock: 246c86ca022SRobert Watson #endif 24722db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 2484e1123c7SRobert Watson vn_finished_write(mp); 249b998d381SEdward Tomasz Napierala out: 250b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 25191f37dcbSRobert Watson return (error); 25291f37dcbSRobert Watson } 25391f37dcbSRobert Watson 25491f37dcbSRobert Watson /* 25591f37dcbSRobert Watson * Given a vnode, get its ACL. 25691f37dcbSRobert Watson */ 25791f37dcbSRobert Watson static int 258b40ce416SJulian Elischer vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type, 25991f37dcbSRobert Watson struct acl *aclp) 26091f37dcbSRobert Watson { 261b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 26291f37dcbSRobert Watson int error; 26391f37dcbSRobert Watson 264f9070809SRobert Watson AUDIT_ARG_VALUE(type); 26523c053d6SSergey Kandaurov inkernelacl = acl_alloc(M_WAITOK | M_ZERO); 266cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 267f9070809SRobert Watson AUDIT_ARG_VNODE1(vp); 268c86ca022SRobert Watson #ifdef MAC 26930d239bcSRobert Watson error = mac_vnode_check_getacl(td->td_ucred, vp, type); 270c86ca022SRobert Watson if (error != 0) 271c86ca022SRobert Watson goto out; 272c86ca022SRobert Watson #endif 273ae1add4eSEdward Tomasz Napierala error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, 274ae1add4eSEdward Tomasz Napierala td->td_ucred, td); 275ae1add4eSEdward Tomasz Napierala 276c86ca022SRobert Watson #ifdef MAC 277c86ca022SRobert Watson out: 278c86ca022SRobert Watson #endif 27922db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 28091f37dcbSRobert Watson if (error == 0) 281ae1add4eSEdward Tomasz Napierala error = acl_copyout(inkernelacl, aclp, type); 282b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 28391f37dcbSRobert Watson return (error); 28491f37dcbSRobert Watson } 28591f37dcbSRobert Watson 28691f37dcbSRobert Watson /* 28791f37dcbSRobert Watson * Given a vnode, delete its ACL. 28891f37dcbSRobert Watson */ 28991f37dcbSRobert Watson static int 290b40ce416SJulian Elischer vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type) 29191f37dcbSRobert Watson { 2924e1123c7SRobert Watson struct mount *mp; 29391f37dcbSRobert Watson int error; 29491f37dcbSRobert Watson 295f9070809SRobert Watson AUDIT_ARG_VALUE(type); 2964e1123c7SRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 297da9ce28eSEdward Tomasz Napierala if (error != 0) 2984e1123c7SRobert Watson return (error); 299cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 300f9070809SRobert Watson AUDIT_ARG_VNODE1(vp); 301c86ca022SRobert Watson #ifdef MAC 30230d239bcSRobert Watson error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 303da9ce28eSEdward Tomasz Napierala if (error != 0) 304c86ca022SRobert Watson goto out; 305c86ca022SRobert Watson #endif 306ae1add4eSEdward Tomasz Napierala error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td); 307c86ca022SRobert Watson #ifdef MAC 308c86ca022SRobert Watson out: 309c86ca022SRobert Watson #endif 31022db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 3114e1123c7SRobert Watson vn_finished_write(mp); 31291f37dcbSRobert Watson return (error); 31391f37dcbSRobert Watson } 31491f37dcbSRobert Watson 31591f37dcbSRobert Watson /* 31691f37dcbSRobert Watson * Given a vnode, check whether an ACL is appropriate for it 317f9070809SRobert Watson * 318f9070809SRobert Watson * XXXRW: No vnode lock held so can't audit vnode state...? 31991f37dcbSRobert Watson */ 32091f37dcbSRobert Watson static int 321b40ce416SJulian Elischer vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 32291f37dcbSRobert Watson struct acl *aclp) 32391f37dcbSRobert Watson { 324b998d381SEdward Tomasz Napierala struct acl *inkernelacl; 32591f37dcbSRobert Watson int error; 32691f37dcbSRobert Watson 327b998d381SEdward Tomasz Napierala inkernelacl = acl_alloc(M_WAITOK); 328ae1add4eSEdward Tomasz Napierala error = acl_copyin(aclp, inkernelacl, type); 329da9ce28eSEdward Tomasz Napierala if (error != 0) 330b998d381SEdward Tomasz Napierala goto out; 3316bb58cddSEdward Tomasz Napierala error = VOP_ACLCHECK(vp, acl_type_unold(type), inkernelacl, 3326bb58cddSEdward Tomasz Napierala td->td_ucred, td); 333b998d381SEdward Tomasz Napierala out: 334b998d381SEdward Tomasz Napierala acl_free(inkernelacl); 33591f37dcbSRobert Watson return (error); 33691f37dcbSRobert Watson } 33791f37dcbSRobert Watson 33891f37dcbSRobert Watson /* 339b0c521e2SRobert Watson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever. Don't 340b0c521e2SRobert Watson * need to lock, as the vacl_ code will get/release any locks required. 34191f37dcbSRobert Watson */ 34291f37dcbSRobert Watson 34391f37dcbSRobert Watson /* 34491f37dcbSRobert Watson * Given a file path, get an ACL for it 34591f37dcbSRobert Watson */ 34691f37dcbSRobert Watson int 3478451d0ddSKip Macy sys___acl_get_file(struct thread *td, struct __acl_get_file_args *uap) 34891f37dcbSRobert Watson { 34991f37dcbSRobert Watson struct nameidata nd; 3505050aa86SKonstantin Belousov int error; 35191f37dcbSRobert Watson 352f9070809SRobert Watson NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, 353f9070809SRobert Watson td); 35491f37dcbSRobert Watson error = namei(&nd); 355f708f4d1SMatthew Dillon if (error == 0) { 356f97182acSAlfred Perlstein error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 35791f37dcbSRobert Watson NDFREE(&nd, 0); 358f708f4d1SMatthew Dillon } 35991f37dcbSRobert Watson return (error); 36091f37dcbSRobert Watson } 36191f37dcbSRobert Watson 36291f37dcbSRobert Watson /* 3633c67c23bSRobert Watson * Given a file path, get an ACL for it; don't follow links. 3643c67c23bSRobert Watson */ 3653c67c23bSRobert Watson int 3668451d0ddSKip Macy sys___acl_get_link(struct thread *td, struct __acl_get_link_args *uap) 3673c67c23bSRobert Watson { 3683c67c23bSRobert Watson struct nameidata nd; 3695050aa86SKonstantin Belousov int error; 3703c67c23bSRobert Watson 371f9070809SRobert Watson NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, 372f9070809SRobert Watson td); 3733c67c23bSRobert Watson error = namei(&nd); 3743c67c23bSRobert Watson if (error == 0) { 3753c67c23bSRobert Watson error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp); 3763c67c23bSRobert Watson NDFREE(&nd, 0); 3773c67c23bSRobert Watson } 3783c67c23bSRobert Watson return (error); 3793c67c23bSRobert Watson } 3803c67c23bSRobert Watson 3813c67c23bSRobert Watson /* 3820c14ff0eSRobert Watson * Given a file path, set an ACL for it. 38391f37dcbSRobert Watson */ 38491f37dcbSRobert Watson int 3858451d0ddSKip Macy sys___acl_set_file(struct thread *td, struct __acl_set_file_args *uap) 38691f37dcbSRobert Watson { 38791f37dcbSRobert Watson struct nameidata nd; 3885050aa86SKonstantin Belousov int error; 38991f37dcbSRobert Watson 390f9070809SRobert Watson NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, 391f9070809SRobert Watson td); 39291f37dcbSRobert Watson error = namei(&nd); 393f708f4d1SMatthew Dillon if (error == 0) { 394f97182acSAlfred Perlstein error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 39591f37dcbSRobert Watson NDFREE(&nd, 0); 396f708f4d1SMatthew Dillon } 39791f37dcbSRobert Watson return (error); 39891f37dcbSRobert Watson } 39991f37dcbSRobert Watson 40091f37dcbSRobert Watson /* 4013c67c23bSRobert Watson * Given a file path, set an ACL for it; don't follow links. 4023c67c23bSRobert Watson */ 4033c67c23bSRobert Watson int 4048451d0ddSKip Macy sys___acl_set_link(struct thread *td, struct __acl_set_link_args *uap) 4053c67c23bSRobert Watson { 4063c67c23bSRobert Watson struct nameidata nd; 4075050aa86SKonstantin Belousov int error; 4083c67c23bSRobert Watson 409f9070809SRobert Watson NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, 410f9070809SRobert Watson td); 4113c67c23bSRobert Watson error = namei(&nd); 4123c67c23bSRobert Watson if (error == 0) { 4133c67c23bSRobert Watson error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp); 4143c67c23bSRobert Watson NDFREE(&nd, 0); 4153c67c23bSRobert Watson } 4163c67c23bSRobert Watson return (error); 4173c67c23bSRobert Watson } 4183c67c23bSRobert Watson 4193c67c23bSRobert Watson /* 420b5368498SRobert Watson * Given a file descriptor, get an ACL for it. 42191f37dcbSRobert Watson */ 42291f37dcbSRobert Watson int 4238451d0ddSKip Macy sys___acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap) 42491f37dcbSRobert Watson { 42591f37dcbSRobert Watson struct file *fp; 4267008be5bSPawel Jakub Dawidek cap_rights_t rights; 4275050aa86SKonstantin Belousov int error; 42891f37dcbSRobert Watson 429f9070809SRobert Watson AUDIT_ARG_FD(uap->filedes); 4304da8456fSMateusz Guzik error = getvnode(td, uap->filedes, 4317008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_ACL_GET), &fp); 432f708f4d1SMatthew Dillon if (error == 0) { 4333b6d9652SPoul-Henning Kamp error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp); 434426da3bcSAlfred Perlstein fdrop(fp, td); 435f708f4d1SMatthew Dillon } 43691f37dcbSRobert Watson return (error); 43791f37dcbSRobert Watson } 43891f37dcbSRobert Watson 43991f37dcbSRobert Watson /* 440b5368498SRobert Watson * Given a file descriptor, set an ACL for it. 44191f37dcbSRobert Watson */ 44291f37dcbSRobert Watson int 4438451d0ddSKip Macy sys___acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap) 44491f37dcbSRobert Watson { 44591f37dcbSRobert Watson struct file *fp; 4467008be5bSPawel Jakub Dawidek cap_rights_t rights; 4475050aa86SKonstantin Belousov int error; 44891f37dcbSRobert Watson 449f9070809SRobert Watson AUDIT_ARG_FD(uap->filedes); 4504da8456fSMateusz Guzik error = getvnode(td, uap->filedes, 4517008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_ACL_SET), &fp); 452f708f4d1SMatthew Dillon if (error == 0) { 4533b6d9652SPoul-Henning Kamp error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp); 454426da3bcSAlfred Perlstein fdrop(fp, td); 455f708f4d1SMatthew Dillon } 45691f37dcbSRobert Watson return (error); 45791f37dcbSRobert Watson } 45891f37dcbSRobert Watson 45991f37dcbSRobert Watson /* 46091f37dcbSRobert Watson * Given a file path, delete an ACL from it. 46191f37dcbSRobert Watson */ 46291f37dcbSRobert Watson int 4638451d0ddSKip Macy sys___acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap) 46491f37dcbSRobert Watson { 46591f37dcbSRobert Watson struct nameidata nd; 4665050aa86SKonstantin Belousov int error; 46791f37dcbSRobert Watson 4685050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 46991f37dcbSRobert Watson error = namei(&nd); 470f708f4d1SMatthew Dillon if (error == 0) { 471d1e405c5SAlfred Perlstein error = vacl_delete(td, nd.ni_vp, uap->type); 47291f37dcbSRobert Watson NDFREE(&nd, 0); 473f708f4d1SMatthew Dillon } 47491f37dcbSRobert Watson return (error); 47591f37dcbSRobert Watson } 47691f37dcbSRobert Watson 47791f37dcbSRobert Watson /* 4783c67c23bSRobert Watson * Given a file path, delete an ACL from it; don't follow links. 4793c67c23bSRobert Watson */ 4803c67c23bSRobert Watson int 4818451d0ddSKip Macy sys___acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap) 4823c67c23bSRobert Watson { 4833c67c23bSRobert Watson struct nameidata nd; 4845050aa86SKonstantin Belousov int error; 4853c67c23bSRobert Watson 4865050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 4873c67c23bSRobert Watson error = namei(&nd); 4883c67c23bSRobert Watson if (error == 0) { 4893c67c23bSRobert Watson error = vacl_delete(td, nd.ni_vp, uap->type); 4903c67c23bSRobert Watson NDFREE(&nd, 0); 4913c67c23bSRobert Watson } 4923c67c23bSRobert Watson return (error); 4933c67c23bSRobert Watson } 4943c67c23bSRobert Watson 4953c67c23bSRobert Watson /* 49691f37dcbSRobert Watson * Given a file path, delete an ACL from it. 49791f37dcbSRobert Watson */ 49891f37dcbSRobert Watson int 4998451d0ddSKip Macy sys___acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap) 50091f37dcbSRobert Watson { 50191f37dcbSRobert Watson struct file *fp; 5027008be5bSPawel Jakub Dawidek cap_rights_t rights; 5035050aa86SKonstantin Belousov int error; 50491f37dcbSRobert Watson 505f9070809SRobert Watson AUDIT_ARG_FD(uap->filedes); 5064da8456fSMateusz Guzik error = getvnode(td, uap->filedes, 5077008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_ACL_DELETE), &fp); 508f708f4d1SMatthew Dillon if (error == 0) { 5093b6d9652SPoul-Henning Kamp error = vacl_delete(td, fp->f_vnode, uap->type); 510426da3bcSAlfred Perlstein fdrop(fp, td); 511f708f4d1SMatthew Dillon } 51291f37dcbSRobert Watson return (error); 51391f37dcbSRobert Watson } 51491f37dcbSRobert Watson 51591f37dcbSRobert Watson /* 5160c14ff0eSRobert Watson * Given a file path, check an ACL for it. 51791f37dcbSRobert Watson */ 51891f37dcbSRobert Watson int 5198451d0ddSKip Macy sys___acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap) 52091f37dcbSRobert Watson { 52191f37dcbSRobert Watson struct nameidata nd; 5225050aa86SKonstantin Belousov int error; 52391f37dcbSRobert Watson 5245050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 52591f37dcbSRobert Watson error = namei(&nd); 526f708f4d1SMatthew Dillon if (error == 0) { 527f97182acSAlfred Perlstein error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 52891f37dcbSRobert Watson NDFREE(&nd, 0); 529f708f4d1SMatthew Dillon } 53091f37dcbSRobert Watson return (error); 53191f37dcbSRobert Watson } 53291f37dcbSRobert Watson 53391f37dcbSRobert Watson /* 5343c67c23bSRobert Watson * Given a file path, check an ACL for it; don't follow links. 5353c67c23bSRobert Watson */ 5363c67c23bSRobert Watson int 5378451d0ddSKip Macy sys___acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap) 5383c67c23bSRobert Watson { 5397a172809SEdward Tomasz Napierala struct nameidata nd; 5405050aa86SKonstantin Belousov int error; 5413c67c23bSRobert Watson 5425050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 5433c67c23bSRobert Watson error = namei(&nd); 5443c67c23bSRobert Watson if (error == 0) { 5453c67c23bSRobert Watson error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp); 5463c67c23bSRobert Watson NDFREE(&nd, 0); 5473c67c23bSRobert Watson } 5483c67c23bSRobert Watson return (error); 5493c67c23bSRobert Watson } 5503c67c23bSRobert Watson 5513c67c23bSRobert Watson /* 5520c14ff0eSRobert Watson * Given a file descriptor, check an ACL for it. 55391f37dcbSRobert Watson */ 55491f37dcbSRobert Watson int 5558451d0ddSKip Macy sys___acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap) 55691f37dcbSRobert Watson { 55791f37dcbSRobert Watson struct file *fp; 5587008be5bSPawel Jakub Dawidek cap_rights_t rights; 5595050aa86SKonstantin Belousov int error; 56091f37dcbSRobert Watson 561f9070809SRobert Watson AUDIT_ARG_FD(uap->filedes); 5624da8456fSMateusz Guzik error = getvnode(td, uap->filedes, 5637008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_ACL_CHECK), &fp); 564f708f4d1SMatthew Dillon if (error == 0) { 5653b6d9652SPoul-Henning Kamp error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp); 566426da3bcSAlfred Perlstein fdrop(fp, td); 567f708f4d1SMatthew Dillon } 56891f37dcbSRobert Watson return (error); 56991f37dcbSRobert Watson } 570d1dfd921SChristian S.J. Peron 571b998d381SEdward Tomasz Napierala struct acl * 572b998d381SEdward Tomasz Napierala acl_alloc(int flags) 573b998d381SEdward Tomasz Napierala { 574b998d381SEdward Tomasz Napierala struct acl *aclp; 575b998d381SEdward Tomasz Napierala 576e0ee7589SEdward Tomasz Napierala aclp = malloc(sizeof(*aclp), M_ACL, flags); 5778ddc3590SEdward Tomasz Napierala if (aclp == NULL) 5788ddc3590SEdward Tomasz Napierala return (NULL); 5798ddc3590SEdward Tomasz Napierala 580ae1add4eSEdward Tomasz Napierala aclp->acl_maxcnt = ACL_MAX_ENTRIES; 581b998d381SEdward Tomasz Napierala 582b998d381SEdward Tomasz Napierala return (aclp); 583b998d381SEdward Tomasz Napierala } 584b998d381SEdward Tomasz Napierala 585b998d381SEdward Tomasz Napierala void 586b998d381SEdward Tomasz Napierala acl_free(struct acl *aclp) 587b998d381SEdward Tomasz Napierala { 588b998d381SEdward Tomasz Napierala 589e0ee7589SEdward Tomasz Napierala free(aclp, M_ACL); 590b998d381SEdward Tomasz Napierala } 591