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

Cache object: 6ed79ff99e3e7cc753efc2e9a27448c3


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