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

Cache object: 7cd587660053436b34507b93f69c440e


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