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/subr_acl_posix1e.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 support routines specific to POSIX.1e access control lists.  These are
   32  * utility routines for code common across file systems implementing POSIX.1e
   33  * ACLs.
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD: releng/8.2/sys/kern/subr_acl_posix1e.c 205748 2010-03-27 17:22:11Z trasz $");
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/mount.h>
   42 #include <sys/priv.h>
   43 #include <sys/vnode.h>
   44 #include <sys/errno.h>
   45 #include <sys/stat.h>
   46 #include <sys/acl.h>
   47 
   48 /*
   49  * Implement a version of vaccess() that understands POSIX.1e ACL semantics;
   50  * the access ACL has already been prepared for evaluation by the file system
   51  * and is passed via 'uid', 'gid', and 'acl'.  Return 0 on success, else an
   52  * errno value.
   53  */
   54 int
   55 vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
   56     struct acl *acl, accmode_t accmode, struct ucred *cred, int *privused)
   57 {
   58         struct acl_entry *acl_other, *acl_mask;
   59         accmode_t dac_granted;
   60         accmode_t priv_granted;
   61         accmode_t acl_mask_granted;
   62         int group_matched, i;
   63 
   64         KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND)) == 0,
   65             ("invalid bit in accmode"));
   66 
   67         /*
   68          * Look for a normal, non-privileged way to access the file/directory
   69          * as requested.  If it exists, go with that.  Otherwise, attempt to
   70          * use privileges granted via priv_granted.  In some cases, which
   71          * privileges to use may be ambiguous due to "best match", in which
   72          * case fall back on first match for the time being.
   73          */
   74         if (privused != NULL)
   75                 *privused = 0;
   76 
   77         /*
   78          * Determine privileges now, but don't apply until we've found a DAC
   79          * entry that matches but has failed to allow access.
   80          *
   81          * XXXRW: Ideally, we'd determine the privileges required before
   82          * asking for them.
   83          */
   84         priv_granted = 0;
   85 
   86         if (type == VDIR) {
   87                 if ((accmode & VEXEC) && !priv_check_cred(cred,
   88                      PRIV_VFS_LOOKUP, 0))
   89                         priv_granted |= VEXEC;
   90         } else {
   91                 if ((accmode & VEXEC) && !priv_check_cred(cred,
   92                     PRIV_VFS_EXEC, 0))
   93                         priv_granted |= VEXEC;
   94         }
   95 
   96         if ((accmode & VREAD) && !priv_check_cred(cred, PRIV_VFS_READ, 0))
   97                 priv_granted |= VREAD;
   98 
   99         if (((accmode & VWRITE) || (accmode & VAPPEND)) &&
  100             !priv_check_cred(cred, PRIV_VFS_WRITE, 0))
  101                 priv_granted |= (VWRITE | VAPPEND);
  102 
  103         if ((accmode & VADMIN) && !priv_check_cred(cred, PRIV_VFS_ADMIN, 0))
  104                 priv_granted |= VADMIN;
  105 
  106         /*
  107          * The owner matches if the effective uid associated with the
  108          * credential matches that of the ACL_USER_OBJ entry.  While we're
  109          * doing the first scan, also cache the location of the ACL_MASK and
  110          * ACL_OTHER entries, preventing some future iterations.
  111          */
  112         acl_mask = acl_other = NULL;
  113         for (i = 0; i < acl->acl_cnt; i++) {
  114                 switch (acl->acl_entry[i].ae_tag) {
  115                 case ACL_USER_OBJ:
  116                         if (file_uid != cred->cr_uid)
  117                                 break;
  118                         dac_granted = 0;
  119                         dac_granted |= VADMIN;
  120                         if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
  121                                 dac_granted |= VEXEC;
  122                         if (acl->acl_entry[i].ae_perm & ACL_READ)
  123                                 dac_granted |= VREAD;
  124                         if (acl->acl_entry[i].ae_perm & ACL_WRITE)
  125                                 dac_granted |= (VWRITE | VAPPEND);
  126                         if ((accmode & dac_granted) == accmode)
  127                                 return (0);
  128 
  129                         /*
  130                          * XXXRW: Do privilege lookup here.
  131                          */
  132                         if ((accmode & (dac_granted | priv_granted)) ==
  133                             accmode) {
  134                                 if (privused != NULL)
  135                                         *privused = 1;
  136                                 return (0);
  137                         }
  138                         goto error;
  139 
  140                 case ACL_MASK:
  141                         acl_mask = &acl->acl_entry[i];
  142                         break;
  143 
  144                 case ACL_OTHER:
  145                         acl_other = &acl->acl_entry[i];
  146                         break;
  147 
  148                 default:
  149                         break;
  150                 }
  151         }
  152 
  153         /*
  154          * An ACL_OTHER entry should always exist in a valid access ACL.  If
  155          * it doesn't, then generate a serious failure.  For now, this means
  156          * a debugging message and EPERM, but in the future should probably
  157          * be a panic.
  158          */
  159         if (acl_other == NULL) {
  160                 /*
  161                  * XXX This should never happen
  162                  */
  163                 printf("vaccess_acl_posix1e: ACL_OTHER missing\n");
  164                 return (EPERM);
  165         }
  166 
  167         /*
  168          * Checks against ACL_USER, ACL_GROUP_OBJ, and ACL_GROUP fields are
  169          * masked by an ACL_MASK entry, if any.  As such, first identify the
  170          * ACL_MASK field, then iterate through identifying potential user
  171          * matches, then group matches.  If there is no ACL_MASK, assume that
  172          * the mask allows all requests to succeed.
  173          */
  174         if (acl_mask != NULL) {
  175                 acl_mask_granted = 0;
  176                 if (acl_mask->ae_perm & ACL_EXECUTE)
  177                         acl_mask_granted |= VEXEC;
  178                 if (acl_mask->ae_perm & ACL_READ)
  179                         acl_mask_granted |= VREAD;
  180                 if (acl_mask->ae_perm & ACL_WRITE)
  181                         acl_mask_granted |= (VWRITE | VAPPEND);
  182         } else
  183                 acl_mask_granted = VEXEC | VREAD | VWRITE | VAPPEND;
  184 
  185         /*
  186          * Check ACL_USER ACL entries.  There will either be one or no
  187          * matches; if there is one, we accept or rejected based on the
  188          * match; otherwise, we continue on to groups.
  189          */
  190         for (i = 0; i < acl->acl_cnt; i++) {
  191                 switch (acl->acl_entry[i].ae_tag) {
  192                 case ACL_USER:
  193                         if (acl->acl_entry[i].ae_id != cred->cr_uid)
  194                                 break;
  195                         dac_granted = 0;
  196                         if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
  197                                 dac_granted |= VEXEC;
  198                         if (acl->acl_entry[i].ae_perm & ACL_READ)
  199                                 dac_granted |= VREAD;
  200                         if (acl->acl_entry[i].ae_perm & ACL_WRITE)
  201                                 dac_granted |= (VWRITE | VAPPEND);
  202                         dac_granted &= acl_mask_granted;
  203                         if ((accmode & dac_granted) == accmode)
  204                                 return (0);
  205                         /*
  206                          * XXXRW: Do privilege lookup here.
  207                          */
  208                         if ((accmode & (dac_granted | priv_granted)) !=
  209                             accmode)
  210                                 goto error;
  211 
  212                         if (privused != NULL)
  213                                 *privused = 1;
  214                         return (0);
  215                 }
  216         }
  217 
  218         /*
  219          * Group match is best-match, not first-match, so find a "best"
  220          * match.  Iterate across, testing each potential group match.  Make
  221          * sure we keep track of whether we found a match or not, so that we
  222          * know if we should try again with any available privilege, or if we
  223          * should move on to ACL_OTHER.
  224          */
  225         group_matched = 0;
  226         for (i = 0; i < acl->acl_cnt; i++) {
  227                 switch (acl->acl_entry[i].ae_tag) {
  228                 case ACL_GROUP_OBJ:
  229                         if (!groupmember(file_gid, cred))
  230                                 break;
  231                         dac_granted = 0;
  232                         if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
  233                                 dac_granted |= VEXEC;
  234                         if (acl->acl_entry[i].ae_perm & ACL_READ)
  235                                 dac_granted |= VREAD;
  236                         if (acl->acl_entry[i].ae_perm & ACL_WRITE)
  237                                 dac_granted |= (VWRITE | VAPPEND);
  238                         dac_granted  &= acl_mask_granted;
  239 
  240                         if ((accmode & dac_granted) == accmode)
  241                                 return (0);
  242 
  243                         group_matched = 1;
  244                         break;
  245 
  246                 case ACL_GROUP:
  247                         if (!groupmember(acl->acl_entry[i].ae_id, cred))
  248                                 break;
  249                         dac_granted = 0;
  250                         if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
  251                                 dac_granted |= VEXEC;
  252                         if (acl->acl_entry[i].ae_perm & ACL_READ)
  253                                 dac_granted |= VREAD;
  254                         if (acl->acl_entry[i].ae_perm & ACL_WRITE)
  255                                 dac_granted |= (VWRITE | VAPPEND);
  256                         dac_granted  &= acl_mask_granted;
  257 
  258                         if ((accmode & dac_granted) == accmode)
  259                                 return (0);
  260 
  261                         group_matched = 1;
  262                         break;
  263 
  264                 default:
  265                         break;
  266                 }
  267         }
  268 
  269         if (group_matched == 1) {
  270                 /*
  271                  * There was a match, but it did not grant rights via pure
  272                  * DAC.  Try again, this time with privilege.
  273                  */
  274                 for (i = 0; i < acl->acl_cnt; i++) {
  275                         switch (acl->acl_entry[i].ae_tag) {
  276                         case ACL_GROUP_OBJ:
  277                                 if (!groupmember(file_gid, cred))
  278                                         break;
  279                                 dac_granted = 0;
  280                                 if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
  281                                         dac_granted |= VEXEC;
  282                                 if (acl->acl_entry[i].ae_perm & ACL_READ)
  283                                         dac_granted |= VREAD;
  284                                 if (acl->acl_entry[i].ae_perm & ACL_WRITE)
  285                                         dac_granted |= (VWRITE | VAPPEND);
  286                                 dac_granted &= acl_mask_granted;
  287 
  288                                 /*
  289                                  * XXXRW: Do privilege lookup here.
  290                                  */
  291                                 if ((accmode & (dac_granted | priv_granted))
  292                                     != accmode)
  293                                         break;
  294 
  295                                 if (privused != NULL)
  296                                         *privused = 1;
  297                                 return (0);
  298 
  299                         case ACL_GROUP:
  300                                 if (!groupmember(acl->acl_entry[i].ae_id,
  301                                     cred))
  302                                         break;
  303                                 dac_granted = 0;
  304                                 if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
  305                                 dac_granted |= VEXEC;
  306                                 if (acl->acl_entry[i].ae_perm & ACL_READ)
  307                                         dac_granted |= VREAD;
  308                                 if (acl->acl_entry[i].ae_perm & ACL_WRITE)
  309                                         dac_granted |= (VWRITE | VAPPEND);
  310                                 dac_granted &= acl_mask_granted;
  311 
  312                                 /*
  313                                  * XXXRW: Do privilege lookup here.
  314                                  */
  315                                 if ((accmode & (dac_granted | priv_granted))
  316                                     != accmode)
  317                                         break;
  318 
  319                                 if (privused != NULL)
  320                                         *privused = 1;
  321                                 return (0);
  322 
  323                         default:
  324                                 break;
  325                         }
  326                 }
  327                 /*
  328                  * Even with privilege, group membership was not sufficient.
  329                  * Return failure.
  330                  */
  331                 goto error;
  332         }
  333                 
  334         /*
  335          * Fall back on ACL_OTHER.  ACL_MASK is not applied to ACL_OTHER.
  336          */
  337         dac_granted = 0;
  338         if (acl_other->ae_perm & ACL_EXECUTE)
  339                 dac_granted |= VEXEC;
  340         if (acl_other->ae_perm & ACL_READ)
  341                 dac_granted |= VREAD;
  342         if (acl_other->ae_perm & ACL_WRITE)
  343                 dac_granted |= (VWRITE | VAPPEND);
  344 
  345         if ((accmode & dac_granted) == accmode)
  346                 return (0);
  347         /*
  348          * XXXRW: Do privilege lookup here.
  349          */
  350         if ((accmode & (dac_granted | priv_granted)) == accmode) {
  351                 if (privused != NULL)
  352                         *privused = 1;
  353                 return (0);
  354         }
  355 
  356 error:
  357         return ((accmode & VADMIN) ? EPERM : EACCES);
  358 }
  359 
  360 /*
  361  * For the purposes of filesystems maintaining the _OBJ entries in an inode
  362  * with a mode_t field, this routine converts a mode_t entry to an
  363  * acl_perm_t.
  364  */
  365 acl_perm_t
  366 acl_posix1e_mode_to_perm(acl_tag_t tag, mode_t mode)
  367 {
  368         acl_perm_t      perm = 0;
  369 
  370         switch(tag) {
  371         case ACL_USER_OBJ:
  372                 if (mode & S_IXUSR)
  373                         perm |= ACL_EXECUTE;
  374                 if (mode & S_IRUSR)
  375                         perm |= ACL_READ;
  376                 if (mode & S_IWUSR)
  377                         perm |= ACL_WRITE;
  378                 return (perm);
  379 
  380         case ACL_GROUP_OBJ:
  381                 if (mode & S_IXGRP)
  382                         perm |= ACL_EXECUTE;
  383                 if (mode & S_IRGRP)
  384                         perm |= ACL_READ;
  385                 if (mode & S_IWGRP)
  386                         perm |= ACL_WRITE;
  387                 return (perm);
  388 
  389         case ACL_OTHER:
  390                 if (mode & S_IXOTH)
  391                         perm |= ACL_EXECUTE;
  392                 if (mode & S_IROTH)
  393                         perm |= ACL_READ;
  394                 if (mode & S_IWOTH)
  395                         perm |= ACL_WRITE;
  396                 return (perm);
  397 
  398         default:
  399                 printf("acl_posix1e_mode_to_perm: invalid tag (%d)\n", tag);
  400                 return (0);
  401         }
  402 }
  403 
  404 /*
  405  * Given inode information (uid, gid, mode), return an acl entry of the
  406  * appropriate type.
  407  */
  408 struct acl_entry
  409 acl_posix1e_mode_to_entry(acl_tag_t tag, uid_t uid, gid_t gid, mode_t mode)
  410 {
  411         struct acl_entry        acl_entry;
  412 
  413         acl_entry.ae_tag = tag;
  414         acl_entry.ae_perm = acl_posix1e_mode_to_perm(tag, mode);
  415         acl_entry.ae_entry_type = 0;
  416         acl_entry.ae_flags = 0;
  417         switch(tag) {
  418         case ACL_USER_OBJ:
  419                 acl_entry.ae_id = uid;
  420                 break;
  421 
  422         case ACL_GROUP_OBJ:
  423                 acl_entry.ae_id = gid;
  424                 break;
  425 
  426         case ACL_OTHER:
  427                 acl_entry.ae_id = ACL_UNDEFINED_ID;
  428                 break;
  429 
  430         default:
  431                 acl_entry.ae_id = ACL_UNDEFINED_ID;
  432                 printf("acl_posix1e_mode_to_entry: invalid tag (%d)\n", tag);
  433         }
  434 
  435         return (acl_entry);
  436 }
  437 
  438 /*
  439  * Utility function to generate a file mode given appropriate ACL entries.
  440  */
  441 mode_t
  442 acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry,
  443     struct acl_entry *acl_group_obj_entry, struct acl_entry *acl_other_entry)
  444 {
  445         mode_t  mode;
  446 
  447         mode = 0;
  448         if (acl_user_obj_entry->ae_perm & ACL_EXECUTE)
  449                 mode |= S_IXUSR;
  450         if (acl_user_obj_entry->ae_perm & ACL_READ)
  451                 mode |= S_IRUSR;
  452         if (acl_user_obj_entry->ae_perm & ACL_WRITE)
  453                 mode |= S_IWUSR;
  454         if (acl_group_obj_entry->ae_perm & ACL_EXECUTE)
  455                 mode |= S_IXGRP;
  456         if (acl_group_obj_entry->ae_perm & ACL_READ)
  457                 mode |= S_IRGRP;
  458         if (acl_group_obj_entry->ae_perm & ACL_WRITE)
  459                 mode |= S_IWGRP;
  460         if (acl_other_entry->ae_perm & ACL_EXECUTE)
  461                 mode |= S_IXOTH;
  462         if (acl_other_entry->ae_perm & ACL_READ)
  463                 mode |= S_IROTH;
  464         if (acl_other_entry->ae_perm & ACL_WRITE)
  465                 mode |= S_IWOTH;
  466 
  467         return (mode);
  468 }
  469 
  470 /*
  471  * Utility function to generate a file mode given a complete POSIX.1e access
  472  * ACL.  Note that if the ACL is improperly formed, this may result in a
  473  * panic.
  474  */
  475 mode_t
  476 acl_posix1e_acl_to_mode(struct acl *acl)
  477 {
  478         struct acl_entry *acl_mask, *acl_user_obj, *acl_group_obj, *acl_other;
  479         int i;
  480 
  481         /*
  482          * Find the ACL entries relevant to a POSIX permission mode.
  483          */
  484         acl_user_obj = acl_group_obj = acl_other = acl_mask = NULL;
  485         for (i = 0; i < acl->acl_cnt; i++) {
  486                 switch (acl->acl_entry[i].ae_tag) {
  487                 case ACL_USER_OBJ:
  488                         acl_user_obj = &acl->acl_entry[i];
  489                         break;
  490 
  491                 case ACL_GROUP_OBJ:
  492                         acl_group_obj = &acl->acl_entry[i];
  493                         break;
  494 
  495                 case ACL_OTHER:
  496                         acl_other = &acl->acl_entry[i];
  497                         break;
  498 
  499                 case ACL_MASK:
  500                         acl_mask = &acl->acl_entry[i];
  501                         break;
  502 
  503                 case ACL_USER:
  504                 case ACL_GROUP:
  505                         break;
  506 
  507                 default:
  508                         panic("acl_posix1e_acl_to_mode: bad ae_tag");
  509                 }
  510         }
  511 
  512         if (acl_user_obj == NULL || acl_group_obj == NULL || acl_other == NULL)
  513                 panic("acl_posix1e_acl_to_mode: missing base ae_tags");
  514 
  515         /*
  516          * POSIX.1e specifies that if there is an ACL_MASK entry, we replace
  517          * the mode "group" bits with its permissions.  If there isn't, we
  518          * use the ACL_GROUP_OBJ permissions.
  519          */
  520         if (acl_mask != NULL)
  521                 return (acl_posix1e_perms_to_mode(acl_user_obj, acl_mask,
  522                     acl_other));
  523         else
  524                 return (acl_posix1e_perms_to_mode(acl_user_obj, acl_group_obj,
  525                     acl_other));
  526 }
  527 
  528 /*
  529  * Perform a syntactic check of the ACL, sufficient to allow an implementing
  530  * filesystem to determine if it should accept this and rely on the POSIX.1e
  531  * ACL properties.
  532  */
  533 int
  534 acl_posix1e_check(struct acl *acl)
  535 {
  536         int num_acl_user_obj, num_acl_user, num_acl_group_obj, num_acl_group;
  537         int num_acl_mask, num_acl_other, i;
  538 
  539         /*
  540          * Verify that the number of entries does not exceed the maximum
  541          * defined for acl_t.
  542          *
  543          * Verify that the correct number of various sorts of ae_tags are
  544          * present:
  545          *   Exactly one ACL_USER_OBJ
  546          *   Exactly one ACL_GROUP_OBJ
  547          *   Exactly one ACL_OTHER
  548          *   If any ACL_USER or ACL_GROUP entries appear, then exactly one
  549          *   ACL_MASK entry must also appear.
  550          *
  551          * Verify that all ae_perm entries are in ACL_PERM_BITS.
  552          *
  553          * Verify all ae_tag entries are understood by this implementation.
  554          *
  555          * Note: Does not check for uniqueness of qualifier (ae_id) field.
  556          */
  557         num_acl_user_obj = num_acl_user = num_acl_group_obj = num_acl_group =
  558             num_acl_mask = num_acl_other = 0;
  559         if (acl->acl_cnt > ACL_MAX_ENTRIES || acl->acl_cnt < 0)
  560                 return (EINVAL);
  561         for (i = 0; i < acl->acl_cnt; i++) {
  562                 /*
  563                  * Check for a valid tag.
  564                  */
  565                 switch(acl->acl_entry[i].ae_tag) {
  566                 case ACL_USER_OBJ:
  567                         acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
  568                         if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
  569                                 return (EINVAL);
  570                         num_acl_user_obj++;
  571                         break;
  572                 case ACL_GROUP_OBJ:
  573                         acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
  574                         if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
  575                                 return (EINVAL);
  576                         num_acl_group_obj++;
  577                         break;
  578                 case ACL_USER:
  579                         if (acl->acl_entry[i].ae_id == ACL_UNDEFINED_ID)
  580                                 return (EINVAL);
  581                         num_acl_user++;
  582                         break;
  583                 case ACL_GROUP:
  584                         if (acl->acl_entry[i].ae_id == ACL_UNDEFINED_ID)
  585                                 return (EINVAL);
  586                         num_acl_group++;
  587                         break;
  588                 case ACL_OTHER:
  589                         acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
  590                         if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
  591                                 return (EINVAL);
  592                         num_acl_other++;
  593                         break;
  594                 case ACL_MASK:
  595                         acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
  596                         if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
  597                                 return (EINVAL);
  598                         num_acl_mask++;
  599                         break;
  600                 default:
  601                         return (EINVAL);
  602                 }
  603                 /*
  604                  * Check for valid perm entries.
  605                  */
  606                 if ((acl->acl_entry[i].ae_perm | ACL_PERM_BITS) !=
  607                     ACL_PERM_BITS)
  608                         return (EINVAL);
  609         }
  610         if ((num_acl_user_obj != 1) || (num_acl_group_obj != 1) ||
  611             (num_acl_other != 1) || (num_acl_mask != 0 && num_acl_mask != 1))
  612                 return (EINVAL);
  613         if (((num_acl_group != 0) || (num_acl_user != 0)) &&
  614             (num_acl_mask != 1))
  615                 return (EINVAL);
  616         return (0);
  617 }
  618 
  619 /*
  620  * Given a requested mode for a new object, and a default ACL, combine the
  621  * two to produce a new mode.  Be careful not to clear any bits that aren't
  622  * intended to be affected by the POSIX.1e ACL.  Eventually, this might also
  623  * take the cmask as an argument, if we push that down into
  624  * per-filesystem-code.
  625  */
  626 mode_t
  627 acl_posix1e_newfilemode(mode_t cmode, struct acl *dacl)
  628 {
  629         mode_t mode;
  630 
  631         mode = cmode;
  632         /*
  633          * The current composition policy is that a permission bit must be
  634          * set in *both* the ACL and the requested creation mode for it to
  635          * appear in the resulting mode/ACL.  First clear any possibly
  636          * effected bits, then reconstruct.
  637          */
  638         mode &= ACL_PRESERVE_MASK;
  639         mode |= (ACL_OVERRIDE_MASK & cmode & acl_posix1e_acl_to_mode(dacl));
  640 
  641         return (mode);
  642 }

Cache object: d35e4c25e2cd184c286454a4481c241c


[ 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.