ACL related changes
[zfs.git] / module / zfs / zfs_acl.c
index 3efd4f8..45ec206 100644 (file)
@@ -22,7 +22,6 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#ifdef HAVE_ZPL
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -53,7 +52,6 @@
 #include <sys/zap.h>
 #include <sys/sa.h>
 #include "fs/fs_subr.h"
-#include <acl/acl_common.h>
 
 #define        ALLOW   ACE_ACCESS_ALLOWED_ACE_TYPE
 #define        DENY    ACE_ACCESS_DENIED_ACE_TYPE
@@ -644,13 +642,6 @@ zfs_ace_walk(void *datap, uint64_t cookie, int aclcnt,
        return ((uint64_t)(uintptr_t)acep);
 }
 
-static zfs_acl_node_t *
-zfs_acl_curr_node(zfs_acl_t *aclp)
-{
-       ASSERT(aclp->z_curr_node);
-       return (aclp->z_curr_node);
-}
-
 /*
  * Copy ACE to internal ZFS format.
  * While processing the ACL each ACE will be validated for correctness.
@@ -1173,6 +1164,126 @@ zfs_acl_chown_setattr(znode_t *zp)
        return (error);
 }
 
+static void
+acl_trivial_access_masks(mode_t mode, uint32_t *allow0, uint32_t *deny1,
+    uint32_t *deny2, uint32_t *owner, uint32_t *group, uint32_t *everyone)
+{
+       *deny1 = *deny2 = *allow0 = *group = 0;
+
+       if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))
+               *deny1 |= ACE_READ_DATA;
+       if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH)))
+               *deny1 |= ACE_WRITE_DATA;
+       if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH)))
+               *deny1 |= ACE_EXECUTE;
+
+       if (!(mode & S_IRGRP) && (mode & S_IROTH))
+               *deny2 = ACE_READ_DATA;
+       if (!(mode & S_IWGRP) && (mode & S_IWOTH))
+               *deny2 |= ACE_WRITE_DATA;
+       if (!(mode & S_IXGRP) && (mode & S_IXOTH))
+               *deny2 |= ACE_EXECUTE;
+
+       if ((mode & S_IRUSR) && (!(mode & S_IRGRP) && (mode & S_IROTH)))
+               *allow0 |= ACE_READ_DATA;
+       if ((mode & S_IWUSR) && (!(mode & S_IWGRP) && (mode & S_IWOTH)))
+               *allow0 |= ACE_WRITE_DATA;
+       if ((mode & S_IXUSR) && (!(mode & S_IXGRP) && (mode & S_IXOTH)))
+               *allow0 |= ACE_EXECUTE;
+
+       *owner = ACE_WRITE_ATTRIBUTES|ACE_WRITE_OWNER|ACE_WRITE_ACL|
+           ACE_WRITE_NAMED_ATTRS|ACE_READ_ACL|ACE_READ_ATTRIBUTES|
+           ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE;
+       if (mode & S_IRUSR)
+               *owner |= ACE_READ_DATA;
+       if (mode & S_IWUSR)
+               *owner |= ACE_WRITE_DATA|ACE_APPEND_DATA;
+       if (mode & S_IXUSR)
+               *owner |= ACE_EXECUTE;
+
+       *group = ACE_READ_ACL|ACE_READ_ATTRIBUTES| ACE_READ_NAMED_ATTRS|
+           ACE_SYNCHRONIZE;
+       if (mode & S_IRGRP)
+               *group |= ACE_READ_DATA;
+       if (mode & S_IWGRP)
+               *group |= ACE_WRITE_DATA|ACE_APPEND_DATA;
+       if (mode & S_IXGRP)
+               *group |= ACE_EXECUTE;
+
+       *everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES| ACE_READ_NAMED_ATTRS|
+           ACE_SYNCHRONIZE;
+       if (mode & S_IROTH)
+               *everyone |= ACE_READ_DATA;
+       if (mode & S_IWOTH)
+               *everyone |= ACE_WRITE_DATA|ACE_APPEND_DATA;
+       if (mode & S_IXOTH)
+               *everyone |= ACE_EXECUTE;
+}
+
+/*
+ * ace_trivial:
+ * determine whether an ace_t acl is trivial
+ *
+ * Trivialness implies that the acl is composed of only
+ * owner, group, everyone entries.  ACL can't
+ * have read_acl denied, and write_owner/write_acl/write_attributes
+ * can only be owner@ entry.
+ */
+static int
+ace_trivial_common(void *acep, int aclcnt,
+    uint64_t (*walk)(void *, uint64_t, int aclcnt,
+    uint16_t *, uint16_t *, uint32_t *))
+{
+       uint16_t flags;
+       uint32_t mask;
+       uint16_t type;
+       uint64_t cookie = 0;
+
+       while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask))) {
+               switch (flags & ACE_TYPE_FLAGS) {
+               case ACE_OWNER:
+               case ACE_GROUP|ACE_IDENTIFIER_GROUP:
+               case ACE_EVERYONE:
+                       break;
+               default:
+                       return (1);
+               }
+
+               if (flags & (ACE_FILE_INHERIT_ACE|
+                   ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|
+                   ACE_INHERIT_ONLY_ACE))
+                       return (1);
+
+               /*
+                * Special check for some special bits
+                *
+                * Don't allow anybody to deny reading basic
+                * attributes or a files ACL.
+                */
+               if ((mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) &&
+                   (type == ACE_ACCESS_DENIED_ACE_TYPE))
+                       return (1);
+
+               /*
+                * Delete permissions are never set by default
+                */
+               if (mask & (ACE_DELETE|ACE_DELETE_CHILD))
+                       return (1);
+               /*
+                * only allow owner@ to have
+                * write_acl/write_owner/write_attributes/write_xattr/
+                */
+               if (type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
+                   (!(flags & ACE_OWNER) && (mask &
+                   (ACE_WRITE_OWNER|ACE_WRITE_ACL| ACE_WRITE_ATTRIBUTES|
+                   ACE_WRITE_NAMED_ATTRS))))
+                       return (1);
+
+       }
+
+       return (0);
+}
+
 /*
  * common code for setting ACLs.
  *
@@ -1332,73 +1443,6 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
        return (sa_bulk_update(zp->z_sa_hdl, bulk, count, tx));
 }
 
-/*
- * Update access mask for prepended ACE
- *
- * This applies the "groupmask" value for aclmode property.
- */
-static void
-zfs_acl_prepend_fixup(zfs_acl_t *aclp, void  *acep, void  *origacep,
-    mode_t mode, uint64_t owner)
-{
-       int     rmask, wmask, xmask;
-       int     user_ace;
-       uint16_t aceflags;
-       uint32_t origmask, acepmask;
-       uint64_t fuid;
-
-       aceflags = aclp->z_ops.ace_flags_get(acep);
-       fuid = aclp->z_ops.ace_who_get(acep);
-       origmask = aclp->z_ops.ace_mask_get(origacep);
-       acepmask = aclp->z_ops.ace_mask_get(acep);
-
-       user_ace = (!(aceflags &
-           (ACE_OWNER|ACE_GROUP|ACE_IDENTIFIER_GROUP)));
-
-       if (user_ace && (fuid == owner)) {
-               rmask = S_IRUSR;
-               wmask = S_IWUSR;
-               xmask = S_IXUSR;
-       } else {
-               rmask = S_IRGRP;
-               wmask = S_IWGRP;
-               xmask = S_IXGRP;
-       }
-
-       if (origmask & ACE_READ_DATA) {
-               if (mode & rmask) {
-                       acepmask &= ~ACE_READ_DATA;
-               } else {
-                       acepmask |= ACE_READ_DATA;
-               }
-       }
-
-       if (origmask & ACE_WRITE_DATA) {
-               if (mode & wmask) {
-                       acepmask &= ~ACE_WRITE_DATA;
-               } else {
-                       acepmask |= ACE_WRITE_DATA;
-               }
-       }
-
-       if (origmask & ACE_APPEND_DATA) {
-               if (mode & wmask) {
-                       acepmask &= ~ACE_APPEND_DATA;
-               } else {
-                       acepmask |= ACE_APPEND_DATA;
-               }
-       }
-
-       if (origmask & ACE_EXECUTE) {
-               if (mode & xmask) {
-                       acepmask &= ~ACE_EXECUTE;
-               } else {
-                       acepmask |= ACE_EXECUTE;
-               }
-       }
-       aclp->z_ops.ace_mask_set(acep, acepmask);
-}
-
 static void
 zfs_acl_chmod(zfsvfs_t *zfsvfs, uint64_t mode, zfs_acl_t *aclp)
 {
@@ -1681,7 +1725,9 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
        int             error;
        zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
        zfs_acl_t       *paclp;
+#ifdef HAVE_KSID
        gid_t           gid;
+#endif /* HAVE_KSID */
        boolean_t       need_chmod = B_TRUE;
        boolean_t       inherited = B_FALSE;
 
@@ -1692,6 +1738,10 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
                if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, cr,
                    &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0)
                        return (error);
+
+       acl_ids->z_fuid = vap->va_uid;
+       acl_ids->z_fgid = vap->va_gid;
+#ifdef HAVE_KSID
        /*
         * Determine uid and gid.
         */
@@ -1745,6 +1795,7 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
                        }
                }
        }
+#endif /* HAVE_KSID */
 
        /*
         * If we're creating a directory, and the parent directory has the
@@ -2072,7 +2123,7 @@ top:
        if (fuidp)
                zfs_fuid_info_free(fuidp);
        dmu_tx_commit(tx);
-done:
+
        mutex_exit(&zp->z_lock);
        mutex_exit(&zp->z_acl_lock);
 
@@ -2748,5 +2799,3 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
 
        return (error);
 }
-
-#endif /* HAVE_ZPL */