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/7.4/sys/kern/subr_acl_posix1e.c 170587 2007-06-12 00:12:01Z rwatson $");
   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, mode_t acc_mode, struct ucred *cred, int *privused)
   57 {
   58         struct acl_entry *acl_other, *acl_mask;
   59         mode_t dac_granted;
   60         mode_t priv_granted;
   61         mode_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 ((acc_mode & VEXEC) && !priv_check_cred(cred,
   85                      PRIV_VFS_LOOKUP, 0))
   86                         priv_granted |= VEXEC;
   87         } else {
   88                 if ((acc_mode & VEXEC) && !priv_check_cred(cred,
   89                     PRIV_VFS_EXEC, 0))
   90                         priv_granted |= VEXEC;
   91         }
   92 
   93         if ((acc_mode & VREAD) && !priv_check_cred(cred, PRIV_VFS_READ, 0))
   94                 priv_granted |= VREAD;
   95 
   96         if (((acc_mode & VWRITE) || (acc_mode & VAPPEND)) &&
   97             !priv_check_cred(cred, PRIV_VFS_WRITE, 0))
   98                 priv_granted |= (VWRITE | VAPPEND);
   99 
  100         if ((acc_mode & 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 ((acc_mode & dac_granted) == acc_mode)
  124                                 return (0);
  125 
  126                         /*
  127                          * XXXRW: Do privilege lookup here.
  128                          */
  129                         if ((acc_mode & (dac_granted | priv_granted)) ==
  130                             acc_mode) {
  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 ((acc_mode & dac_granted) == acc_mode)
  201                                 return (0);
  202                         /*
  203                          * XXXRW: Do privilege lookup here.
  204                          */
  205                         if ((acc_mode & (dac_granted | priv_granted)) !=
  206                             acc_mode)
  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 ((acc_mode & dac_granted) == acc_mode)
  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 ((acc_mode & dac_granted) == acc_mode)
  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 ((acc_mode & (dac_granted | priv_granted))
  289                                     != acc_mode)
  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 ((acc_mode & (dac_granted | priv_granted))
  313                                     != acc_mode)
  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 ((acc_mode & dac_granted) == acc_mode)
  343                 return (0);
  344         /*
  345          * XXXRW: Do privilege lookup here.
  346          */
  347         if ((acc_mode & (dac_granted | priv_granted)) == acc_mode) {
  348                 if (privused != NULL)
  349                         *privused = 1;
  350                 return (0);
  351         }
  352 
  353 error:
  354         return ((acc_mode & 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         switch(tag) {
  413         case ACL_USER_OBJ:
  414                 acl_entry.ae_id = uid;
  415                 break;
  416 
  417         case ACL_GROUP_OBJ:
  418                 acl_entry.ae_id = gid;
  419                 break;
  420 
  421         case ACL_OTHER:
  422                 acl_entry.ae_id = ACL_UNDEFINED_ID;
  423                 break;
  424 
  425         default:
  426                 acl_entry.ae_id = ACL_UNDEFINED_ID;
  427                 printf("acl_posix1e_mode_to_entry: invalid tag (%d)\n", tag);
  428         }
  429 
  430         return (acl_entry);
  431 }
  432 
  433 /*
  434  * Utility function to generate a file mode given appropriate ACL entries.
  435  */
  436 mode_t
  437 acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry,
  438     struct acl_entry *acl_group_obj_entry, struct acl_entry *acl_other_entry)
  439 {
  440         mode_t  mode;
  441 
  442         mode = 0;
  443         if (acl_user_obj_entry->ae_perm & ACL_EXECUTE)
  444                 mode |= S_IXUSR;
  445         if (acl_user_obj_entry->ae_perm & ACL_READ)
  446                 mode |= S_IRUSR;
  447         if (acl_user_obj_entry->ae_perm & ACL_WRITE)
  448                 mode |= S_IWUSR;
  449         if (acl_group_obj_entry->ae_perm & ACL_EXECUTE)
  450                 mode |= S_IXGRP;
  451         if (acl_group_obj_entry->ae_perm & ACL_READ)
  452                 mode |= S_IRGRP;
  453         if (acl_group_obj_entry->ae_perm & ACL_WRITE)
  454                 mode |= S_IWGRP;
  455         if (acl_other_entry->ae_perm & ACL_EXECUTE)
  456                 mode |= S_IXOTH;
  457         if (acl_other_entry->ae_perm & ACL_READ)
  458                 mode |= S_IROTH;
  459         if (acl_other_entry->ae_perm & ACL_WRITE)
  460                 mode |= S_IWOTH;
  461 
  462         return (mode);
  463 }
  464 
  465 /*
  466  * Utility function to generate a file mode given a complete POSIX.1e access
  467  * ACL.  Note that if the ACL is improperly formed, this may result in a
  468  * panic.
  469  */
  470 mode_t
  471 acl_posix1e_acl_to_mode(struct acl *acl)
  472 {
  473         struct acl_entry *acl_mask, *acl_user_obj, *acl_group_obj, *acl_other;
  474         int i;
  475 
  476         /*
  477          * Find the ACL entries relevant to a POSIX permission mode.
  478          */
  479         acl_user_obj = acl_group_obj = acl_other = acl_mask = NULL;
  480         for (i = 0; i < acl->acl_cnt; i++) {
  481                 switch (acl->acl_entry[i].ae_tag) {
  482                 case ACL_USER_OBJ:
  483                         acl_user_obj = &acl->acl_entry[i];
  484                         break;
  485 
  486                 case ACL_GROUP_OBJ:
  487                         acl_group_obj = &acl->acl_entry[i];
  488                         break;
  489 
  490                 case ACL_OTHER:
  491                         acl_other = &acl->acl_entry[i];
  492                         break;
  493 
  494                 case ACL_MASK:
  495                         acl_mask = &acl->acl_entry[i];
  496                         break;
  497 
  498                 case ACL_USER:
  499                 case ACL_GROUP:
  500                         break;
  501 
  502                 default:
  503                         panic("acl_posix1e_acl_to_mode: bad ae_tag");
  504                 }
  505         }
  506 
  507         if (acl_user_obj == NULL || acl_group_obj == NULL || acl_other == NULL)
  508                 panic("acl_posix1e_acl_to_mode: missing base ae_tags");
  509 
  510         /*
  511          * POSIX.1e specifies that if there is an ACL_MASK entry, we replace
  512          * the mode "group" bits with its permissions.  If there isn't, we
  513          * use the ACL_GROUP_OBJ permissions.
  514          */
  515         if (acl_mask != NULL)
  516                 return (acl_posix1e_perms_to_mode(acl_user_obj, acl_mask,
  517                     acl_other));
  518         else
  519                 return (acl_posix1e_perms_to_mode(acl_user_obj, acl_group_obj,
  520                     acl_other));
  521 }
  522 
  523 /*
  524  * Perform a syntactic check of the ACL, sufficient to allow an implementing
  525  * filesystem to determine if it should accept this and rely on the POSIX.1e
  526  * ACL properties.
  527  */
  528 int
  529 acl_posix1e_check(struct acl *acl)
  530 {
  531         int num_acl_user_obj, num_acl_user, num_acl_group_obj, num_acl_group;
  532         int num_acl_mask, num_acl_other, i;
  533 
  534         /*
  535          * Verify that the number of entries does not exceed the maximum
  536          * defined for acl_t.
  537          *
  538          * Verify that the correct number of various sorts of ae_tags are
  539          * present:
  540          *   Exactly one ACL_USER_OBJ
  541          *   Exactly one ACL_GROUP_OBJ
  542          *   Exactly one ACL_OTHER
  543          *   If any ACL_USER or ACL_GROUP entries appear, then exactly one
  544          *   ACL_MASK entry must also appear.
  545          *
  546          * Verify that all ae_perm entries are in ACL_PERM_BITS.
  547          *
  548          * Verify all ae_tag entries are understood by this implementation.
  549          *
  550          * Note: Does not check for uniqueness of qualifier (ae_id) field.
  551          */
  552         num_acl_user_obj = num_acl_user = num_acl_group_obj = num_acl_group =
  553             num_acl_mask = num_acl_other = 0;
  554         if (acl->acl_cnt > ACL_MAX_ENTRIES || acl->acl_cnt < 0)
  555                 return (EINVAL);
  556         for (i = 0; i < acl->acl_cnt; i++) {
  557                 /*
  558                  * Check for a valid tag.
  559                  */
  560                 switch(acl->acl_entry[i].ae_tag) {
  561                 case ACL_USER_OBJ:
  562                         acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
  563                         if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
  564                                 return (EINVAL);
  565                         num_acl_user_obj++;
  566                         break;
  567                 case ACL_GROUP_OBJ:
  568                         acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
  569                         if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
  570                                 return (EINVAL);
  571                         num_acl_group_obj++;
  572                         break;
  573                 case ACL_USER:
  574                         if (acl->acl_entry[i].ae_id == ACL_UNDEFINED_ID)
  575                                 return (EINVAL);
  576                         num_acl_user++;
  577                         break;
  578                 case ACL_GROUP:
  579                         if (acl->acl_entry[i].ae_id == ACL_UNDEFINED_ID)
  580                                 return (EINVAL);
  581                         num_acl_group++;
  582                         break;
  583                 case ACL_OTHER:
  584                         acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
  585                         if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
  586                                 return (EINVAL);
  587                         num_acl_other++;
  588                         break;
  589                 case ACL_MASK:
  590                         acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
  591                         if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
  592                                 return (EINVAL);
  593                         num_acl_mask++;
  594                         break;
  595                 default:
  596                         return (EINVAL);
  597                 }
  598                 /*
  599                  * Check for valid perm entries.
  600                  */
  601                 if ((acl->acl_entry[i].ae_perm | ACL_PERM_BITS) !=
  602                     ACL_PERM_BITS)
  603                         return (EINVAL);
  604         }
  605         if ((num_acl_user_obj != 1) || (num_acl_group_obj != 1) ||
  606             (num_acl_other != 1) || (num_acl_mask != 0 && num_acl_mask != 1))
  607                 return (EINVAL);
  608         if (((num_acl_group != 0) || (num_acl_user != 0)) &&
  609             (num_acl_mask != 1))
  610                 return (EINVAL);
  611         return (0);
  612 }
  613 
  614 /*
  615  * Given a requested mode for a new object, and a default ACL, combine the
  616  * two to produce a new mode.  Be careful not to clear any bits that aren't
  617  * intended to be affected by the POSIX.1e ACL.  Eventually, this might also
  618  * take the cmask as an argument, if we push that down into
  619  * per-filesystem-code.
  620  */
  621 mode_t
  622 acl_posix1e_newfilemode(mode_t cmode, struct acl *dacl)
  623 {
  624         mode_t mode;
  625 
  626         mode = cmode;
  627         /*
  628          * The current composition policy is that a permission bit must be
  629          * set in *both* the ACL and the requested creation mode for it to
  630          * appear in the resulting mode/ACL.  First clear any possibly
  631          * effected bits, then reconstruct.
  632          */
  633         mode &= ACL_PRESERVE_MASK;
  634         mode |= (ACL_OVERRIDE_MASK & cmode & acl_posix1e_acl_to_mode(dacl));
  635 
  636         return (mode);
  637 }

Cache object: 13ad7af141c35abc8a7623849d6bfcd6


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