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/contrib/openzfs/module/os/freebsd/spl/acl_common.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  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 /*
   22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
   24  */
   25 
   26 #include <sys/types.h>
   27 #include <sys/stat.h>
   28 #include <sys/avl.h>
   29 #include <sys/misc.h>
   30 #if defined(_KERNEL)
   31 #include <sys/kmem.h>
   32 #include <sys/systm.h>
   33 #include <sys/sysmacros.h>
   34 #include <acl/acl_common.h>
   35 #include <sys/debug.h>
   36 #else
   37 #include <errno.h>
   38 #include <stdlib.h>
   39 #include <stddef.h>
   40 #include <unistd.h>
   41 #include <assert.h>
   42 #include <grp.h>
   43 #include <pwd.h>
   44 #include <acl_common.h>
   45 #endif
   46 
   47 #define ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \
   48     ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \
   49     ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL)
   50 
   51 
   52 #define ACL_SYNCHRONIZE_SET_DENY                0x0000001
   53 #define ACL_SYNCHRONIZE_SET_ALLOW               0x0000002
   54 #define ACL_SYNCHRONIZE_ERR_DENY                0x0000004
   55 #define ACL_SYNCHRONIZE_ERR_ALLOW               0x0000008
   56 
   57 #define ACL_WRITE_OWNER_SET_DENY                0x0000010
   58 #define ACL_WRITE_OWNER_SET_ALLOW               0x0000020
   59 #define ACL_WRITE_OWNER_ERR_DENY                0x0000040
   60 #define ACL_WRITE_OWNER_ERR_ALLOW               0x0000080
   61 
   62 #define ACL_DELETE_SET_DENY                     0x0000100
   63 #define ACL_DELETE_SET_ALLOW                    0x0000200
   64 #define ACL_DELETE_ERR_DENY                     0x0000400
   65 #define ACL_DELETE_ERR_ALLOW                    0x0000800
   66 
   67 #define ACL_WRITE_ATTRS_OWNER_SET_DENY          0x0001000
   68 #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW         0x0002000
   69 #define ACL_WRITE_ATTRS_OWNER_ERR_DENY          0x0004000
   70 #define ACL_WRITE_ATTRS_OWNER_ERR_ALLOW         0x0008000
   71 
   72 #define ACL_WRITE_ATTRS_WRITER_SET_DENY         0x0010000
   73 #define ACL_WRITE_ATTRS_WRITER_SET_ALLOW        0x0020000
   74 #define ACL_WRITE_ATTRS_WRITER_ERR_DENY         0x0040000
   75 #define ACL_WRITE_ATTRS_WRITER_ERR_ALLOW        0x0080000
   76 
   77 #define ACL_WRITE_NAMED_WRITER_SET_DENY         0x0100000
   78 #define ACL_WRITE_NAMED_WRITER_SET_ALLOW        0x0200000
   79 #define ACL_WRITE_NAMED_WRITER_ERR_DENY         0x0400000
   80 #define ACL_WRITE_NAMED_WRITER_ERR_ALLOW        0x0800000
   81 
   82 #define ACL_READ_NAMED_READER_SET_DENY          0x1000000
   83 #define ACL_READ_NAMED_READER_SET_ALLOW         0x2000000
   84 #define ACL_READ_NAMED_READER_ERR_DENY          0x4000000
   85 #define ACL_READ_NAMED_READER_ERR_ALLOW         0x8000000
   86 
   87 
   88 #define ACE_VALID_MASK_BITS (\
   89     ACE_READ_DATA | \
   90     ACE_LIST_DIRECTORY | \
   91     ACE_WRITE_DATA | \
   92     ACE_ADD_FILE | \
   93     ACE_APPEND_DATA | \
   94     ACE_ADD_SUBDIRECTORY | \
   95     ACE_READ_NAMED_ATTRS | \
   96     ACE_WRITE_NAMED_ATTRS | \
   97     ACE_EXECUTE | \
   98     ACE_DELETE_CHILD | \
   99     ACE_READ_ATTRIBUTES | \
  100     ACE_WRITE_ATTRIBUTES | \
  101     ACE_DELETE | \
  102     ACE_READ_ACL | \
  103     ACE_WRITE_ACL | \
  104     ACE_WRITE_OWNER | \
  105     ACE_SYNCHRONIZE)
  106 
  107 #define ACE_MASK_UNDEFINED                      0x80000000
  108 
  109 #define ACE_VALID_FLAG_BITS (ACE_FILE_INHERIT_ACE | \
  110     ACE_DIRECTORY_INHERIT_ACE | \
  111     ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \
  112     ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \
  113     ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE)
  114 
  115 /*
  116  * ACL conversion helpers
  117  */
  118 
  119 typedef enum {
  120         ace_unused,
  121         ace_user_obj,
  122         ace_user,
  123         ace_group, /* includes GROUP and GROUP_OBJ */
  124         ace_other_obj
  125 } ace_to_aent_state_t;
  126 
  127 typedef struct acevals {
  128         uid_t key;
  129         avl_node_t avl;
  130         uint32_t mask;
  131         uint32_t allowed;
  132         uint32_t denied;
  133         int aent_type;
  134 } acevals_t;
  135 
  136 typedef struct ace_list {
  137         acevals_t user_obj;
  138         avl_tree_t user;
  139         int numusers;
  140         acevals_t group_obj;
  141         avl_tree_t group;
  142         int numgroups;
  143         acevals_t other_obj;
  144         uint32_t acl_mask;
  145         int hasmask;
  146         int dfacl_flag;
  147         ace_to_aent_state_t state;
  148         int seen; /* bitmask of all aclent_t a_type values seen */
  149 } ace_list_t;
  150 
  151 /*
  152  * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
  153  * v = Ptr to array/vector of objs
  154  * n = # objs in the array
  155  * s = size of each obj (must be multiples of a word size)
  156  * f = ptr to function to compare two objs
  157  *      returns (-1 = less than, 0 = equal, 1 = greater than
  158  */
  159 void
  160 ksort(caddr_t v, int n, int s, int (*f)(void *, void *))
  161 {
  162         int g, i, j, ii;
  163         unsigned int *p1, *p2;
  164         unsigned int tmp;
  165 
  166         /* No work to do */
  167         if (v == NULL || n <= 1)
  168                 return;
  169 
  170         /* Sanity check on arguments */
  171         ASSERT3U(((uintptr_t)v & 0x3), ==, 0);
  172         ASSERT3S((s & 0x3), ==, 0);
  173         ASSERT3S(s, >, 0);
  174         for (g = n / 2; g > 0; g /= 2) {
  175                 for (i = g; i < n; i++) {
  176                         for (j = i - g; j >= 0 &&
  177                             (*f)(v + j * s, v + (j + g) * s) == 1;
  178                             j -= g) {
  179                                 p1 = (void *)(v + j * s);
  180                                 p2 = (void *)(v + (j + g) * s);
  181                                 for (ii = 0; ii < s / 4; ii++) {
  182                                         tmp = *p1;
  183                                         *p1++ = *p2;
  184                                         *p2++ = tmp;
  185                                 }
  186                         }
  187                 }
  188         }
  189 }
  190 
  191 /*
  192  * Compare two acls, all fields.  Returns:
  193  * -1 (less than)
  194  *  0 (equal)
  195  * +1 (greater than)
  196  */
  197 int
  198 cmp2acls(void *a, void *b)
  199 {
  200         aclent_t *x = (aclent_t *)a;
  201         aclent_t *y = (aclent_t *)b;
  202 
  203         /* Compare types */
  204         if (x->a_type < y->a_type)
  205                 return (-1);
  206         if (x->a_type > y->a_type)
  207                 return (1);
  208         /* Equal types; compare id's */
  209         if (x->a_id < y->a_id)
  210                 return (-1);
  211         if (x->a_id > y->a_id)
  212                 return (1);
  213         /* Equal ids; compare perms */
  214         if (x->a_perm < y->a_perm)
  215                 return (-1);
  216         if (x->a_perm > y->a_perm)
  217                 return (1);
  218         /* Totally equal */
  219         return (0);
  220 }
  221 
  222 static int
  223 cacl_malloc(void **ptr, size_t size)
  224 {
  225         *ptr = kmem_zalloc(size, KM_SLEEP);
  226         return (0);
  227 }
  228 
  229 
  230 #if !defined(_KERNEL)
  231 acl_t *
  232 acl_alloc(enum acl_type type)
  233 {
  234         acl_t *aclp;
  235 
  236         if (cacl_malloc((void **)&aclp, sizeof (acl_t)) != 0)
  237                 return (NULL);
  238 
  239         aclp->acl_aclp = NULL;
  240         aclp->acl_cnt = 0;
  241 
  242         switch (type) {
  243         case ACE_T:
  244                 aclp->acl_type = ACE_T;
  245                 aclp->acl_entry_size = sizeof (ace_t);
  246                 break;
  247         case ACLENT_T:
  248                 aclp->acl_type = ACLENT_T;
  249                 aclp->acl_entry_size = sizeof (aclent_t);
  250                 break;
  251         default:
  252                 acl_free(aclp);
  253                 aclp = NULL;
  254         }
  255         return (aclp);
  256 }
  257 
  258 /*
  259  * Free acl_t structure
  260  */
  261 void
  262 acl_free(acl_t *aclp)
  263 {
  264         int acl_size;
  265 
  266         if (aclp == NULL)
  267                 return;
  268 
  269         if (aclp->acl_aclp) {
  270                 acl_size = aclp->acl_cnt * aclp->acl_entry_size;
  271                 cacl_free(aclp->acl_aclp, acl_size);
  272         }
  273 
  274         cacl_free(aclp, sizeof (acl_t));
  275 }
  276 
  277 static uint32_t
  278 access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow)
  279 {
  280         uint32_t access_mask = 0;
  281         int acl_produce;
  282         int synchronize_set = 0, write_owner_set = 0;
  283         int delete_set = 0, write_attrs_set = 0;
  284         int read_named_set = 0, write_named_set = 0;
  285 
  286         acl_produce = (ACL_SYNCHRONIZE_SET_ALLOW |
  287             ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
  288             ACL_WRITE_ATTRS_WRITER_SET_DENY);
  289 
  290         if (isallow) {
  291                 synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW;
  292                 write_owner_set = ACL_WRITE_OWNER_SET_ALLOW;
  293                 delete_set = ACL_DELETE_SET_ALLOW;
  294                 if (hasreadperm)
  295                         read_named_set = ACL_READ_NAMED_READER_SET_ALLOW;
  296                 if (haswriteperm)
  297                         write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW;
  298                 if (isowner)
  299                         write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW;
  300                 else if (haswriteperm)
  301                         write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW;
  302         } else {
  303 
  304                 synchronize_set = ACL_SYNCHRONIZE_SET_DENY;
  305                 write_owner_set = ACL_WRITE_OWNER_SET_DENY;
  306                 delete_set = ACL_DELETE_SET_DENY;
  307                 if (hasreadperm)
  308                         read_named_set = ACL_READ_NAMED_READER_SET_DENY;
  309                 if (haswriteperm)
  310                         write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY;
  311                 if (isowner)
  312                         write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY;
  313                 else if (haswriteperm)
  314                         write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY;
  315                 else
  316                         /*
  317                          * If the entity is not the owner and does not
  318                          * have write permissions ACE_WRITE_ATTRIBUTES will
  319                          * always go in the DENY ACE.
  320                          */
  321                         access_mask |= ACE_WRITE_ATTRIBUTES;
  322         }
  323 
  324         if (acl_produce & synchronize_set)
  325                 access_mask |= ACE_SYNCHRONIZE;
  326         if (acl_produce & write_owner_set)
  327                 access_mask |= ACE_WRITE_OWNER;
  328         if (acl_produce & delete_set)
  329                 access_mask |= ACE_DELETE;
  330         if (acl_produce & write_attrs_set)
  331                 access_mask |= ACE_WRITE_ATTRIBUTES;
  332         if (acl_produce & read_named_set)
  333                 access_mask |= ACE_READ_NAMED_ATTRS;
  334         if (acl_produce & write_named_set)
  335                 access_mask |= ACE_WRITE_NAMED_ATTRS;
  336 
  337         return (access_mask);
  338 }
  339 
  340 /*
  341  * Given an mode_t, convert it into an access_mask as used
  342  * by nfsace, assuming aclent_t -> nfsace semantics.
  343  */
  344 static uint32_t
  345 mode_to_ace_access(mode_t mode, boolean_t isdir, int isowner, int isallow)
  346 {
  347         uint32_t access = 0;
  348         int haswriteperm = 0;
  349         int hasreadperm = 0;
  350 
  351         if (isallow) {
  352                 haswriteperm = (mode & S_IWOTH);
  353                 hasreadperm = (mode & S_IROTH);
  354         } else {
  355                 haswriteperm = !(mode & S_IWOTH);
  356                 hasreadperm = !(mode & S_IROTH);
  357         }
  358 
  359         /*
  360          * The following call takes care of correctly setting the following
  361          * mask bits in the access_mask:
  362          * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE,
  363          * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS
  364          */
  365         access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow);
  366 
  367         if (isallow) {
  368                 access |= ACE_READ_ACL | ACE_READ_ATTRIBUTES;
  369                 if (isowner)
  370                         access |= ACE_WRITE_ACL;
  371         } else {
  372                 if (! isowner)
  373                         access |= ACE_WRITE_ACL;
  374         }
  375 
  376         /* read */
  377         if (mode & S_IROTH) {
  378                 access |= ACE_READ_DATA;
  379         }
  380         /* write */
  381         if (mode & S_IWOTH) {
  382                 access |= ACE_WRITE_DATA |
  383                     ACE_APPEND_DATA;
  384                 if (isdir)
  385                         access |= ACE_DELETE_CHILD;
  386         }
  387         /* exec */
  388         if (mode & S_IXOTH) {
  389                 access |= ACE_EXECUTE;
  390         }
  391 
  392         return (access);
  393 }
  394 
  395 /*
  396  * Given an nfsace (presumably an ALLOW entry), make a
  397  * corresponding DENY entry at the address given.
  398  */
  399 static void
  400 ace_make_deny(ace_t *allow, ace_t *deny, int isdir, int isowner)
  401 {
  402         (void) memcpy(deny, allow, sizeof (ace_t));
  403 
  404         deny->a_who = allow->a_who;
  405 
  406         deny->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
  407         deny->a_access_mask ^= ACE_POSIX_SUPPORTED_BITS;
  408         if (isdir)
  409                 deny->a_access_mask ^= ACE_DELETE_CHILD;
  410 
  411         deny->a_access_mask &= ~(ACE_SYNCHRONIZE | ACE_WRITE_OWNER |
  412             ACE_DELETE | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
  413             ACE_WRITE_NAMED_ATTRS);
  414         deny->a_access_mask |= access_mask_set((allow->a_access_mask &
  415             ACE_WRITE_DATA), (allow->a_access_mask & ACE_READ_DATA), isowner,
  416             B_FALSE);
  417 }
  418 /*
  419  * Make an initial pass over an array of aclent_t's.  Gather
  420  * information such as an ACL_MASK (if any), number of users,
  421  * number of groups, and whether the array needs to be sorted.
  422  */
  423 static int
  424 ln_aent_preprocess(aclent_t *aclent, int n,
  425     int *hasmask, mode_t *mask,
  426     int *numuser, int *numgroup, int *needsort)
  427 {
  428         int error = 0;
  429         int i;
  430         int curtype = 0;
  431 
  432         *hasmask = 0;
  433         *mask = 07;
  434         *needsort = 0;
  435         *numuser = 0;
  436         *numgroup = 0;
  437 
  438         for (i = 0; i < n; i++) {
  439                 if (aclent[i].a_type < curtype)
  440                         *needsort = 1;
  441                 else if (aclent[i].a_type > curtype)
  442                         curtype = aclent[i].a_type;
  443                 if (aclent[i].a_type & USER)
  444                         (*numuser)++;
  445                 if (aclent[i].a_type & (GROUP | GROUP_OBJ))
  446                         (*numgroup)++;
  447                 if (aclent[i].a_type & CLASS_OBJ) {
  448                         if (*hasmask) {
  449                                 error = EINVAL;
  450                                 goto out;
  451                         } else {
  452                                 *hasmask = 1;
  453                                 *mask = aclent[i].a_perm;
  454                         }
  455                 }
  456         }
  457 
  458         if ((! *hasmask) && (*numuser + *numgroup > 1)) {
  459                 error = EINVAL;
  460                 goto out;
  461         }
  462 
  463 out:
  464         return (error);
  465 }
  466 
  467 /*
  468  * Convert an array of aclent_t into an array of nfsace entries,
  469  * following POSIX draft -> nfsv4 conversion semantics as outlined in
  470  * the IETF draft.
  471  */
  472 static int
  473 ln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir)
  474 {
  475         int error = 0;
  476         mode_t mask;
  477         int numuser, numgroup, needsort;
  478         int resultsize = 0;
  479         int i, groupi = 0, skip;
  480         ace_t *acep, *result = NULL;
  481         int hasmask;
  482 
  483         error = ln_aent_preprocess(aclent, n, &hasmask, &mask,
  484             &numuser, &numgroup, &needsort);
  485         if (error != 0)
  486                 goto out;
  487 
  488         /* allow + deny for each aclent */
  489         resultsize = n * 2;
  490         if (hasmask) {
  491                 /*
  492                  * stick extra deny on the group_obj and on each
  493                  * user|group for the mask (the group_obj was added
  494                  * into the count for numgroup)
  495                  */
  496                 resultsize += numuser + numgroup;
  497                 /* ... and don't count the mask itself */
  498                 resultsize -= 2;
  499         }
  500 
  501         /* sort the source if necessary */
  502         if (needsort)
  503                 ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls);
  504 
  505         if (cacl_malloc((void **)&result, resultsize * sizeof (ace_t)) != 0)
  506                 goto out;
  507 
  508         acep = result;
  509 
  510         for (i = 0; i < n; i++) {
  511                 /*
  512                  * don't process CLASS_OBJ (mask); mask was grabbed in
  513                  * ln_aent_preprocess()
  514                  */
  515                 if (aclent[i].a_type & CLASS_OBJ)
  516                         continue;
  517 
  518                 /* If we need an ACL_MASK emulator, prepend it now */
  519                 if ((hasmask) &&
  520                     (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) {
  521                         acep->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
  522                         acep->a_flags = 0;
  523                         if (aclent[i].a_type & GROUP_OBJ) {
  524                                 acep->a_who = (uid_t)-1;
  525                                 acep->a_flags |=
  526                                     (ACE_IDENTIFIER_GROUP|ACE_GROUP);
  527                         } else if (aclent[i].a_type & USER) {
  528                                 acep->a_who = aclent[i].a_id;
  529                         } else {
  530                                 acep->a_who = aclent[i].a_id;
  531                                 acep->a_flags |= ACE_IDENTIFIER_GROUP;
  532                         }
  533                         if (aclent[i].a_type & ACL_DEFAULT) {
  534                                 acep->a_flags |= ACE_INHERIT_ONLY_ACE |
  535                                     ACE_FILE_INHERIT_ACE |
  536                                     ACE_DIRECTORY_INHERIT_ACE;
  537                         }
  538                         /*
  539                          * Set the access mask for the prepended deny
  540                          * ace.  To do this, we invert the mask (found
  541                          * in ln_aent_preprocess()) then convert it to an
  542                          * DENY ace access_mask.
  543                          */
  544                         acep->a_access_mask = mode_to_ace_access((mask ^ 07),
  545                             isdir, 0, 0);
  546                         acep += 1;
  547                 }
  548 
  549                 /* handle a_perm -> access_mask */
  550                 acep->a_access_mask = mode_to_ace_access(aclent[i].a_perm,
  551                     isdir, aclent[i].a_type & USER_OBJ, 1);
  552 
  553                 /* emulate a default aclent */
  554                 if (aclent[i].a_type & ACL_DEFAULT) {
  555                         acep->a_flags |= ACE_INHERIT_ONLY_ACE |
  556                             ACE_FILE_INHERIT_ACE |
  557                             ACE_DIRECTORY_INHERIT_ACE;
  558                 }
  559 
  560                 /*
  561                  * handle a_perm and a_id
  562                  *
  563                  * this must be done last, since it involves the
  564                  * corresponding deny aces, which are handled
  565                  * differently for each different a_type.
  566                  */
  567                 if (aclent[i].a_type & USER_OBJ) {
  568                         acep->a_who = (uid_t)-1;
  569                         acep->a_flags |= ACE_OWNER;
  570                         ace_make_deny(acep, acep + 1, isdir, B_TRUE);
  571                         acep += 2;
  572                 } else if (aclent[i].a_type & USER) {
  573                         acep->a_who = aclent[i].a_id;
  574                         ace_make_deny(acep, acep + 1, isdir, B_FALSE);
  575                         acep += 2;
  576                 } else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) {
  577                         if (aclent[i].a_type & GROUP_OBJ) {
  578                                 acep->a_who = (uid_t)-1;
  579                                 acep->a_flags |= ACE_GROUP;
  580                         } else {
  581                                 acep->a_who = aclent[i].a_id;
  582                         }
  583                         acep->a_flags |= ACE_IDENTIFIER_GROUP;
  584                         /*
  585                          * Set the corresponding deny for the group ace.
  586                          *
  587                          * The deny aces go after all of the groups, unlike
  588                          * everything else, where they immediately follow
  589                          * the allow ace.
  590                          *
  591                          * We calculate "skip", the number of slots to
  592                          * skip ahead for the deny ace, here.
  593                          *
  594                          * The pattern is:
  595                          * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3
  596                          * thus, skip is
  597                          * (2 * numgroup) - 1 - groupi
  598                          * (2 * numgroup) to account for MD + A
  599                          * - 1 to account for the fact that we're on the
  600                          * access (A), not the mask (MD)
  601                          * - groupi to account for the fact that we have
  602                          * passed up groupi number of MD's.
  603                          */
  604                         skip = (2 * numgroup) - 1 - groupi;
  605                         ace_make_deny(acep, acep + skip, isdir, B_FALSE);
  606                         /*
  607                          * If we just did the last group, skip acep past
  608                          * all of the denies; else, just move ahead one.
  609                          */
  610                         if (++groupi >= numgroup)
  611                                 acep += numgroup + 1;
  612                         else
  613                                 acep += 1;
  614                 } else if (aclent[i].a_type & OTHER_OBJ) {
  615                         acep->a_who = (uid_t)-1;
  616                         acep->a_flags |= ACE_EVERYONE;
  617                         ace_make_deny(acep, acep + 1, isdir, B_FALSE);
  618                         acep += 2;
  619                 } else {
  620                         error = EINVAL;
  621                         goto out;
  622                 }
  623         }
  624 
  625         *acepp = result;
  626         *rescount = resultsize;
  627 
  628 out:
  629         if (error != 0) {
  630                 if ((result != NULL) && (resultsize > 0)) {
  631                         cacl_free(result, resultsize * sizeof (ace_t));
  632                 }
  633         }
  634 
  635         return (error);
  636 }
  637 
  638 static int
  639 convert_aent_to_ace(aclent_t *aclentp, int aclcnt, boolean_t isdir,
  640     ace_t **retacep, int *retacecnt)
  641 {
  642         ace_t *acep;
  643         ace_t *dfacep;
  644         int acecnt = 0;
  645         int dfacecnt = 0;
  646         int dfaclstart = 0;
  647         int dfaclcnt = 0;
  648         aclent_t *aclp;
  649         int i;
  650         int error;
  651         int acesz, dfacesz;
  652 
  653         ksort((caddr_t)aclentp, aclcnt, sizeof (aclent_t), cmp2acls);
  654 
  655         for (i = 0, aclp = aclentp; i < aclcnt; aclp++, i++) {
  656                 if (aclp->a_type & ACL_DEFAULT)
  657                         break;
  658         }
  659 
  660         if (i < aclcnt) {
  661                 dfaclstart = i;
  662                 dfaclcnt = aclcnt - i;
  663         }
  664 
  665         if (dfaclcnt && !isdir) {
  666                 return (EINVAL);
  667         }
  668 
  669         error = ln_aent_to_ace(aclentp, i,  &acep, &acecnt, isdir);
  670         if (error)
  671                 return (error);
  672 
  673         if (dfaclcnt) {
  674                 error = ln_aent_to_ace(&aclentp[dfaclstart], dfaclcnt,
  675                     &dfacep, &dfacecnt, isdir);
  676                 if (error) {
  677                         if (acep) {
  678                                 cacl_free(acep, acecnt * sizeof (ace_t));
  679                         }
  680                         return (error);
  681                 }
  682         }
  683 
  684         if (dfacecnt != 0) {
  685                 acesz = sizeof (ace_t) * acecnt;
  686                 dfacesz = sizeof (ace_t) * dfacecnt;
  687                 acep = cacl_realloc(acep, acesz, acesz + dfacesz);
  688                 if (acep == NULL)
  689                         return (ENOMEM);
  690                 if (dfaclcnt) {
  691                         (void) memcpy(acep + acecnt, dfacep, dfacesz);
  692                 }
  693         }
  694         if (dfaclcnt)
  695                 cacl_free(dfacep, dfacecnt * sizeof (ace_t));
  696 
  697         *retacecnt = acecnt + dfacecnt;
  698         *retacep = acep;
  699         return (0);
  700 }
  701 
  702 static int
  703 ace_mask_to_mode(uint32_t  mask, o_mode_t *modep, boolean_t isdir)
  704 {
  705         int error = 0;
  706         o_mode_t mode = 0;
  707         uint32_t bits, wantbits;
  708 
  709         /* read */
  710         if (mask & ACE_READ_DATA)
  711                 mode |= S_IROTH;
  712 
  713         /* write */
  714         wantbits = (ACE_WRITE_DATA | ACE_APPEND_DATA);
  715         if (isdir)
  716                 wantbits |= ACE_DELETE_CHILD;
  717         bits = mask & wantbits;
  718         if (bits != 0) {
  719                 if (bits != wantbits) {
  720                         error = ENOTSUP;
  721                         goto out;
  722                 }
  723                 mode |= S_IWOTH;
  724         }
  725 
  726         /* exec */
  727         if (mask & ACE_EXECUTE) {
  728                 mode |= S_IXOTH;
  729         }
  730 
  731         *modep = mode;
  732 
  733 out:
  734         return (error);
  735 }
  736 
  737 static void
  738 acevals_init(acevals_t *vals, uid_t key)
  739 {
  740         memset(vals, 0, sizeof (*vals));
  741         vals->allowed = ACE_MASK_UNDEFINED;
  742         vals->denied = ACE_MASK_UNDEFINED;
  743         vals->mask = ACE_MASK_UNDEFINED;
  744         vals->key = key;
  745 }
  746 
  747 static void
  748 ace_list_init(ace_list_t *al, int dfacl_flag)
  749 {
  750         acevals_init(&al->user_obj, 0);
  751         acevals_init(&al->group_obj, 0);
  752         acevals_init(&al->other_obj, 0);
  753         al->numusers = 0;
  754         al->numgroups = 0;
  755         al->acl_mask = 0;
  756         al->hasmask = 0;
  757         al->state = ace_unused;
  758         al->seen = 0;
  759         al->dfacl_flag = dfacl_flag;
  760 }
  761 
  762 /*
  763  * Find or create an acevals holder for a given id and avl tree.
  764  *
  765  * Note that only one thread will ever touch these avl trees, so
  766  * there is no need for locking.
  767  */
  768 static acevals_t *
  769 acevals_find(ace_t *ace, avl_tree_t *avl, int *num)
  770 {
  771         acevals_t key, *rc;
  772         avl_index_t where;
  773 
  774         key.key = ace->a_who;
  775         rc = avl_find(avl, &key, &where);
  776         if (rc != NULL)
  777                 return (rc);
  778 
  779         /* this memory is freed by ln_ace_to_aent()->ace_list_free() */
  780         if (cacl_malloc((void **)&rc, sizeof (acevals_t)) != 0)
  781                 return (NULL);
  782 
  783         acevals_init(rc, ace->a_who);
  784         avl_insert(avl, rc, where);
  785         (*num)++;
  786 
  787         return (rc);
  788 }
  789 
  790 static int
  791 access_mask_check(ace_t *acep, int mask_bit, int isowner)
  792 {
  793         int set_deny, err_deny;
  794         int set_allow, err_allow;
  795         int acl_consume;
  796         int haswriteperm, hasreadperm;
  797 
  798         if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) {
  799                 haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 0 : 1;
  800                 hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 0 : 1;
  801         } else {
  802                 haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 1 : 0;
  803                 hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 1 : 0;
  804         }
  805 
  806         acl_consume = (ACL_SYNCHRONIZE_ERR_DENY |
  807             ACL_DELETE_ERR_DENY |
  808             ACL_WRITE_OWNER_ERR_DENY |
  809             ACL_WRITE_OWNER_ERR_ALLOW |
  810             ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
  811             ACL_WRITE_ATTRS_OWNER_ERR_DENY |
  812             ACL_WRITE_ATTRS_WRITER_SET_DENY |
  813             ACL_WRITE_ATTRS_WRITER_ERR_ALLOW |
  814             ACL_WRITE_NAMED_WRITER_ERR_DENY |
  815             ACL_READ_NAMED_READER_ERR_DENY);
  816 
  817         if (mask_bit == ACE_SYNCHRONIZE) {
  818                 set_deny = ACL_SYNCHRONIZE_SET_DENY;
  819                 err_deny =  ACL_SYNCHRONIZE_ERR_DENY;
  820                 set_allow = ACL_SYNCHRONIZE_SET_ALLOW;
  821                 err_allow = ACL_SYNCHRONIZE_ERR_ALLOW;
  822         } else if (mask_bit == ACE_WRITE_OWNER) {
  823                 set_deny = ACL_WRITE_OWNER_SET_DENY;
  824                 err_deny =  ACL_WRITE_OWNER_ERR_DENY;
  825                 set_allow = ACL_WRITE_OWNER_SET_ALLOW;
  826                 err_allow = ACL_WRITE_OWNER_ERR_ALLOW;
  827         } else if (mask_bit == ACE_DELETE) {
  828                 set_deny = ACL_DELETE_SET_DENY;
  829                 err_deny =  ACL_DELETE_ERR_DENY;
  830                 set_allow = ACL_DELETE_SET_ALLOW;
  831                 err_allow = ACL_DELETE_ERR_ALLOW;
  832         } else if (mask_bit == ACE_WRITE_ATTRIBUTES) {
  833                 if (isowner) {
  834                         set_deny = ACL_WRITE_ATTRS_OWNER_SET_DENY;
  835                         err_deny =  ACL_WRITE_ATTRS_OWNER_ERR_DENY;
  836                         set_allow = ACL_WRITE_ATTRS_OWNER_SET_ALLOW;
  837                         err_allow = ACL_WRITE_ATTRS_OWNER_ERR_ALLOW;
  838                 } else if (haswriteperm) {
  839                         set_deny = ACL_WRITE_ATTRS_WRITER_SET_DENY;
  840                         err_deny =  ACL_WRITE_ATTRS_WRITER_ERR_DENY;
  841                         set_allow = ACL_WRITE_ATTRS_WRITER_SET_ALLOW;
  842                         err_allow = ACL_WRITE_ATTRS_WRITER_ERR_ALLOW;
  843                 } else {
  844                         if ((acep->a_access_mask & mask_bit) &&
  845                             (acep->a_type & ACE_ACCESS_ALLOWED_ACE_TYPE)) {
  846                                 return (ENOTSUP);
  847                         }
  848                         return (0);
  849                 }
  850         } else if (mask_bit == ACE_READ_NAMED_ATTRS) {
  851                 if (!hasreadperm)
  852                         return (0);
  853 
  854                 set_deny = ACL_READ_NAMED_READER_SET_DENY;
  855                 err_deny = ACL_READ_NAMED_READER_ERR_DENY;
  856                 set_allow = ACL_READ_NAMED_READER_SET_ALLOW;
  857                 err_allow = ACL_READ_NAMED_READER_ERR_ALLOW;
  858         } else if (mask_bit == ACE_WRITE_NAMED_ATTRS) {
  859                 if (!haswriteperm)
  860                         return (0);
  861 
  862                 set_deny = ACL_WRITE_NAMED_WRITER_SET_DENY;
  863                 err_deny = ACL_WRITE_NAMED_WRITER_ERR_DENY;
  864                 set_allow = ACL_WRITE_NAMED_WRITER_SET_ALLOW;
  865                 err_allow = ACL_WRITE_NAMED_WRITER_ERR_ALLOW;
  866         } else {
  867                 return (EINVAL);
  868         }
  869 
  870         if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) {
  871                 if (acl_consume & set_deny) {
  872                         if (!(acep->a_access_mask & mask_bit)) {
  873                                 return (ENOTSUP);
  874                         }
  875                 } else if (acl_consume & err_deny) {
  876                         if (acep->a_access_mask & mask_bit) {
  877                                 return (ENOTSUP);
  878                         }
  879                 }
  880         } else {
  881                 /* ACE_ACCESS_ALLOWED_ACE_TYPE */
  882                 if (acl_consume & set_allow) {
  883                         if (!(acep->a_access_mask & mask_bit)) {
  884                                 return (ENOTSUP);
  885                         }
  886                 } else if (acl_consume & err_allow) {
  887                         if (acep->a_access_mask & mask_bit) {
  888                                 return (ENOTSUP);
  889                         }
  890                 }
  891         }
  892         return (0);
  893 }
  894 
  895 static int
  896 ace_to_aent_legal(ace_t *acep)
  897 {
  898         int error = 0;
  899         int isowner;
  900 
  901         /* only ALLOW or DENY */
  902         if ((acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE) &&
  903             (acep->a_type != ACE_ACCESS_DENIED_ACE_TYPE)) {
  904                 error = ENOTSUP;
  905                 goto out;
  906         }
  907 
  908         /* check for invalid flags */
  909         if (acep->a_flags & ~(ACE_VALID_FLAG_BITS)) {
  910                 error = EINVAL;
  911                 goto out;
  912         }
  913 
  914         /* some flags are illegal */
  915         if (acep->a_flags & (ACE_SUCCESSFUL_ACCESS_ACE_FLAG |
  916             ACE_FAILED_ACCESS_ACE_FLAG |
  917             ACE_NO_PROPAGATE_INHERIT_ACE)) {
  918                 error = ENOTSUP;
  919                 goto out;
  920         }
  921 
  922         /* check for invalid masks */
  923         if (acep->a_access_mask & ~(ACE_VALID_MASK_BITS)) {
  924                 error = EINVAL;
  925                 goto out;
  926         }
  927 
  928         if ((acep->a_flags & ACE_OWNER)) {
  929                 isowner = 1;
  930         } else {
  931                 isowner = 0;
  932         }
  933 
  934         error = access_mask_check(acep, ACE_SYNCHRONIZE, isowner);
  935         if (error)
  936                 goto out;
  937 
  938         error = access_mask_check(acep, ACE_WRITE_OWNER, isowner);
  939         if (error)
  940                 goto out;
  941 
  942         error = access_mask_check(acep, ACE_DELETE, isowner);
  943         if (error)
  944                 goto out;
  945 
  946         error = access_mask_check(acep, ACE_WRITE_ATTRIBUTES, isowner);
  947         if (error)
  948                 goto out;
  949 
  950         error = access_mask_check(acep, ACE_READ_NAMED_ATTRS, isowner);
  951         if (error)
  952                 goto out;
  953 
  954         error = access_mask_check(acep, ACE_WRITE_NAMED_ATTRS, isowner);
  955         if (error)
  956                 goto out;
  957 
  958         /* more detailed checking of masks */
  959         if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
  960                 if (! (acep->a_access_mask & ACE_READ_ATTRIBUTES)) {
  961                         error = ENOTSUP;
  962                         goto out;
  963                 }
  964                 if ((acep->a_access_mask & ACE_WRITE_DATA) &&
  965                     (! (acep->a_access_mask & ACE_APPEND_DATA))) {
  966                         error = ENOTSUP;
  967                         goto out;
  968                 }
  969                 if ((! (acep->a_access_mask & ACE_WRITE_DATA)) &&
  970                     (acep->a_access_mask & ACE_APPEND_DATA)) {
  971                         error = ENOTSUP;
  972                         goto out;
  973                 }
  974         }
  975 
  976         /* ACL enforcement */
  977         if ((acep->a_access_mask & ACE_READ_ACL) &&
  978             (acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE)) {
  979                 error = ENOTSUP;
  980                 goto out;
  981         }
  982         if (acep->a_access_mask & ACE_WRITE_ACL) {
  983                 if ((acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) &&
  984                     (isowner)) {
  985                         error = ENOTSUP;
  986                         goto out;
  987                 }
  988                 if ((acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) &&
  989                     (! isowner)) {
  990                         error = ENOTSUP;
  991                         goto out;
  992                 }
  993         }
  994 
  995 out:
  996         return (error);
  997 }
  998 
  999 static int
 1000 ace_allow_to_mode(uint32_t mask, o_mode_t *modep, boolean_t isdir)
 1001 {
 1002         /* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */
 1003         if ((mask & (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) !=
 1004             (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) {
 1005                 return (ENOTSUP);
 1006         }
 1007 
 1008         return (ace_mask_to_mode(mask, modep, isdir));
 1009 }
 1010 
 1011 static int
 1012 acevals_to_aent(acevals_t *vals, aclent_t *dest, ace_list_t *list,
 1013     uid_t owner, gid_t group, boolean_t isdir)
 1014 {
 1015         int error;
 1016         uint32_t  flips = ACE_POSIX_SUPPORTED_BITS;
 1017 
 1018         if (isdir)
 1019                 flips |= ACE_DELETE_CHILD;
 1020         if (vals->allowed != (vals->denied ^ flips)) {
 1021                 error = ENOTSUP;
 1022                 goto out;
 1023         }
 1024         if ((list->hasmask) && (list->acl_mask != vals->mask) &&
 1025             (vals->aent_type & (USER | GROUP | GROUP_OBJ))) {
 1026                 error = ENOTSUP;
 1027                 goto out;
 1028         }
 1029         error = ace_allow_to_mode(vals->allowed, &dest->a_perm, isdir);
 1030         if (error != 0)
 1031                 goto out;
 1032         dest->a_type = vals->aent_type;
 1033         if (dest->a_type & (USER | GROUP)) {
 1034                 dest->a_id = vals->key;
 1035         } else if (dest->a_type & USER_OBJ) {
 1036                 dest->a_id = owner;
 1037         } else if (dest->a_type & GROUP_OBJ) {
 1038                 dest->a_id = group;
 1039         } else if (dest->a_type & OTHER_OBJ) {
 1040                 dest->a_id = 0;
 1041         } else {
 1042                 error = EINVAL;
 1043                 goto out;
 1044         }
 1045 
 1046 out:
 1047         return (error);
 1048 }
 1049 
 1050 
 1051 static int
 1052 ace_list_to_aent(ace_list_t *list, aclent_t **aclentp, int *aclcnt,
 1053     uid_t owner, gid_t group, boolean_t isdir)
 1054 {
 1055         int error = 0;
 1056         aclent_t *aent, *result = NULL;
 1057         acevals_t *vals;
 1058         int resultcount;
 1059 
 1060         if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) !=
 1061             (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) {
 1062                 error = ENOTSUP;
 1063                 goto out;
 1064         }
 1065         if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) {
 1066                 error = ENOTSUP;
 1067                 goto out;
 1068         }
 1069 
 1070         resultcount = 3 + list->numusers + list->numgroups;
 1071         /*
 1072          * This must be the same condition as below, when we add the CLASS_OBJ
 1073          * (aka ACL mask)
 1074          */
 1075         if ((list->hasmask) || (! list->dfacl_flag))
 1076                 resultcount += 1;
 1077 
 1078         if (cacl_malloc((void **)&result,
 1079             resultcount * sizeof (aclent_t)) != 0) {
 1080                 error = ENOMEM;
 1081                 goto out;
 1082         }
 1083         aent = result;
 1084 
 1085         /* USER_OBJ */
 1086         if (!(list->user_obj.aent_type & USER_OBJ)) {
 1087                 error = EINVAL;
 1088                 goto out;
 1089         }
 1090 
 1091         error = acevals_to_aent(&list->user_obj, aent, list, owner, group,
 1092             isdir);
 1093 
 1094         if (error != 0)
 1095                 goto out;
 1096         ++aent;
 1097         /* USER */
 1098         vals = NULL;
 1099         for (vals = avl_first(&list->user); vals != NULL;
 1100             vals = AVL_NEXT(&list->user, vals)) {
 1101                 if (!(vals->aent_type & USER)) {
 1102                         error = EINVAL;
 1103                         goto out;
 1104                 }
 1105                 error = acevals_to_aent(vals, aent, list, owner, group,
 1106                     isdir);
 1107                 if (error != 0)
 1108                         goto out;
 1109                 ++aent;
 1110         }
 1111         /* GROUP_OBJ */
 1112         if (!(list->group_obj.aent_type & GROUP_OBJ)) {
 1113                 error = EINVAL;
 1114                 goto out;
 1115         }
 1116         error = acevals_to_aent(&list->group_obj, aent, list, owner, group,
 1117             isdir);
 1118         if (error != 0)
 1119                 goto out;
 1120         ++aent;
 1121         /* GROUP */
 1122         vals = NULL;
 1123         for (vals = avl_first(&list->group); vals != NULL;
 1124             vals = AVL_NEXT(&list->group, vals)) {
 1125                 if (!(vals->aent_type & GROUP)) {
 1126                         error = EINVAL;
 1127                         goto out;
 1128                 }
 1129                 error = acevals_to_aent(vals, aent, list, owner, group,
 1130                     isdir);
 1131                 if (error != 0)
 1132                         goto out;
 1133                 ++aent;
 1134         }
 1135         /*
 1136          * CLASS_OBJ (aka ACL_MASK)
 1137          *
 1138          * An ACL_MASK is not fabricated if the ACL is a default ACL.
 1139          * This is to follow UFS's behavior.
 1140          */
 1141         if ((list->hasmask) || (! list->dfacl_flag)) {
 1142                 if (list->hasmask) {
 1143                         uint32_t flips = ACE_POSIX_SUPPORTED_BITS;
 1144                         if (isdir)
 1145                                 flips |= ACE_DELETE_CHILD;
 1146                         error = ace_mask_to_mode(list->acl_mask ^ flips,
 1147                             &aent->a_perm, isdir);
 1148                         if (error != 0)
 1149                                 goto out;
 1150                 } else {
 1151                         /* fabricate the ACL_MASK from the group permissions */
 1152                         error = ace_mask_to_mode(list->group_obj.allowed,
 1153                             &aent->a_perm, isdir);
 1154                         if (error != 0)
 1155                                 goto out;
 1156                 }
 1157                 aent->a_id = 0;
 1158                 aent->a_type = CLASS_OBJ | list->dfacl_flag;
 1159                 ++aent;
 1160         }
 1161         /* OTHER_OBJ */
 1162         if (!(list->other_obj.aent_type & OTHER_OBJ)) {
 1163                 error = EINVAL;
 1164                 goto out;
 1165         }
 1166         error = acevals_to_aent(&list->other_obj, aent, list, owner, group,
 1167             isdir);
 1168         if (error != 0)
 1169                 goto out;
 1170         ++aent;
 1171 
 1172         *aclentp = result;
 1173         *aclcnt = resultcount;
 1174 
 1175 out:
 1176         if (error != 0) {
 1177                 if (result != NULL)
 1178                         cacl_free(result, resultcount * sizeof (aclent_t));
 1179         }
 1180 
 1181         return (error);
 1182 }
 1183 
 1184 
 1185 /*
 1186  * free all data associated with an ace_list
 1187  */
 1188 static void
 1189 ace_list_free(ace_list_t *al)
 1190 {
 1191         acevals_t *node;
 1192         void *cookie;
 1193 
 1194         if (al == NULL)
 1195                 return;
 1196 
 1197         cookie = NULL;
 1198         while ((node = avl_destroy_nodes(&al->user, &cookie)) != NULL)
 1199                 cacl_free(node, sizeof (acevals_t));
 1200         cookie = NULL;
 1201         while ((node = avl_destroy_nodes(&al->group, &cookie)) != NULL)
 1202                 cacl_free(node, sizeof (acevals_t));
 1203 
 1204         avl_destroy(&al->user);
 1205         avl_destroy(&al->group);
 1206 
 1207         /* free the container itself */
 1208         cacl_free(al, sizeof (ace_list_t));
 1209 }
 1210 
 1211 static int
 1212 acevals_compare(const void *va, const void *vb)
 1213 {
 1214         const acevals_t *a = va, *b = vb;
 1215 
 1216         if (a->key == b->key)
 1217                 return (0);
 1218 
 1219         if (a->key > b->key)
 1220                 return (1);
 1221 
 1222         else
 1223                 return (-1);
 1224 }
 1225 
 1226 /*
 1227  * Convert a list of ace_t entries to equivalent regular and default
 1228  * aclent_t lists.  Return error (ENOTSUP) when conversion is not possible.
 1229  */
 1230 static int
 1231 ln_ace_to_aent(ace_t *ace, int n, uid_t owner, gid_t group,
 1232     aclent_t **aclentp, int *aclcnt, aclent_t **dfaclentp, int *dfaclcnt,
 1233     boolean_t isdir)
 1234 {
 1235         int error = 0;
 1236         ace_t *acep;
 1237         uint32_t bits;
 1238         int i;
 1239         ace_list_t *normacl = NULL, *dfacl = NULL, *acl;
 1240         acevals_t *vals;
 1241 
 1242         *aclentp = NULL;
 1243         *aclcnt = 0;
 1244         *dfaclentp = NULL;
 1245         *dfaclcnt = 0;
 1246 
 1247         /* we need at least user_obj, group_obj, and other_obj */
 1248         if (n < 6) {
 1249                 error = ENOTSUP;
 1250                 goto out;
 1251         }
 1252         if (ace == NULL) {
 1253                 error = EINVAL;
 1254                 goto out;
 1255         }
 1256 
 1257         error = cacl_malloc((void **)&normacl, sizeof (ace_list_t));
 1258         if (error != 0)
 1259                 goto out;
 1260 
 1261         avl_create(&normacl->user, acevals_compare, sizeof (acevals_t),
 1262             offsetof(acevals_t, avl));
 1263         avl_create(&normacl->group, acevals_compare, sizeof (acevals_t),
 1264             offsetof(acevals_t, avl));
 1265 
 1266         ace_list_init(normacl, 0);
 1267 
 1268         error = cacl_malloc((void **)&dfacl, sizeof (ace_list_t));
 1269         if (error != 0)
 1270                 goto out;
 1271 
 1272         avl_create(&dfacl->user, acevals_compare, sizeof (acevals_t),
 1273             offsetof(acevals_t, avl));
 1274         avl_create(&dfacl->group, acevals_compare, sizeof (acevals_t),
 1275             offsetof(acevals_t, avl));
 1276         ace_list_init(dfacl, ACL_DEFAULT);
 1277 
 1278         /* process every ace_t... */
 1279         for (i = 0; i < n; i++) {
 1280                 acep = &ace[i];
 1281 
 1282                 /* rule out certain cases quickly */
 1283                 error = ace_to_aent_legal(acep);
 1284                 if (error != 0)
 1285                         goto out;
 1286 
 1287                 /*
 1288                  * Turn off these bits in order to not have to worry about
 1289                  * them when doing the checks for compliments.
 1290                  */
 1291                 acep->a_access_mask &= ~(ACE_WRITE_OWNER | ACE_DELETE |
 1292                     ACE_SYNCHRONIZE | ACE_WRITE_ATTRIBUTES |
 1293                     ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS);
 1294 
 1295                 /* see if this should be a regular or default acl */
 1296                 bits = acep->a_flags &
 1297                     (ACE_INHERIT_ONLY_ACE |
 1298                     ACE_FILE_INHERIT_ACE |
 1299                     ACE_DIRECTORY_INHERIT_ACE);
 1300                 if (bits != 0) {
 1301                         /* all or nothing on these inherit bits */
 1302                         if (bits != (ACE_INHERIT_ONLY_ACE |
 1303                             ACE_FILE_INHERIT_ACE |
 1304                             ACE_DIRECTORY_INHERIT_ACE)) {
 1305                                 error = ENOTSUP;
 1306                                 goto out;
 1307                         }
 1308                         acl = dfacl;
 1309                 } else {
 1310                         acl = normacl;
 1311                 }
 1312 
 1313                 if ((acep->a_flags & ACE_OWNER)) {
 1314                         if (acl->state > ace_user_obj) {
 1315                                 error = ENOTSUP;
 1316                                 goto out;
 1317                         }
 1318                         acl->state = ace_user_obj;
 1319                         acl->seen |= USER_OBJ;
 1320                         vals = &acl->user_obj;
 1321                         vals->aent_type = USER_OBJ | acl->dfacl_flag;
 1322                 } else if ((acep->a_flags & ACE_EVERYONE)) {
 1323                         acl->state = ace_other_obj;
 1324                         acl->seen |= OTHER_OBJ;
 1325                         vals = &acl->other_obj;
 1326                         vals->aent_type = OTHER_OBJ | acl->dfacl_flag;
 1327                 } else if (acep->a_flags & ACE_IDENTIFIER_GROUP) {
 1328                         if (acl->state > ace_group) {
 1329                                 error = ENOTSUP;
 1330                                 goto out;
 1331                         }
 1332                         if ((acep->a_flags & ACE_GROUP)) {
 1333                                 acl->seen |= GROUP_OBJ;
 1334                                 vals = &acl->group_obj;
 1335                                 vals->aent_type = GROUP_OBJ | acl->dfacl_flag;
 1336                         } else {
 1337                                 acl->seen |= GROUP;
 1338                                 vals = acevals_find(acep, &acl->group,
 1339                                     &acl->numgroups);
 1340                                 if (vals == NULL) {
 1341                                         error = ENOMEM;
 1342                                         goto out;
 1343                                 }
 1344                                 vals->aent_type = GROUP | acl->dfacl_flag;
 1345                         }
 1346                         acl->state = ace_group;
 1347                 } else {
 1348                         if (acl->state > ace_user) {
 1349                                 error = ENOTSUP;
 1350                                 goto out;
 1351                         }
 1352                         acl->state = ace_user;
 1353                         acl->seen |= USER;
 1354                         vals = acevals_find(acep, &acl->user,
 1355                             &acl->numusers);
 1356                         if (vals == NULL) {
 1357                                 error = ENOMEM;
 1358                                 goto out;
 1359                         }
 1360                         vals->aent_type = USER | acl->dfacl_flag;
 1361                 }
 1362 
 1363                 if (!(acl->state > ace_unused)) {
 1364                         error = EINVAL;
 1365                         goto out;
 1366                 }
 1367 
 1368                 if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
 1369                         /* no more than one allowed per aclent_t */
 1370                         if (vals->allowed != ACE_MASK_UNDEFINED) {
 1371                                 error = ENOTSUP;
 1372                                 goto out;
 1373                         }
 1374                         vals->allowed = acep->a_access_mask;
 1375                 } else {
 1376                         /*
 1377                          * it's a DENY; if there was a previous DENY, it
 1378                          * must have been an ACL_MASK.
 1379                          */
 1380                         if (vals->denied != ACE_MASK_UNDEFINED) {
 1381                                 /* ACL_MASK is for USER and GROUP only */
 1382                                 if ((acl->state != ace_user) &&
 1383                                     (acl->state != ace_group)) {
 1384                                         error = ENOTSUP;
 1385                                         goto out;
 1386                                 }
 1387 
 1388                                 if (! acl->hasmask) {
 1389                                         acl->hasmask = 1;
 1390                                         acl->acl_mask = vals->denied;
 1391                                 /* check for mismatched ACL_MASK emulations */
 1392                                 } else if (acl->acl_mask != vals->denied) {
 1393                                         error = ENOTSUP;
 1394                                         goto out;
 1395                                 }
 1396                                 vals->mask = vals->denied;
 1397                         }
 1398                         vals->denied = acep->a_access_mask;
 1399                 }
 1400         }
 1401 
 1402         /* done collating; produce the aclent_t lists */
 1403         if (normacl->state != ace_unused) {
 1404                 error = ace_list_to_aent(normacl, aclentp, aclcnt,
 1405                     owner, group, isdir);
 1406                 if (error != 0) {
 1407                         goto out;
 1408                 }
 1409         }
 1410         if (dfacl->state != ace_unused) {
 1411                 error = ace_list_to_aent(dfacl, dfaclentp, dfaclcnt,
 1412                     owner, group, isdir);
 1413                 if (error != 0) {
 1414                         goto out;
 1415                 }
 1416         }
 1417 
 1418 out:
 1419         if (normacl != NULL)
 1420                 ace_list_free(normacl);
 1421         if (dfacl != NULL)
 1422                 ace_list_free(dfacl);
 1423 
 1424         return (error);
 1425 }
 1426 
 1427 static int
 1428 convert_ace_to_aent(ace_t *acebufp, int acecnt, boolean_t isdir,
 1429     uid_t owner, gid_t group, aclent_t **retaclentp, int *retaclcnt)
 1430 {
 1431         int error = 0;
 1432         aclent_t *aclentp, *dfaclentp;
 1433         int aclcnt, dfaclcnt;
 1434         int aclsz, dfaclsz;
 1435 
 1436         error = ln_ace_to_aent(acebufp, acecnt, owner, group,
 1437             &aclentp, &aclcnt, &dfaclentp, &dfaclcnt, isdir);
 1438 
 1439         if (error)
 1440                 return (error);
 1441 
 1442 
 1443         if (dfaclcnt != 0) {
 1444                 /*
 1445                  * Slap aclentp and dfaclentp into a single array.
 1446                  */
 1447                 aclsz = sizeof (aclent_t) * aclcnt;
 1448                 dfaclsz = sizeof (aclent_t) * dfaclcnt;
 1449                 aclentp = cacl_realloc(aclentp, aclsz, aclsz + dfaclsz);
 1450                 if (aclentp != NULL) {
 1451                         (void) memcpy(aclentp + aclcnt, dfaclentp, dfaclsz);
 1452                 } else {
 1453                         error = ENOMEM;
 1454                 }
 1455         }
 1456 
 1457         if (aclentp) {
 1458                 *retaclentp = aclentp;
 1459                 *retaclcnt = aclcnt + dfaclcnt;
 1460         }
 1461 
 1462         if (dfaclentp)
 1463                 cacl_free(dfaclentp, dfaclsz);
 1464 
 1465         return (error);
 1466 }
 1467 
 1468 
 1469 int
 1470 acl_translate(acl_t *aclp, int target_flavor, boolean_t isdir, uid_t owner,
 1471     gid_t group)
 1472 {
 1473         int aclcnt;
 1474         void *acldata;
 1475         int error;
 1476 
 1477         /*
 1478          * See if we need to translate
 1479          */
 1480         if ((target_flavor == _ACL_ACE_ENABLED && aclp->acl_type == ACE_T) ||
 1481             (target_flavor == _ACL_ACLENT_ENABLED &&
 1482             aclp->acl_type == ACLENT_T))
 1483                 return (0);
 1484 
 1485         if (target_flavor == -1) {
 1486                 error = EINVAL;
 1487                 goto out;
 1488         }
 1489 
 1490         if (target_flavor ==  _ACL_ACE_ENABLED &&
 1491             aclp->acl_type == ACLENT_T) {
 1492                 error = convert_aent_to_ace(aclp->acl_aclp,
 1493                     aclp->acl_cnt, isdir, (ace_t **)&acldata, &aclcnt);
 1494                 if (error)
 1495                         goto out;
 1496 
 1497         } else if (target_flavor == _ACL_ACLENT_ENABLED &&
 1498             aclp->acl_type == ACE_T) {
 1499                 error = convert_ace_to_aent(aclp->acl_aclp, aclp->acl_cnt,
 1500                     isdir, owner, group, (aclent_t **)&acldata, &aclcnt);
 1501                 if (error)
 1502                         goto out;
 1503         } else {
 1504                 error = ENOTSUP;
 1505                 goto out;
 1506         }
 1507 
 1508         /*
 1509          * replace old acl with newly translated acl
 1510          */
 1511         cacl_free(aclp->acl_aclp, aclp->acl_cnt * aclp->acl_entry_size);
 1512         aclp->acl_aclp = acldata;
 1513         aclp->acl_cnt = aclcnt;
 1514         if (target_flavor == _ACL_ACE_ENABLED) {
 1515                 aclp->acl_type = ACE_T;
 1516                 aclp->acl_entry_size = sizeof (ace_t);
 1517         } else {
 1518                 aclp->acl_type = ACLENT_T;
 1519                 aclp->acl_entry_size = sizeof (aclent_t);
 1520         }
 1521         return (0);
 1522 
 1523 out:
 1524 
 1525 #if !defined(_KERNEL)
 1526         errno = error;
 1527         return (-1);
 1528 #else
 1529         return (error);
 1530 #endif
 1531 }
 1532 #endif /* !_KERNEL */
 1533 
 1534 #define SET_ACE(acl, index, who, mask, type, flags) { \
 1535         acl[0][index].a_who = (uint32_t)who; \
 1536         acl[0][index].a_type = type; \
 1537         acl[0][index].a_flags = flags; \
 1538         acl[0][index++].a_access_mask = mask; \
 1539 }
 1540 
 1541 void
 1542 acl_trivial_access_masks(mode_t mode, boolean_t isdir, trivial_acl_t *masks)
 1543 {
 1544         uint32_t read_mask = ACE_READ_DATA;
 1545         uint32_t write_mask = ACE_WRITE_DATA|ACE_APPEND_DATA;
 1546         uint32_t execute_mask = ACE_EXECUTE;
 1547 
 1548         (void) isdir;   /* will need this later */
 1549 
 1550         masks->deny1 = 0;
 1551         if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))
 1552                 masks->deny1 |= read_mask;
 1553         if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH)))
 1554                 masks->deny1 |= write_mask;
 1555         if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH)))
 1556                 masks->deny1 |= execute_mask;
 1557 
 1558         masks->deny2 = 0;
 1559         if (!(mode & S_IRGRP) && (mode & S_IROTH))
 1560                 masks->deny2 |= read_mask;
 1561         if (!(mode & S_IWGRP) && (mode & S_IWOTH))
 1562                 masks->deny2 |= write_mask;
 1563         if (!(mode & S_IXGRP) && (mode & S_IXOTH))
 1564                 masks->deny2 |= execute_mask;
 1565 
 1566         masks->allow0 = 0;
 1567         if ((mode & S_IRUSR) && (!(mode & S_IRGRP) && (mode & S_IROTH)))
 1568                 masks->allow0 |= read_mask;
 1569         if ((mode & S_IWUSR) && (!(mode & S_IWGRP) && (mode & S_IWOTH)))
 1570                 masks->allow0 |= write_mask;
 1571         if ((mode & S_IXUSR) && (!(mode & S_IXGRP) && (mode & S_IXOTH)))
 1572                 masks->allow0 |= execute_mask;
 1573 
 1574         masks->owner = ACE_WRITE_ATTRIBUTES|ACE_WRITE_OWNER|ACE_WRITE_ACL|
 1575             ACE_WRITE_NAMED_ATTRS|ACE_READ_ACL|ACE_READ_ATTRIBUTES|
 1576             ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE;
 1577         if (mode & S_IRUSR)
 1578                 masks->owner |= read_mask;
 1579         if (mode & S_IWUSR)
 1580                 masks->owner |= write_mask;
 1581         if (mode & S_IXUSR)
 1582                 masks->owner |= execute_mask;
 1583 
 1584         masks->group = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
 1585             ACE_SYNCHRONIZE;
 1586         if (mode & S_IRGRP)
 1587                 masks->group |= read_mask;
 1588         if (mode & S_IWGRP)
 1589                 masks->group |= write_mask;
 1590         if (mode & S_IXGRP)
 1591                 masks->group |= execute_mask;
 1592 
 1593         masks->everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
 1594             ACE_SYNCHRONIZE;
 1595         if (mode & S_IROTH)
 1596                 masks->everyone |= read_mask;
 1597         if (mode & S_IWOTH)
 1598                 masks->everyone |= write_mask;
 1599         if (mode & S_IXOTH)
 1600                 masks->everyone |= execute_mask;
 1601 }
 1602 
 1603 int
 1604 acl_trivial_create(mode_t mode, boolean_t isdir, ace_t **acl, int *count)
 1605 {
 1606         int             index = 0;
 1607         int             error;
 1608         trivial_acl_t   masks;
 1609 
 1610         *count = 3;
 1611         acl_trivial_access_masks(mode, isdir, &masks);
 1612 
 1613         if (masks.allow0)
 1614                 (*count)++;
 1615         if (masks.deny1)
 1616                 (*count)++;
 1617         if (masks.deny2)
 1618                 (*count)++;
 1619 
 1620         if ((error = cacl_malloc((void **)acl, *count * sizeof (ace_t))) != 0)
 1621                 return (error);
 1622 
 1623         if (masks.allow0) {
 1624                 SET_ACE(acl, index, -1, masks.allow0,
 1625                     ACE_ACCESS_ALLOWED_ACE_TYPE, ACE_OWNER);
 1626         }
 1627         if (masks.deny1) {
 1628                 SET_ACE(acl, index, -1, masks.deny1,
 1629                     ACE_ACCESS_DENIED_ACE_TYPE, ACE_OWNER);
 1630         }
 1631         if (masks.deny2) {
 1632                 SET_ACE(acl, index, -1, masks.deny2,
 1633                     ACE_ACCESS_DENIED_ACE_TYPE, ACE_GROUP|ACE_IDENTIFIER_GROUP);
 1634         }
 1635 
 1636         SET_ACE(acl, index, -1, masks.owner, ACE_ACCESS_ALLOWED_ACE_TYPE,
 1637             ACE_OWNER);
 1638         SET_ACE(acl, index, -1, masks.group, ACE_ACCESS_ALLOWED_ACE_TYPE,
 1639             ACE_IDENTIFIER_GROUP|ACE_GROUP);
 1640         SET_ACE(acl, index, -1, masks.everyone, ACE_ACCESS_ALLOWED_ACE_TYPE,
 1641             ACE_EVERYONE);
 1642 
 1643         return (0);
 1644 }
 1645 
 1646 /*
 1647  * ace_trivial:
 1648  * determine whether an ace_t acl is trivial
 1649  *
 1650  * Trivialness implies that the acl is composed of only
 1651  * owner, group, everyone entries.  ACL can't
 1652  * have read_acl denied, and write_owner/write_acl/write_attributes
 1653  * can only be owner@ entry.
 1654  */
 1655 int
 1656 ace_trivial_common(void *acep, int aclcnt,
 1657     uintptr_t (*walk)(void *, uintptr_t, int aclcnt,
 1658     uint16_t *, uint16_t *, uint32_t *))
 1659 {
 1660         uint16_t flags;
 1661         uint32_t mask;
 1662         uint16_t type;
 1663         uintptr_t cookie = 0;
 1664 
 1665         while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask))) {
 1666                 switch (flags & ACE_TYPE_FLAGS) {
 1667                 case ACE_OWNER:
 1668                 case ACE_GROUP|ACE_IDENTIFIER_GROUP:
 1669                 case ACE_EVERYONE:
 1670                         break;
 1671                 default:
 1672                         return (1);
 1673 
 1674                 }
 1675 
 1676                 if (flags & (ACE_FILE_INHERIT_ACE|
 1677                     ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|
 1678                     ACE_INHERIT_ONLY_ACE))
 1679                         return (1);
 1680 
 1681                 /*
 1682                  * Special check for some special bits
 1683                  *
 1684                  * Don't allow anybody to deny reading basic
 1685                  * attributes or a files ACL.
 1686                  */
 1687                 if ((mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) &&
 1688                     (type == ACE_ACCESS_DENIED_ACE_TYPE))
 1689                         return (1);
 1690 
 1691                 /*
 1692                  * Delete permissions are never set by default
 1693                  */
 1694                 if (mask & (ACE_DELETE|ACE_DELETE_CHILD))
 1695                         return (1);
 1696                 /*
 1697                  * only allow owner@ to have
 1698                  * write_acl/write_owner/write_attributes/write_xattr/
 1699                  */
 1700                 if (type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
 1701                     (!(flags & ACE_OWNER) && (mask &
 1702                     (ACE_WRITE_OWNER|ACE_WRITE_ACL| ACE_WRITE_ATTRIBUTES|
 1703                     ACE_WRITE_NAMED_ATTRS))))
 1704                         return (1);
 1705 
 1706         }
 1707         return (0);
 1708 }

Cache object: ec5fd2c4276eec2d43baacac9b579405


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