summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorMark Shellenbaum <Mark.Shellenbaum@Sun.COM>2010-04-14 13:25:42 -0600
committerMark Shellenbaum <Mark.Shellenbaum@Sun.COM>2010-04-14 13:25:42 -0600
commit27dd1e87cd3d939264769dd4af7e6a529cde001f (patch)
tree71be7e9b44ec87814159094591ebf5680350824a /usr/src
parent1cfa752f4e24c34133009b0f6c139127a5c461de (diff)
downloadillumos-joyent-27dd1e87cd3d939264769dd4af7e6a529cde001f.tar.gz
PSARC/2010/029 Improved ACL interoperability
6923083 ZFS/NFS/SMB ACL interoperability changes
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/ls/ls.c11
-rw-r--r--usr/src/common/acl/acl_common.c359
-rw-r--r--usr/src/common/acl/acl_common.h10
-rw-r--r--usr/src/common/zfs/zfs_prop.c20
-rw-r--r--usr/src/lib/libsec/common/aclutils.c20
-rw-r--r--usr/src/lib/libzfs_jni/common/libzfs_jni_property.c15
-rw-r--r--usr/src/uts/common/fs/fs_subr.c19
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_acl.h7
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h4
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_acl.c593
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vfsops.c14
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c53
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_znode.c3
-rw-r--r--usr/src/uts/common/sys/fs/zfs.h5
14 files changed, 421 insertions, 712 deletions
diff --git a/usr/src/cmd/ls/ls.c b/usr/src/cmd/ls/ls.c
index 5358e0e01d..a509fa1496 100644
--- a/usr/src/cmd/ls/ls.c
+++ b/usr/src/cmd/ls/ls.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -1677,12 +1676,13 @@ record_ancestry(char *file, struct stat *pstatb, struct lbuf *rep,
#define IS_TYPE_ALLOWED(type) ((type) == ACE_ACCESS_ALLOWED_ACE_TYPE)
int
-grp_mask_to_mode(acl_t *acep)
+grp_mask_to_mode(struct lbuf *p)
{
int mode = 0, seen = 0;
int acecnt;
int flags;
ace_t *ap;
+ acl_t *acep = p->aclp;
acecnt = acl_cnt(acep);
for (ap = (ace_t *)acl_data(acep); acecnt--; ap++) {
@@ -1700,7 +1700,8 @@ grp_mask_to_mode(acl_t *acep)
* that will be the group mode bit.
*/
flags = ap->a_flags & ACE_TYPE_FLAGS;
- if (flags == OWNED_GROUP || flags == ACE_EVERYONE) {
+ if (flags == OWNED_GROUP || (flags == ACE_IDENTIFIER_GROUP &&
+ ap->a_who == p->lgid) || flags == ACE_EVERYONE) {
if (ap->a_access_mask & ACE_READ_DATA) {
if (!(seen & S_IRGRP)) {
seen |= S_IRGRP;
@@ -2052,7 +2053,7 @@ gstat(char *file, int argfl, struct ditem *myparent)
} else if (acl_type(rep->aclp) == ACE_T) {
int mode;
- mode = grp_mask_to_mode(rep->aclp);
+ mode = grp_mask_to_mode(rep);
rep->lflags &= ~S_IRWXG;
rep->lflags |= mode;
}
diff --git a/usr/src/common/acl/acl_common.c b/usr/src/common/acl/acl_common.c
index 94a9fc9c11..eafc47d10f 100644
--- a/usr/src/common/acl/acl_common.c
+++ b/usr/src/common/acl/acl_common.c
@@ -19,12 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/avl.h>
@@ -149,166 +146,6 @@ typedef struct ace_list {
int seen; /* bitmask of all aclent_t a_type values seen */
} ace_list_t;
-ace_t trivial_acl[] = {
- {(uid_t)-1, 0, ACE_OWNER, ACE_ACCESS_DENIED_ACE_TYPE},
- {(uid_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES|
- ACE_WRITE_NAMED_ATTRS, ACE_OWNER, ACE_ACCESS_ALLOWED_ACE_TYPE},
- {(uid_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP,
- ACE_ACCESS_DENIED_ACE_TYPE},
- {(uid_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP,
- ACE_ACCESS_ALLOWED_ACE_TYPE},
- {(uid_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER| ACE_WRITE_ATTRIBUTES|
- ACE_WRITE_NAMED_ATTRS, ACE_EVERYONE, ACE_ACCESS_DENIED_ACE_TYPE},
- {(uid_t)-1, ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
- ACE_SYNCHRONIZE, ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE}
-};
-
-
-void
-adjust_ace_pair_common(void *pair, size_t access_off,
- size_t pairsize, mode_t mode)
-{
- char *datap = (char *)pair;
- uint32_t *amask0 = (uint32_t *)(uintptr_t)(datap + access_off);
- uint32_t *amask1 = (uint32_t *)(uintptr_t)(datap + pairsize +
- access_off);
- if (mode & S_IROTH)
- *amask1 |= ACE_READ_DATA;
- else
- *amask0 |= ACE_READ_DATA;
- if (mode & S_IWOTH)
- *amask1 |= ACE_WRITE_DATA|ACE_APPEND_DATA;
- else
- *amask0 |= ACE_WRITE_DATA|ACE_APPEND_DATA;
- if (mode & S_IXOTH)
- *amask1 |= ACE_EXECUTE;
- else
- *amask0 |= ACE_EXECUTE;
-}
-
-void
-adjust_ace_pair(ace_t *pair, mode_t mode)
-{
- adjust_ace_pair_common(pair, offsetof(ace_t, a_access_mask),
- sizeof (ace_t), mode);
-}
-
-static void
-ace_allow_deny_helper(uint16_t type, boolean_t *allow, boolean_t *deny)
-{
- if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
- *allow = B_TRUE;
- else if (type == ACE_ACCESS_DENIED_ACE_TYPE)
- *deny = B_TRUE;
-}
-
-/*
- * 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.
- */
-int
-ace_trivial_common(void *acep, int aclcnt,
- uint64_t (*walk)(void *, uint64_t, int aclcnt,
- uint16_t *, uint16_t *, uint32_t *))
-{
- boolean_t owner_allow = B_FALSE;
- boolean_t group_allow = B_FALSE;
- boolean_t everyone_allow = B_FALSE;
- boolean_t owner_deny = B_FALSE;
- boolean_t group_deny = B_FALSE;
- boolean_t everyone_deny = B_FALSE;
- 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:
- if (group_allow || group_deny || everyone_allow ||
- everyone_deny)
- return (1);
- ace_allow_deny_helper(type, &owner_allow, &owner_deny);
- break;
- case ACE_GROUP|ACE_IDENTIFIER_GROUP:
- if (everyone_allow || everyone_deny &&
- (!owner_allow && !owner_deny))
- return (1);
- ace_allow_deny_helper(type, &group_allow, &group_deny);
- break;
-
- case ACE_EVERYONE:
- if (!owner_allow && !owner_deny &&
- !group_allow && !group_deny)
- return (1);
- ace_allow_deny_helper(type,
- &everyone_allow, &everyone_deny);
- 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);
-
- /*
- * Allow on owner@ to allow
- * write_acl/write_owner/write_attributes
- */
- if (type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
- (!(flags & ACE_OWNER) && (mask &
- (ACE_WRITE_OWNER|ACE_WRITE_ACL|ACE_WRITE_ATTRIBUTES))))
- return (1);
-
- }
-
- if (!owner_allow || !owner_deny || !group_allow || !group_deny ||
- !everyone_allow || !everyone_deny)
- return (1);
-
- return (0);
-}
-
-uint64_t
-ace_walk(void *datap, uint64_t cookie, int aclcnt, uint16_t *flags,
- uint16_t *type, uint32_t *mask)
-{
- ace_t *acep = datap;
-
- if (cookie >= aclcnt)
- return (0);
-
- *flags = acep[cookie].a_flags;
- *type = acep[cookie].a_type;
- *mask = acep[cookie++].a_access_mask;
-
- return (cookie);
-}
-
-int
-ace_trivial(ace_t *acep, int aclcnt)
-{
- return (ace_trivial_common(acep, aclcnt, ace_walk));
-}
-
/*
* Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
* v = Ptr to array/vector of objs
@@ -1722,3 +1559,197 @@ out:
return (error);
#endif
}
+
+#define SET_ACE(acl, index, who, mask, type, flags) { \
+ acl[0][index].a_who = (uint32_t)who; \
+ acl[0][index].a_type = type; \
+ acl[0][index].a_flags = flags; \
+ acl[0][index++].a_access_mask = mask; \
+}
+
+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;
+}
+
+int
+acl_trivial_create(mode_t mode, ace_t **acl, int *count)
+{
+ uint32_t deny1, deny2;
+ uint32_t allow0;
+ uint32_t owner, group, everyone;
+ int index = 0;
+ int error;
+
+ *count = 3;
+ acl_trivial_access_masks(mode, &allow0, &deny1, &deny2, &owner, &group,
+ &everyone);
+
+ if (allow0)
+ (*count)++;
+ if (deny1)
+ (*count)++;
+ if (deny2)
+ (*count)++;
+
+ if ((error = cacl_malloc((void **)acl, *count * sizeof (ace_t))) != 0)
+ return (error);
+
+ if (allow0) {
+ SET_ACE(acl, index, -1, allow0, ACE_ACCESS_ALLOWED_ACE_TYPE,
+ ACE_OWNER);
+ }
+ if (deny1) {
+ SET_ACE(acl, index, -1, deny1, ACE_ACCESS_DENIED_ACE_TYPE,
+ ACE_OWNER);
+ }
+ if (deny2) {
+ SET_ACE(acl, index, -1, deny2, ACE_ACCESS_DENIED_ACE_TYPE,
+ ACE_GROUP|ACE_IDENTIFIER_GROUP);
+ }
+
+ SET_ACE(acl, index, -1, owner, ACE_ACCESS_ALLOWED_ACE_TYPE, ACE_OWNER);
+ SET_ACE(acl, index, -1, group, ACE_ACCESS_ALLOWED_ACE_TYPE,
+ ACE_IDENTIFIER_GROUP|ACE_GROUP);
+ SET_ACE(acl, index, -1, everyone, ACE_ACCESS_ALLOWED_ACE_TYPE,
+ ACE_EVERYONE);
+
+ return (0);
+}
+
+/*
+ * 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.
+ */
+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);
+}
+
+uint64_t
+ace_walk(void *datap, uint64_t cookie, int aclcnt, uint16_t *flags,
+ uint16_t *type, uint32_t *mask)
+{
+ ace_t *acep = datap;
+
+ if (cookie >= aclcnt)
+ return (0);
+
+ *flags = acep[cookie].a_flags;
+ *type = acep[cookie].a_type;
+ *mask = acep[cookie++].a_access_mask;
+
+ return (cookie);
+}
+
+int
+ace_trivial(ace_t *acep, int aclcnt)
+{
+ return (ace_trivial_common(acep, aclcnt, ace_walk));
+}
diff --git a/usr/src/common/acl/acl_common.h b/usr/src/common/acl/acl_common.h
index 84bd04f52f..f76cbd3b45 100644
--- a/usr/src/common/acl/acl_common.h
+++ b/usr/src/common/acl/acl_common.h
@@ -19,16 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _ACL_COMMON_H
#define _ACL_COMMON_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-
#include <sys/types.h>
#include <sys/acl.h>
#include <sys/stat.h>
@@ -52,7 +48,9 @@ extern int acl_translate(acl_t *aclp, int target_flavor,
int isdir, uid_t owner, gid_t group);
void ksort(caddr_t v, int n, int s, int (*f)());
int cmp2acls(void *a, void *b);
-
+int acl_trivial_create(mode_t mode, ace_t **acl, int *count);
+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);
#ifdef __cplusplus
}
diff --git a/usr/src/common/zfs/zfs_prop.c b/usr/src/common/zfs/zfs_prop.c
index a7b36dd080..8c87292bc6 100644
--- a/usr/src/common/zfs/zfs_prop.c
+++ b/usr/src/common/zfs/zfs_prop.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/zio.h>
@@ -103,13 +102,6 @@ zfs_prop_init(void)
{ NULL }
};
- static zprop_index_t acl_mode_table[] = {
- { "discard", ZFS_ACL_DISCARD },
- { "groupmask", ZFS_ACL_GROUPMASK },
- { "passthrough", ZFS_ACL_PASSTHROUGH },
- { NULL }
- };
-
static zprop_index_t acl_inherit_table[] = {
{ "discard", ZFS_ACL_DISCARD },
{ "noallow", ZFS_ACL_NOALLOW },
@@ -202,9 +194,6 @@ zfs_prop_init(void)
zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN,
PROP_INHERIT, ZFS_TYPE_FILESYSTEM,
"hidden | visible", "SNAPDIR", snapdir_table);
- zprop_register_index(ZFS_PROP_ACLMODE, "aclmode", ZFS_ACL_GROUPMASK,
- PROP_INHERIT, ZFS_TYPE_FILESYSTEM,
- "discard | groupmask | passthrough", "ACLMODE", acl_mode_table);
zprop_register_index(ZFS_PROP_ACLINHERIT, "aclinherit",
ZFS_ACL_RESTRICTED, PROP_INHERIT, ZFS_TYPE_FILESYSTEM,
"discard | noallow | restricted | passthrough | passthrough-x",
@@ -368,6 +357,13 @@ zfs_prop_init(void)
zprop_register_hidden(ZFS_PROP_OBJSETID, "objsetid", PROP_TYPE_NUMBER,
PROP_READONLY, ZFS_TYPE_DATASET, "OBJSETID");
+ /*
+ * Property to be removed once libbe is integrated
+ */
+ zprop_register_hidden(ZFS_PROP_PRIVATE, "priv_prop",
+ PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_FILESYSTEM,
+ "PRIV_PROP");
+
/* oddball properties */
zprop_register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0,
NULL, PROP_READONLY, ZFS_TYPE_DATASET,
diff --git a/usr/src/lib/libsec/common/aclutils.c b/usr/src/lib/libsec/common/aclutils.c
index 2850c4dd1a..afe36a3aaa 100644
--- a/usr/src/lib/libsec/common/aclutils.c
+++ b/usr/src/lib/libsec/common/aclutils.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -391,7 +390,7 @@ acl_strip(const char *file, uid_t owner, gid_t group, mode_t mode)
{
int error = 0;
aclent_t min_acl[MIN_ACL_ENTRIES];
- ace_t min_ace_acl[6]; /* owner, group, everyone + complement denies */
+ ace_t *min_ace_acl;
int acl_flavor;
int aclcnt;
@@ -420,16 +419,11 @@ acl_strip(const char *file, uid_t owner, gid_t group, mode_t mode)
aclcnt = 4;
error = acl(file, SETACL, aclcnt, min_acl);
} else if (acl_flavor & _ACL_ACE_ENABLED) {
- (void) memcpy(min_ace_acl, trivial_acl, sizeof (ace_t) * 6);
-
- /*
- * Make aces match request mode
- */
- adjust_ace_pair(&min_ace_acl[0], (mode & 0700) >> 6);
- adjust_ace_pair(&min_ace_acl[2], (mode & 0070) >> 3);
- adjust_ace_pair(&min_ace_acl[4], mode & 0007);
-
- error = acl(file, ACE_SETACL, 6, min_ace_acl);
+ if ((error = acl_trivial_create(mode, &min_ace_acl,
+ &aclcnt)) != 0)
+ return (error);
+ error = acl(file, ACE_SETACL, aclcnt, min_ace_acl);
+ free(min_ace_acl);
} else {
errno = EINVAL;
error = 1;
diff --git a/usr/src/lib/libzfs_jni/common/libzfs_jni_property.c b/usr/src/lib/libzfs_jni/common/libzfs_jni_property.c
index ccf2043234..cce767243b 100644
--- a/usr/src/lib/libzfs_jni/common/libzfs_jni_property.c
+++ b/usr/src/lib/libzfs_jni/common/libzfs_jni_property.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include "libzfs_jni_property.h"
@@ -69,7 +68,6 @@ static jobject create_default_ObjectProperty(
JNIEnv *, zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *);
static jobject str_to_enum_element(JNIEnv *, char *, char *);
static jobject str_to_aclinherit(JNIEnv *, char *);
-static jobject str_to_aclmode(JNIEnv *, char *);
static jobject str_to_checksum(JNIEnv *, char *);
static jobject str_to_compression(JNIEnv *, char *);
static jobject str_to_snapdir(JNIEnv *, char *);
@@ -116,10 +114,6 @@ custom_prop_desct_t props_custom[] = {
ZFSJNI_PACKAGE_DATA "AclInheritProperty",
ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit" },
- { ZFS_PROP_ACLMODE, str_to_aclmode, NULL,
- ZFSJNI_PACKAGE_DATA "AclModeProperty",
- ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode" },
-
{ ZFS_PROP_CHECKSUM, str_to_checksum, NULL,
ZFSJNI_PACKAGE_DATA "ChecksumProperty",
ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum" },
@@ -457,13 +451,6 @@ str_to_aclinherit(JNIEnv *env, char *str)
}
static jobject
-str_to_aclmode(JNIEnv *env, char *str)
-{
- return (str_to_enum_element(env, str,
- ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode"));
-}
-
-static jobject
str_to_checksum(JNIEnv *env, char *str)
{
return (str_to_enum_element(env, str,
diff --git a/usr/src/uts/common/fs/fs_subr.c b/usr/src/uts/common/fs/fs_subr.c
index b1fec8b4ba..1858d0ef30 100644
--- a/usr/src/uts/common/fs/fs_subr.c
+++ b/usr/src/uts/common/fs/fs_subr.c
@@ -23,8 +23,7 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -583,7 +582,6 @@ fs_fab_acl(
caller_context_t *ct)
{
aclent_t *aclentp;
- ace_t *acep;
struct vattr vattr;
int error;
size_t aclsize;
@@ -623,18 +621,12 @@ fs_fab_acl(
aclentp->a_perm = (ushort_t)(0007);
aclentp->a_id = (gid_t)-1; /* Really undefined */
} else if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) {
- aclsize = 6 * sizeof (ace_t);
- vsecattr->vsa_aclcnt = 6;
- vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP);
- vsecattr->vsa_aclentsz = aclsize;
- acep = vsecattr->vsa_aclentp;
- (void) memcpy(acep, trivial_acl, sizeof (ace_t) * 6);
- adjust_ace_pair(acep, (vattr.va_mode & 0700) >> 6);
- adjust_ace_pair(acep + 2, (vattr.va_mode & 0070) >> 3);
- adjust_ace_pair(acep + 4, vattr.va_mode & 0007);
+ VERIFY(0 == acl_trivial_create(vattr.va_mode,
+ (ace_t **)&vsecattr->vsa_aclentp, &vsecattr->vsa_aclcnt));
+ vsecattr->vsa_aclentsz = vsecattr->vsa_aclcnt * sizeof (ace_t);
}
- return (0);
+ return (error);
}
/*
@@ -797,7 +789,6 @@ fs_acl_nontrivial(vnode_t *vp, cred_t *cr)
vsecattr.vsa_dfaclcnt * sizeof (aclent_t));
}
if (acl_flavor & _ACL_ACE_ENABLED) {
-
isnontrivial = ace_trivial(vsecattr.vsa_aclentp,
vsecattr.vsa_aclcnt);
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_acl.h b/usr/src/uts/common/fs/zfs/sys/zfs_acl.h
index ae4fd53a0a..72e868fabb 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_acl.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_acl.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_FS_ZFS_ACL_H
@@ -238,7 +237,9 @@ zfs_acl_t *zfs_acl_alloc(int);
zfs_acl_node_t *zfs_acl_node_alloc(size_t);
void zfs_acl_xform(struct znode *, zfs_acl_t *, cred_t *);
void zfs_acl_data_locator(void **, uint32_t *, uint32_t, boolean_t, void *);
-uint64_t zfs_mode_compute(uint64_t, zfs_acl_t *, uint64_t *);
+uint64_t zfs_mode_compute(uint64_t, zfs_acl_t *,
+ uint64_t *, uint64_t, uint64_t);
+int zfs_acl_chown_setattr(struct znode *);
#endif
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h b/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h
index f920d70ee5..86dcdacc08 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_FS_ZFS_VFSOPS_H
@@ -58,7 +57,6 @@ struct zfsvfs {
boolean_t z_fuid_dirty; /* need to sync fuid table ? */
struct zfs_fuid_info *z_fuid_replay; /* fuid info for replay */
zilog_t *z_log; /* intent log pointer */
- uint_t z_acl_mode; /* acl chmod/mode behavior */
uint_t z_acl_inherit; /* acl inheritance behavior */
zfs_case_t z_case; /* case-sense */
boolean_t z_utf8; /* utf8-only */
diff --git a/usr/src/uts/common/fs/zfs/zfs_acl.c b/usr/src/uts/common/fs/zfs/zfs_acl.c
index 5a24a8ee79..e8bc55b70a 100644
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_acl.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/types.h>
@@ -854,7 +853,8 @@ zfs_set_ace(zfs_acl_t *aclp, void *acep, uint32_t access_mask,
* Also, create FUIDs for any User/Group ACEs
*/
uint64_t
-zfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp, uint64_t *pflags)
+zfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp,
+ uint64_t *pflags, uint64_t fuid, uint64_t fgid)
{
int entry_type;
mode_t mode;
@@ -883,7 +883,8 @@ zfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp, uint64_t *pflags)
entry_type == OWNING_GROUP))
continue;
- if (entry_type == ACE_OWNER) {
+ if (entry_type == ACE_OWNER || (entry_type == 0 &&
+ who == fuid)) {
if ((access_mask & ACE_READ_DATA) &&
(!(seen & S_IRUSR))) {
seen |= S_IRUSR;
@@ -905,7 +906,8 @@ zfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp, uint64_t *pflags)
mode |= S_IXUSR;
}
}
- } else if (entry_type == OWNING_GROUP) {
+ } else if (entry_type == OWNING_GROUP ||
+ (entry_type == ACE_IDENTIFIER_GROUP && who == fgid)) {
if ((access_mask & ACE_READ_DATA) &&
(!(seen & S_IRGRP))) {
seen |= S_IRGRP;
@@ -1102,6 +1104,47 @@ zfs_acl_data_locator(void **dataptr, uint32_t *length, uint32_t buflen,
*length = cb->cb_acl_node->z_size;
}
+
+static int
+zfs_acl_get_owner_fuids(znode_t *zp, uint64_t *fuid, uint64_t *fgid)
+{
+ int count = 0;
+ sa_bulk_attr_t bulk[2];
+ int error;
+
+ if (IS_EPHEMERAL(zp->z_uid) || IS_EPHEMERAL(zp->z_gid)) {
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zp->z_zfsvfs), NULL,
+ &fuid, sizeof (fuid));
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zp->z_zfsvfs), NULL,
+ &fgid, sizeof (fuid));
+ if ((error = sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) != 0) {
+ return (error);
+ }
+ } else {
+ *fuid = zp->z_uid;
+ *fgid = zp->z_gid;
+ }
+ return (0);
+}
+
+int
+zfs_acl_chown_setattr(znode_t *zp)
+{
+ int error;
+ zfs_acl_t *aclp;
+ uint64_t fuid, fgid;
+
+ if ((error = zfs_acl_get_owner_fuids(zp, &fuid, &fgid)) != 0)
+ return (error);
+
+ mutex_enter(&zp->z_acl_lock);
+ if ((error = zfs_acl_node_read(zp, &aclp, B_FALSE)) == 0)
+ zp->z_mode = zfs_mode_compute(zp->z_mode, aclp,
+ &zp->z_pflags, fuid, fgid);
+ mutex_exit(&zp->z_acl_lock);
+ return (error);
+}
+
/*
* common code for setting ACLs.
*
@@ -1120,9 +1163,14 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
sa_bulk_attr_t bulk[5];
uint64_t ctime[2];
int count = 0;
+ uint64_t fuid, fgid;
mode = zp->z_mode;
- mode = zfs_mode_compute(mode, aclp, &zp->z_pflags);
+
+ if ((error = zfs_acl_get_owner_fuids(zp, &fuid, &fgid)) != 0)
+ return (error);
+
+ mode = zfs_mode_compute(mode, aclp, &zp->z_pflags, fuid, fgid);
zp->z_mode = mode;
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,
@@ -1326,314 +1374,64 @@ zfs_acl_prepend_fixup(zfs_acl_t *aclp, void *acep, void *origacep,
aclp->z_ops.ace_mask_set(acep, acepmask);
}
-/*
- * Apply mode to canonical six ACEs.
- */
-static void
-zfs_acl_fixup_canonical_six(zfs_acl_t *aclp, mode_t mode)
-{
- zfs_acl_node_t *aclnode = list_tail(&aclp->z_acl);
- void *acep;
- int maskoff = aclp->z_ops.ace_mask_off();
- size_t abstract_size = aclp->z_ops.ace_abstract_size();
-
- ASSERT(aclnode != NULL);
-
- acep = (void *)((caddr_t)aclnode->z_acldata +
- aclnode->z_size - (abstract_size * 6));
-
- /*
- * Fixup final ACEs to match the mode
- */
-
- adjust_ace_pair_common(acep, maskoff, abstract_size,
- (mode & 0700) >> 6); /* owner@ */
-
- acep = (caddr_t)acep + (abstract_size * 2);
-
- adjust_ace_pair_common(acep, maskoff, abstract_size,
- (mode & 0070) >> 3); /* group@ */
-
- acep = (caddr_t)acep + (abstract_size * 2);
- adjust_ace_pair_common(acep, maskoff,
- abstract_size, mode); /* everyone@ */
-}
-
-
-static int
-zfs_acl_ace_match(zfs_acl_t *aclp, void *acep, int allow_deny,
- int entry_type, int accessmask)
-{
- uint32_t mask = aclp->z_ops.ace_mask_get(acep);
- uint16_t type = aclp->z_ops.ace_type_get(acep);
- uint16_t flags = aclp->z_ops.ace_flags_get(acep);
-
- return (mask == accessmask && type == allow_deny &&
- ((flags & ACE_TYPE_FLAGS) == entry_type));
-}
-
-/*
- * Can prepended ACE be reused?
- */
-static int
-zfs_reuse_deny(zfs_acl_t *aclp, void *acep, void *prevacep)
-{
- int okay_masks;
- uint16_t prevtype;
- uint16_t prevflags;
- uint16_t flags;
- uint32_t mask, prevmask;
-
- if (prevacep == NULL)
- return (B_FALSE);
-
- prevtype = aclp->z_ops.ace_type_get(prevacep);
- prevflags = aclp->z_ops.ace_flags_get(prevacep);
- flags = aclp->z_ops.ace_flags_get(acep);
- mask = aclp->z_ops.ace_mask_get(acep);
- prevmask = aclp->z_ops.ace_mask_get(prevacep);
-
- if (prevtype != DENY)
- return (B_FALSE);
-
- if (prevflags != (flags & ACE_IDENTIFIER_GROUP))
- return (B_FALSE);
-
- okay_masks = (mask & OKAY_MASK_BITS);
-
- if (prevmask & ~okay_masks)
- return (B_FALSE);
-
- return (B_TRUE);
-}
-
-
-/*
- * Insert new ACL node into chain of zfs_acl_node_t's
- *
- * This will result in two possible results.
- * 1. If the ACL is currently just a single zfs_acl_node and
- * we are prepending the entry then current acl node will have
- * a new node inserted above it.
- *
- * 2. If we are inserting in the middle of current acl node then
- * the current node will be split in two and new node will be inserted
- * in between the two split nodes.
- */
-static zfs_acl_node_t *
-zfs_acl_ace_insert(zfs_acl_t *aclp, void *acep)
-{
- zfs_acl_node_t *newnode;
- zfs_acl_node_t *trailernode = NULL;
- zfs_acl_node_t *currnode = zfs_acl_curr_node(aclp);
- int curr_idx = aclp->z_curr_node->z_ace_idx;
- int trailer_count;
- size_t oldsize;
-
- newnode = zfs_acl_node_alloc(aclp->z_ops.ace_size(acep));
- newnode->z_ace_count = 1;
-
- oldsize = currnode->z_size;
-
- if (curr_idx != 1) {
- trailernode = zfs_acl_node_alloc(0);
- trailernode->z_acldata = acep;
-
- trailer_count = currnode->z_ace_count - curr_idx + 1;
- currnode->z_ace_count = curr_idx - 1;
- currnode->z_size = (caddr_t)acep - (caddr_t)currnode->z_acldata;
- trailernode->z_size = oldsize - currnode->z_size;
- trailernode->z_ace_count = trailer_count;
- }
-
- aclp->z_acl_count += 1;
- aclp->z_acl_bytes += aclp->z_ops.ace_size(acep);
-
- if (curr_idx == 1)
- list_insert_before(&aclp->z_acl, currnode, newnode);
- else
- list_insert_after(&aclp->z_acl, currnode, newnode);
- if (trailernode) {
- list_insert_after(&aclp->z_acl, newnode, trailernode);
- aclp->z_curr_node = trailernode;
- trailernode->z_ace_idx = 1;
- }
-
- return (newnode);
-}
-
-/*
- * Prepend deny ACE
- */
-static void *
-zfs_acl_prepend_deny(uint64_t uid, zfs_acl_t *aclp, void *acep,
- mode_t mode)
-{
- zfs_acl_node_t *aclnode;
- void *newacep;
- uint64_t fuid;
- uint16_t flags;
-
- aclnode = zfs_acl_ace_insert(aclp, acep);
- newacep = aclnode->z_acldata;
- fuid = aclp->z_ops.ace_who_get(acep);
- flags = aclp->z_ops.ace_flags_get(acep);
- zfs_set_ace(aclp, newacep, 0, DENY, fuid, (flags & ACE_TYPE_FLAGS));
- zfs_acl_prepend_fixup(aclp, newacep, acep, mode, uid);
-
- return (newacep);
-}
-
-/*
- * Split an inherited ACE into inherit_only ACE
- * and original ACE with inheritance flags stripped off.
- */
static void
-zfs_acl_split_ace(zfs_acl_t *aclp, zfs_ace_hdr_t *acep)
+zfs_acl_chmod(zfsvfs_t *zfsvfs, uint64_t mode, zfs_acl_t *aclp)
{
- zfs_acl_node_t *aclnode;
- zfs_acl_node_t *currnode;
- void *newacep;
- uint16_t type, flags;
- uint32_t mask;
- uint64_t fuid;
-
- type = aclp->z_ops.ace_type_get(acep);
- flags = aclp->z_ops.ace_flags_get(acep);
- mask = aclp->z_ops.ace_mask_get(acep);
- fuid = aclp->z_ops.ace_who_get(acep);
-
- aclnode = zfs_acl_ace_insert(aclp, acep);
- newacep = aclnode->z_acldata;
-
- aclp->z_ops.ace_type_set(newacep, type);
- aclp->z_ops.ace_flags_set(newacep, flags | ACE_INHERIT_ONLY_ACE);
- aclp->z_ops.ace_mask_set(newacep, mask);
- aclp->z_ops.ace_type_set(newacep, type);
- aclp->z_ops.ace_who_set(newacep, fuid);
- aclp->z_next_ace = acep;
- flags &= ~ALL_INHERIT;
- aclp->z_ops.ace_flags_set(acep, flags);
- currnode = zfs_acl_curr_node(aclp);
- ASSERT(currnode->z_ace_idx >= 1);
- currnode->z_ace_idx -= 1;
-}
-
-/*
- * Are ACES started at index i, the canonical six ACES?
- */
-static int
-zfs_have_canonical_six(zfs_acl_t *aclp)
-{
- void *acep;
- zfs_acl_node_t *aclnode = list_tail(&aclp->z_acl);
- int i = 0;
- size_t abstract_size = aclp->z_ops.ace_abstract_size();
-
- ASSERT(aclnode != NULL);
-
- if (aclnode->z_ace_count < 6)
- return (0);
-
- acep = (void *)((caddr_t)aclnode->z_acldata +
- aclnode->z_size - (aclp->z_ops.ace_abstract_size() * 6));
-
- if ((zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++),
- DENY, ACE_OWNER, 0) &&
- zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++),
- ALLOW, ACE_OWNER, OWNER_ALLOW_MASK) &&
- zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), DENY,
- OWNING_GROUP, 0) && zfs_acl_ace_match(aclp, (caddr_t)acep +
- (abstract_size * i++),
- ALLOW, OWNING_GROUP, 0) &&
- zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++),
- DENY, ACE_EVERYONE, EVERYONE_DENY_MASK) &&
- zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++),
- ALLOW, ACE_EVERYONE, EVERYONE_ALLOW_MASK))) {
- return (1);
- } else {
- return (0);
- }
-}
-
-
-/*
- * Apply step 1g, to group entries
- *
- * Need to deal with corner case where group may have
- * greater permissions than owner. If so then limit
- * group permissions, based on what extra permissions
- * group has.
- */
-static void
-zfs_fixup_group_entries(zfs_acl_t *aclp, void *acep, void *prevacep,
- mode_t mode)
-{
- uint32_t prevmask = aclp->z_ops.ace_mask_get(prevacep);
- uint32_t mask = aclp->z_ops.ace_mask_get(acep);
- uint16_t prevflags = aclp->z_ops.ace_flags_get(prevacep);
- mode_t extramode = (mode >> 3) & 07;
- mode_t ownermode = (mode >> 6);
-
- if (prevflags & ACE_IDENTIFIER_GROUP) {
-
- extramode &= ~ownermode;
-
- if (extramode) {
- if (extramode & S_IROTH) {
- prevmask &= ~ACE_READ_DATA;
- mask &= ~ACE_READ_DATA;
- }
- if (extramode & S_IWOTH) {
- prevmask &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
- mask &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
- }
- if (extramode & S_IXOTH) {
- prevmask &= ~ACE_EXECUTE;
- mask &= ~ACE_EXECUTE;
- }
- }
- }
- aclp->z_ops.ace_mask_set(acep, mask);
- aclp->z_ops.ace_mask_set(prevacep, prevmask);
-}
-
-/*
- * Apply the chmod algorithm as described
- * in PSARC/2002/240
- */
-static void
-zfs_acl_chmod(zfsvfs_t *zfsvfs, uint64_t uid,
- uint64_t mode, zfs_acl_t *aclp)
-{
- void *acep = NULL, *prevacep = NULL;
+ void *acep = NULL;
uint64_t who;
- int i;
+ int new_count, new_bytes;
+ int ace_size;
int entry_type;
- int reuse_deny;
- int need_canonical_six = 1;
uint16_t iflags, type;
uint32_t access_mask;
-
- /*
- * If discard then just discard all ACL nodes which
- * represent the ACEs.
- *
- * New owner@/group@/everone@ ACEs will be added
- * later.
- */
- if (zfsvfs->z_acl_mode == ZFS_ACL_DISCARD)
- zfs_acl_release_nodes(aclp);
+ zfs_acl_node_t *newnode;
+ size_t abstract_size = aclp->z_ops.ace_abstract_size();
+ void *zacep;
+ uint32_t owner, group, everyone;
+ uint32_t deny1, deny2, allow0;
+
+ new_count = new_bytes = 0;
+
+ acl_trivial_access_masks((mode_t)mode, &allow0, &deny1, &deny2,
+ &owner, &group, &everyone);
+
+ newnode = zfs_acl_node_alloc((abstract_size * 6) + aclp->z_acl_bytes);
+
+ zacep = newnode->z_acldata;
+ if (allow0) {
+ zfs_set_ace(aclp, zacep, allow0, ALLOW, -1, ACE_OWNER);
+ zacep = (void *)((uintptr_t)zacep + abstract_size);
+ new_count++;
+ new_bytes += abstract_size;
+ } if (deny1) {
+ zfs_set_ace(aclp, zacep, deny1, DENY, -1, ACE_OWNER);
+ zacep = (void *)((uintptr_t)zacep + abstract_size);
+ new_count++;
+ new_bytes += abstract_size;
+ }
+ if (deny2) {
+ zfs_set_ace(aclp, zacep, deny2, DENY, -1, OWNING_GROUP);
+ zacep = (void *)((uintptr_t)zacep + abstract_size);
+ new_count++;
+ new_bytes += abstract_size;
+ }
while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask,
&iflags, &type)) {
+ uint16_t inherit_flags;
entry_type = (iflags & ACE_TYPE_FLAGS);
- iflags = (iflags & ALL_INHERIT);
+ inherit_flags = (iflags & ALL_INHERIT);
+
+ if ((entry_type == ACE_OWNER || entry_type == ACE_EVERYONE ||
+ (entry_type == OWNING_GROUP)) &&
+ ((inherit_flags & ACE_INHERIT_ONLY_ACE) == 0)) {
+ continue;
+ }
if ((type != ALLOW && type != DENY) ||
- (iflags & ACE_INHERIT_ONLY_ACE)) {
- if (iflags)
+ (inherit_flags & ACE_INHERIT_ONLY_ACE)) {
+ if (inherit_flags)
aclp->z_hints |= ZFS_INHERIT_ACE;
switch (type) {
case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
@@ -1643,125 +1441,59 @@ zfs_acl_chmod(zfsvfs_t *zfsvfs, uint64_t uid,
aclp->z_hints |= ZFS_ACL_OBJ_ACE;
break;
}
- goto nextace;
- }
-
- /*
- * Need to split ace into two?
- */
- if ((iflags & (ACE_FILE_INHERIT_ACE|
- ACE_DIRECTORY_INHERIT_ACE)) &&
- (!(iflags & ACE_INHERIT_ONLY_ACE))) {
- zfs_acl_split_ace(aclp, acep);
- aclp->z_hints |= ZFS_INHERIT_ACE;
- goto nextace;
- }
-
- if (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE ||
- (entry_type == OWNING_GROUP)) {
- access_mask &= ~OGE_CLEAR;
- aclp->z_ops.ace_mask_set(acep, access_mask);
- goto nextace;
} else {
- reuse_deny = B_TRUE;
- if (type == ALLOW) {
-
- /*
- * Check preceding ACE if any, to see
- * if we need to prepend a DENY ACE.
- * This is only applicable when the acl_mode
- * property == groupmask.
- */
- if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK) {
-
- reuse_deny = zfs_reuse_deny(aclp, acep,
- prevacep);
-
- if (!reuse_deny) {
- prevacep =
- zfs_acl_prepend_deny(uid,
- aclp, acep, mode);
- } else {
- zfs_acl_prepend_fixup(
- aclp, prevacep,
- acep, mode, uid);
- }
- zfs_fixup_group_entries(aclp, acep,
- prevacep, mode);
- }
- }
- }
-nextace:
- prevacep = acep;
- }
- /*
- * Check out last six aces, if we have six.
- */
-
- if (aclp->z_acl_count >= 6) {
- if (zfs_have_canonical_six(aclp)) {
- need_canonical_six = 0;
+ /*
+ * Limit permissions to be no greater than
+ * group permissions
+ */
+ if (zfsvfs->z_acl_inherit == ZFS_ACL_RESTRICTED) {
+ if (!(mode & S_IRGRP))
+ access_mask &= ~ACE_READ_DATA;
+ if (!(mode & S_IWGRP))
+ access_mask &=
+ ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
+ if (!(mode & S_IXGRP))
+ access_mask &= ~ACE_EXECUTE;
+ access_mask &=
+ ~(ACE_WRITE_OWNER|ACE_WRITE_ACL|
+ ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS);
+ }
}
- }
-
- if (need_canonical_six) {
- size_t abstract_size = aclp->z_ops.ace_abstract_size();
- void *zacep;
- zfs_acl_node_t *aclnode =
- zfs_acl_node_alloc(abstract_size * 6);
-
- aclnode->z_size = abstract_size * 6;
- aclnode->z_ace_count = 6;
- aclp->z_acl_bytes += aclnode->z_size;
- list_insert_tail(&aclp->z_acl, aclnode);
-
- zacep = aclnode->z_acldata;
-
- i = 0;
- zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++),
- 0, DENY, -1, ACE_OWNER);
- zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++),
- OWNER_ALLOW_MASK, ALLOW, -1, ACE_OWNER);
- zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 0,
- DENY, -1, OWNING_GROUP);
- zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 0,
- ALLOW, -1, OWNING_GROUP);
- zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++),
- EVERYONE_DENY_MASK, DENY, -1, ACE_EVERYONE);
- zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++),
- EVERYONE_ALLOW_MASK, ALLOW, -1, ACE_EVERYONE);
- aclp->z_acl_count += 6;
- }
-
- zfs_acl_fixup_canonical_six(aclp, mode);
+ zfs_set_ace(aclp, zacep, access_mask, type, who, iflags);
+ ace_size = aclp->z_ops.ace_size(acep);
+ zacep = (void *)((uintptr_t)zacep + ace_size);
+ new_count++;
+ new_bytes += ace_size;
+ }
+ zfs_set_ace(aclp, zacep, owner, 0, -1, ACE_OWNER);
+ zacep = (void *)((uintptr_t)zacep + abstract_size);
+ zfs_set_ace(aclp, zacep, group, 0, -1, OWNING_GROUP);
+ zacep = (void *)((uintptr_t)zacep + abstract_size);
+ zfs_set_ace(aclp, zacep, everyone, 0, -1, ACE_EVERYONE);
+
+ new_count += 3;
+ new_bytes += abstract_size * 3;
+ zfs_acl_release_nodes(aclp);
+ aclp->z_acl_count = new_count;
+ aclp->z_acl_bytes = new_bytes;
+ newnode->z_ace_count = new_count;
+ newnode->z_size = new_bytes;
+ list_insert_tail(&aclp->z_acl, newnode);
}
int
zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode)
{
- int error;
-
mutex_enter(&zp->z_lock);
mutex_enter(&zp->z_acl_lock);
-
- *aclp = NULL;
- error = zfs_acl_node_read(zp, aclp, B_TRUE);
- if (error == 0) {
- uint64_t owner;
- if (IS_EPHEMERAL(zp->z_uid))
- if ((error = sa_lookup(zp->z_sa_hdl,
- SA_ZPL_UID(zp->z_zfsvfs),
- &owner, sizeof (owner))) != 0)
- return (error);
- else
- owner = (uint64_t)zp->z_uid;
- (*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS;
- zfs_acl_chmod(zp->z_zfsvfs, owner, mode, *aclp);
- }
+ *aclp = zfs_acl_alloc(zfs_acl_version_zp(zp));
+ (*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS;
+ zfs_acl_chmod(zp->z_zfsvfs, mode, *aclp);
mutex_exit(&zp->z_acl_lock);
mutex_exit(&zp->z_lock);
- return (error);
+ ASSERT(*aclp);
+ return (0);
}
/*
@@ -1803,8 +1535,8 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp,
uint64_t mode, boolean_t *need_chmod)
{
void *pacep;
- void *acep, *acep2;
- zfs_acl_node_t *aclnode, *aclnode2;
+ void *acep;
+ zfs_acl_node_t *aclnode;
zfs_acl_t *aclp = NULL;
uint64_t who;
uint32_t access_mask;
@@ -1877,6 +1609,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp,
&data2)) == data1sz);
bcopy(data1, data2, data2sz);
}
+
aclp->z_acl_count++;
aclnode->z_ace_count++;
aclp->z_acl_bytes += aclnode->z_size;
@@ -1895,37 +1628,13 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp,
ASSERT(vdir);
- newflags = aclp->z_ops.ace_flags_get(acep);
+ /*
+ * If only FILE_INHERIT is set then turn on
+ * inherit_only
+ */
if ((iflags & (ACE_FILE_INHERIT_ACE |
- ACE_DIRECTORY_INHERIT_ACE)) !=
+ ACE_DIRECTORY_INHERIT_ACE)) ==
ACE_FILE_INHERIT_ACE) {
- aclnode2 = zfs_acl_node_alloc(ace_size);
- list_insert_tail(&aclp->z_acl, aclnode2);
- acep2 = aclnode2->z_acldata;
- zfs_set_ace(aclp, acep2,
- access_mask, type, who,
- iflags|ACE_INHERITED_ACE);
- newflags |= ACE_INHERIT_ONLY_ACE;
- aclp->z_ops.ace_flags_set(acep, newflags);
- newflags &= ~ALL_INHERIT;
- aclp->z_ops.ace_flags_set(acep2,
- newflags|ACE_INHERITED_ACE);
-
- /*
- * Copy special opaque data if any
- */
- if ((data1sz = aclp->z_ops.ace_data(acep,
- &data1)) != 0) {
- VERIFY((data2sz =
- aclp->z_ops.ace_data(acep2,
- &data2)) == data1sz);
- bcopy(data1, data2, data1sz);
- }
- aclp->z_acl_count++;
- aclnode2->z_ace_count++;
- aclp->z_acl_bytes += aclnode->z_size;
- zfs_restricted_update(zfsvfs, aclp, acep2);
- } else {
newflags |= ACE_INHERIT_ONLY_ACE;
aclp->z_ops.ace_flags_set(acep,
newflags|ACE_INHERITED_ACE);
@@ -2053,14 +1762,14 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
if (need_chmod) {
acl_ids->z_aclp->z_hints |= (vap->va_type == VDIR) ?
ZFS_ACL_AUTO_INHERIT : 0;
- zfs_acl_chmod(zfsvfs, acl_ids->z_fuid,
- acl_ids->z_mode, acl_ids->z_aclp);
+ zfs_acl_chmod(zfsvfs, acl_ids->z_mode, acl_ids->z_aclp);
}
}
if (inherited || vsecp) {
acl_ids->z_mode = zfs_mode_compute(acl_ids->z_mode,
- acl_ids->z_aclp, &acl_ids->z_aclp->z_hints);
+ acl_ids->z_aclp, &acl_ids->z_aclp->z_hints,
+ acl_ids->z_fuid, acl_ids->z_fgid);
if (ace_trivial_common(acl_ids->z_aclp, 0, zfs_ace_walk) == 0)
acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL;
}
diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
index 02a9adfb49..a8883b1e7a 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
@@ -383,14 +383,6 @@ vscan_changed_cb(void *arg, uint64_t newval)
}
static void
-acl_mode_changed_cb(void *arg, uint64_t newval)
-{
- zfsvfs_t *zfsvfs = arg;
-
- zfsvfs->z_acl_mode = newval;
-}
-
-static void
acl_inherit_changed_cb(void *arg, uint64_t newval)
{
zfsvfs_t *zfsvfs = arg;
@@ -520,8 +512,6 @@ zfs_register_callbacks(vfs_t *vfsp)
error = error ? error : dsl_prop_register(ds,
"snapdir", snapdir_changed_cb, zfsvfs);
error = error ? error : dsl_prop_register(ds,
- "aclmode", acl_mode_changed_cb, zfsvfs);
- error = error ? error : dsl_prop_register(ds,
"aclinherit", acl_inherit_changed_cb, zfsvfs);
error = error ? error : dsl_prop_register(ds,
"vscan", vscan_changed_cb, zfsvfs);
@@ -562,7 +552,6 @@ unregister:
(void) dsl_prop_unregister(ds, "setuid", setuid_changed_cb, zfsvfs);
(void) dsl_prop_unregister(ds, "exec", exec_changed_cb, zfsvfs);
(void) dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, zfsvfs);
- (void) dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, zfsvfs);
(void) dsl_prop_unregister(ds, "aclinherit", acl_inherit_changed_cb,
zfsvfs);
(void) dsl_prop_unregister(ds, "vscan", vscan_changed_cb, zfsvfs);
@@ -1250,9 +1239,6 @@ zfs_unregister_callbacks(zfsvfs_t *zfsvfs)
VERIFY(dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb,
zfsvfs) == 0);
- VERIFY(dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb,
- zfsvfs) == 0);
-
VERIFY(dsl_prop_unregister(ds, "aclinherit",
acl_inherit_changed_cb, zfsvfs) == 0);
diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c
index 6b77385df1..fcaac48a62 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c
@@ -2953,27 +2953,43 @@ top:
if (attrzp)
mutex_enter(&attrzp->z_lock);
- if (mask & AT_UID) {
- SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
- &new_uid, sizeof (new_uid));
- zp->z_uid = zfs_fuid_map_id(zfsvfs, new_uid, cr, ZFS_OWNER);
- if (attrzp) {
- SA_ADD_BULK_ATTR(xattr_bulk, xattr_count,
- SA_ZPL_UID(zfsvfs), NULL, &new_uid,
- sizeof (new_uid));
- attrzp->z_gid = zp->z_uid;
+ if (mask & (AT_UID|AT_GID)) {
+
+ if (mask & AT_UID) {
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
+ &new_uid, sizeof (new_uid));
+ zp->z_uid = zfs_fuid_map_id(zfsvfs, new_uid,
+ cr, ZFS_OWNER);
+ if (attrzp) {
+ SA_ADD_BULK_ATTR(xattr_bulk, xattr_count,
+ SA_ZPL_UID(zfsvfs), NULL, &new_uid,
+ sizeof (new_uid));
+ attrzp->z_gid = zp->z_uid;
+ }
}
- }
- if (mask & AT_GID) {
- SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL,
- &new_gid, sizeof (new_gid));
- zp->z_gid = zfs_fuid_map_id(zfsvfs, new_gid, cr, ZFS_GROUP);
+ if (mask & AT_GID) {
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs),
+ NULL, &new_gid, sizeof (new_gid));
+ zp->z_gid = zfs_fuid_map_id(zfsvfs, new_gid, cr,
+ ZFS_GROUP);
+ if (attrzp) {
+ SA_ADD_BULK_ATTR(xattr_bulk, xattr_count,
+ SA_ZPL_GID(zfsvfs), NULL, &new_gid,
+ sizeof (new_gid));
+ attrzp->z_gid = zp->z_gid;
+ }
+ }
+ if (!(mask & AT_MODE)) {
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs),
+ NULL, &new_mode, sizeof (new_mode));
+ new_mode = zp->z_mode;
+ }
+ err = zfs_acl_chown_setattr(zp);
+ ASSERT(err == 0);
if (attrzp) {
- SA_ADD_BULK_ATTR(xattr_bulk, xattr_count,
- SA_ZPL_GID(zfsvfs), NULL, &new_gid,
- sizeof (new_gid));
- attrzp->z_gid = zp->z_gid;
+ err = zfs_acl_chown_setattr(attrzp);
+ ASSERT(err == 0);
}
}
@@ -2982,6 +2998,7 @@ top:
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,
&new_mode, sizeof (new_mode));
zp->z_mode = new_mode;
+ ASSERT3U((uintptr_t)aclp, !=, NULL);
err = zfs_aclset_common(zp, aclp, cr, tx);
ASSERT3U(err, ==, 0);
zp->z_acl_cached = aclp;
diff --git a/usr/src/uts/common/fs/zfs/zfs_znode.c b/usr/src/uts/common/fs/zfs/zfs_znode.c
index 3cc99c5b8d..6d5a3f645f 100644
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c
@@ -968,7 +968,8 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_ACES(zfsvfs),
zfs_acl_data_locator, &locate,
acl_ids->z_aclp->z_acl_bytes);
- mode = zfs_mode_compute(mode, acl_ids->z_aclp, &pflags);
+ mode = zfs_mode_compute(mode, acl_ids->z_aclp, &pflags,
+ acl_ids->z_fuid, acl_ids->z_fgid);
}
VERIFY(sa_replace_all_by_template(sa_hdl, sa_attrs, cnt, tx) == 0);
diff --git a/usr/src/uts/common/sys/fs/zfs.h b/usr/src/uts/common/sys/fs/zfs.h
index 1694dbe6cf..ddf4db3e2f 100644
--- a/usr/src/uts/common/sys/fs/zfs.h
+++ b/usr/src/uts/common/sys/fs/zfs.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_FS_ZFS_H
@@ -86,7 +85,7 @@ typedef enum {
ZFS_PROP_READONLY,
ZFS_PROP_ZONED,
ZFS_PROP_SNAPDIR,
- ZFS_PROP_ACLMODE,
+ ZFS_PROP_PRIVATE, /* not exposed to user, temporary */
ZFS_PROP_ACLINHERIT,
ZFS_PROP_CREATETXG, /* not exposed to the user */
ZFS_PROP_NAME, /* not exposed to the user */