The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_acl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999-2006 Robert N. M. Watson
    3  * All rights reserved.
    4  *
    5  * This software was developed by Robert Watson for the TrustedBSD Project.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 /*
   29  * Developed by the TrustedBSD Project.
   30  *
   31  * ACL system calls and other functions common across different ACL types.
   32  * Type-specific routines go into subr_acl_<type>.c.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/7.3/sys/kern/vfs_acl.c 180695 2008-07-22 14:27:47Z rwatson $");
   37 
   38 #include "opt_mac.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/sysproto.h>
   43 #include <sys/kernel.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mount.h>
   46 #include <sys/vnode.h>
   47 #include <sys/lock.h>
   48 #include <sys/mutex.h>
   49 #include <sys/namei.h>
   50 #include <sys/file.h>
   51 #include <sys/filedesc.h>
   52 #include <sys/proc.h>
   53 #include <sys/sysent.h>
   54 #include <sys/acl.h>
   55 
   56 #include <security/mac/mac_framework.h>
   57 
   58 #include <vm/uma.h>
   59 
   60 uma_zone_t      acl_zone;
   61 static int      vacl_set_acl(struct thread *td, struct vnode *vp,
   62                     acl_type_t type, struct acl *aclp);
   63 static int      vacl_get_acl(struct thread *td, struct vnode *vp,
   64                     acl_type_t type, struct acl *aclp);
   65 static int      vacl_aclcheck(struct thread *td, struct vnode *vp,
   66                     acl_type_t type, struct acl *aclp);
   67 
   68 /*
   69  * These calls wrap the real vnode operations, and are called by the syscall
   70  * code once the syscall has converted the path or file descriptor to a vnode
   71  * (unlocked).  The aclp pointer is assumed still to point to userland, so
   72  * this should not be consumed within the kernel except by syscall code.
   73  * Other code should directly invoke VOP_{SET,GET}ACL.
   74  */
   75 
   76 /*
   77  * Given a vnode, set its ACL.
   78  */
   79 static int
   80 vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type,
   81     struct acl *aclp)
   82 {
   83         struct acl inkernacl;
   84         struct mount *mp;
   85         int error;
   86 
   87         error = copyin(aclp, &inkernacl, sizeof(struct acl));
   88         if (error)
   89                 return(error);
   90         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
   91         if (error != 0)
   92                 return (error);
   93         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
   94         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
   95 #ifdef MAC
   96         error = mac_check_vnode_setacl(td->td_ucred, vp, type, &inkernacl);
   97         if (error != 0)
   98                 goto out;
   99 #endif
  100         error = VOP_SETACL(vp, type, &inkernacl, td->td_ucred, td);
  101 #ifdef MAC
  102 out:
  103 #endif
  104         VOP_UNLOCK(vp, 0, td);
  105         vn_finished_write(mp);
  106         return(error);
  107 }
  108 
  109 /*
  110  * Given a vnode, get its ACL.
  111  */
  112 static int
  113 vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type,
  114     struct acl *aclp)
  115 {
  116         struct acl inkernelacl;
  117         int error;
  118 
  119         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
  120         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  121 #ifdef MAC
  122         error = mac_check_vnode_getacl(td->td_ucred, vp, type);
  123         if (error != 0)
  124                 goto out;
  125 #endif
  126         error = VOP_GETACL(vp, type, &inkernelacl, td->td_ucred, td);
  127 #ifdef MAC
  128 out:
  129 #endif
  130         VOP_UNLOCK(vp, 0, td);
  131         if (error == 0)
  132                 error = copyout(&inkernelacl, aclp, sizeof(struct acl));
  133         return (error);
  134 }
  135 
  136 /*
  137  * Given a vnode, delete its ACL.
  138  */
  139 static int
  140 vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type)
  141 {
  142         struct mount *mp;
  143         int error;
  144 
  145         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
  146         if (error)
  147                 return (error);
  148         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
  149         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  150 #ifdef MAC
  151         error = mac_check_vnode_deleteacl(td->td_ucred, vp, type);
  152         if (error)
  153                 goto out;
  154 #endif
  155         error = VOP_SETACL(vp, type, 0, td->td_ucred, td);
  156 #ifdef MAC
  157 out:
  158 #endif
  159         VOP_UNLOCK(vp, 0, td);
  160         vn_finished_write(mp);
  161         return (error);
  162 }
  163 
  164 /*
  165  * Given a vnode, check whether an ACL is appropriate for it
  166  */
  167 static int
  168 vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type,
  169     struct acl *aclp)
  170 {
  171         struct acl inkernelacl;
  172         int error;
  173 
  174         error = copyin(aclp, &inkernelacl, sizeof(struct acl));
  175         if (error)
  176                 return(error);
  177         error = VOP_ACLCHECK(vp, type, &inkernelacl, td->td_ucred, td);
  178         return (error);
  179 }
  180 
  181 /*
  182  * syscalls -- convert the path/fd to a vnode, and call vacl_whatever.  Don't
  183  * need to lock, as the vacl_ code will get/release any locks required.
  184  */
  185 
  186 /*
  187  * Given a file path, get an ACL for it
  188  */
  189 int
  190 __acl_get_file(struct thread *td, struct __acl_get_file_args *uap)
  191 {
  192         struct nameidata nd;
  193         int vfslocked, error;
  194 
  195         NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
  196         error = namei(&nd);
  197         vfslocked = NDHASGIANT(&nd);
  198         if (error == 0) {
  199                 error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
  200                 NDFREE(&nd, 0);
  201         }
  202         VFS_UNLOCK_GIANT(vfslocked);
  203         return (error);
  204 }
  205 
  206 /*
  207  * Given a file path, get an ACL for it; don't follow links.
  208  */
  209 int
  210 __acl_get_link(struct thread *td, struct __acl_get_link_args *uap)
  211 {
  212         struct nameidata nd;
  213         int vfslocked, error;
  214 
  215         NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
  216         error = namei(&nd);
  217         vfslocked = NDHASGIANT(&nd);
  218         if (error == 0) {
  219                 error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
  220                 NDFREE(&nd, 0);
  221         }
  222         VFS_UNLOCK_GIANT(vfslocked);
  223         return (error);
  224 }
  225 
  226 /*
  227  * Given a file path, set an ACL for it.
  228  */
  229 int
  230 __acl_set_file(struct thread *td, struct __acl_set_file_args *uap)
  231 {
  232         struct nameidata nd;
  233         int vfslocked, error;
  234 
  235         NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
  236         error = namei(&nd);
  237         vfslocked = NDHASGIANT(&nd);
  238         if (error == 0) {
  239                 error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
  240                 NDFREE(&nd, 0);
  241         }
  242         VFS_UNLOCK_GIANT(vfslocked);
  243         return (error);
  244 }
  245 
  246 /*
  247  * Given a file path, set an ACL for it; don't follow links.
  248  */
  249 int
  250 __acl_set_link(struct thread *td, struct __acl_set_link_args *uap)
  251 {
  252         struct nameidata nd;
  253         int vfslocked, error;
  254 
  255         NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
  256         error = namei(&nd);
  257         vfslocked = NDHASGIANT(&nd);
  258         if (error == 0) {
  259                 error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
  260                 NDFREE(&nd, 0);
  261         }
  262         VFS_UNLOCK_GIANT(vfslocked);
  263         return (error);
  264 }
  265 
  266 /*
  267  * Given a file descriptor, get an ACL for it.
  268  */
  269 int
  270 __acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap)
  271 {
  272         struct file *fp;
  273         int vfslocked, error;
  274 
  275         error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
  276         if (error == 0) {
  277                 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
  278                 error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp);
  279                 fdrop(fp, td);
  280                 VFS_UNLOCK_GIANT(vfslocked);
  281         }
  282         return (error);
  283 }
  284 
  285 /*
  286  * Given a file descriptor, set an ACL for it.
  287  */
  288 int
  289 __acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap)
  290 {
  291         struct file *fp;
  292         int vfslocked, error;
  293 
  294         error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
  295         if (error == 0) {
  296                 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
  297                 error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp);
  298                 fdrop(fp, td);
  299                 VFS_UNLOCK_GIANT(vfslocked);
  300         }
  301         return (error);
  302 }
  303 
  304 /*
  305  * Given a file path, delete an ACL from it.
  306  */
  307 int
  308 __acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap)
  309 {
  310         struct nameidata nd;
  311         int vfslocked, error;
  312 
  313         NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
  314         error = namei(&nd);
  315         vfslocked = NDHASGIANT(&nd);
  316         if (error == 0) {
  317                 error = vacl_delete(td, nd.ni_vp, uap->type);
  318                 NDFREE(&nd, 0);
  319         }
  320         VFS_UNLOCK_GIANT(vfslocked);
  321         return (error);
  322 }
  323 
  324 /*
  325  * Given a file path, delete an ACL from it; don't follow links.
  326  */
  327 int
  328 __acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap)
  329 {
  330         struct nameidata nd;
  331         int vfslocked, error;
  332 
  333         NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
  334         error = namei(&nd);
  335         vfslocked = NDHASGIANT(&nd);
  336         if (error == 0) {
  337                 error = vacl_delete(td, nd.ni_vp, uap->type);
  338                 NDFREE(&nd, 0);
  339         }
  340         VFS_UNLOCK_GIANT(vfslocked);
  341         return (error);
  342 }
  343 
  344 /*
  345  * Given a file path, delete an ACL from it.
  346  */
  347 int
  348 __acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap)
  349 {
  350         struct file *fp;
  351         int vfslocked, error;
  352 
  353         error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
  354         if (error == 0) {
  355                 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
  356                 error = vacl_delete(td, fp->f_vnode, uap->type);
  357                 fdrop(fp, td);
  358                 VFS_UNLOCK_GIANT(vfslocked);
  359         }
  360         return (error);
  361 }
  362 
  363 /*
  364  * Given a file path, check an ACL for it.
  365  */
  366 int
  367 __acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap)
  368 {
  369         struct nameidata        nd;
  370         int vfslocked, error;
  371 
  372         NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
  373         error = namei(&nd);
  374         vfslocked = NDHASGIANT(&nd);
  375         if (error == 0) {
  376                 error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
  377                 NDFREE(&nd, 0);
  378         }
  379         VFS_UNLOCK_GIANT(vfslocked);
  380         return (error);
  381 }
  382 
  383 /*
  384  * Given a file path, check an ACL for it; don't follow links.
  385  */
  386 int
  387 __acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap)
  388 {
  389         struct nameidata        nd;
  390         int vfslocked, error;
  391 
  392         NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
  393         error = namei(&nd);
  394         vfslocked = NDHASGIANT(&nd);
  395         if (error == 0) {
  396                 error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
  397                 NDFREE(&nd, 0);
  398         }
  399         VFS_UNLOCK_GIANT(vfslocked);
  400         return (error);
  401 }
  402 
  403 /*
  404  * Given a file descriptor, check an ACL for it.
  405  */
  406 int
  407 __acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap)
  408 {
  409         struct file *fp;
  410         int vfslocked, error;
  411 
  412         error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
  413         if (error == 0) {
  414                 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
  415                 error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp);
  416                 fdrop(fp, td);
  417                 VFS_UNLOCK_GIANT(vfslocked);
  418         }
  419         return (error);
  420 }
  421 
  422 /* ARGUSED */
  423 
  424 static void
  425 aclinit(void *dummy __unused)
  426 {
  427 
  428         acl_zone = uma_zcreate("ACL UMA zone", sizeof(struct acl),
  429             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  430 }
  431 SYSINIT(acls, SI_SUB_ACL, SI_ORDER_FIRST, aclinit, NULL);

Cache object: d399d6b978bcaa47b25889a571828f18


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.