diff options
author | marks <none@none> | 2008-04-09 06:51:13 -0700 |
---|---|---|
committer | marks <none@none> | 2008-04-09 06:51:13 -0700 |
commit | b3d141f8c7a5335d670721a81f797b1834ee327b (patch) | |
tree | 36515f3ec8c3d7bc9d130e6622615bb858f58e64 /usr/src | |
parent | 5529abe02121fd6e540b19adb0d8f1715de83b58 (diff) | |
download | illumos-joyent-b3d141f8c7a5335d670721a81f797b1834ee327b.tar.gz |
PSARC/2008/231 New ZFS "passthrough" ACL inheritance rules
6538405 ZFS needs mechanism to bypass file creation mode
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/common/zfs/zfs_prop.c | 9 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/zfs_acl.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_acl.c | 156 |
3 files changed, 90 insertions, 77 deletions
diff --git a/usr/src/common/zfs/zfs_prop.c b/usr/src/common/zfs/zfs_prop.c index c65f441d89..8527e932f4 100644 --- a/usr/src/common/zfs/zfs_prop.c +++ b/usr/src/common/zfs/zfs_prop.c @@ -96,8 +96,9 @@ zfs_prop_init(void) static zprop_index_t acl_inherit_table[] = { { "discard", ZFS_ACL_DISCARD }, { "noallow", ZFS_ACL_NOALLOW }, - { "secure", ZFS_ACL_SECURE }, + { "restricted", ZFS_ACL_RESTRICTED }, { "passthrough", ZFS_ACL_PASSTHROUGH }, + { "secure", ZFS_ACL_RESTRICTED }, /* bkwrd compatability */ { NULL } }; @@ -165,10 +166,10 @@ zfs_prop_init(void) register_index(ZFS_PROP_ACLMODE, "aclmode", ZFS_ACL_GROUPMASK, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, "discard | groupmask | passthrough", "ACLMODE", acl_mode_table); - register_index(ZFS_PROP_ACLINHERIT, "aclinherit", ZFS_ACL_SECURE, + register_index(ZFS_PROP_ACLINHERIT, "aclinherit", ZFS_ACL_RESTRICTED, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, - "discard | noallow | secure | passthrough", "ACLINHERIT", - acl_inherit_table); + "discard | noallow | restricted | passthrough", + "ACLINHERIT", acl_inherit_table); register_index(ZFS_PROP_COPIES, "copies", 1, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "1 | 2 | 3", "COPIES", copies_table); 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 926dfcedec..7b68f3e545 100644 --- a/usr/src/uts/common/fs/zfs/sys/zfs_acl.h +++ b/usr/src/uts/common/fs/zfs/sys/zfs_acl.h @@ -180,7 +180,7 @@ typedef struct zfs_acl { #define ZFS_ACL_NOALLOW 1 #define ZFS_ACL_GROUPMASK 2 #define ZFS_ACL_PASSTHROUGH 3 -#define ZFS_ACL_SECURE 4 +#define ZFS_ACL_RESTRICTED 4 struct znode; struct zfsvfs; diff --git a/usr/src/uts/common/fs/zfs/zfs_acl.c b/usr/src/uts/common/fs/zfs/zfs_acl.c index 0ef73f475d..4f5768fceb 100644 --- a/usr/src/uts/common/fs/zfs/zfs_acl.c +++ b/usr/src/uts/common/fs/zfs/zfs_acl.c @@ -85,7 +85,7 @@ #define ALL_INHERIT (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \ ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE|ACE_INHERITED_ACE) -#define SECURE_CLEAR (ACE_WRITE_ACL|ACE_WRITE_OWNER) +#define RESTRICTED_CLEAR (ACE_WRITE_ACL|ACE_WRITE_OWNER) #define V4_ACL_WIDE_FLAGS (ZFS_ACL_AUTO_INHERIT|ZFS_ACL_DEFAULTED|\ ZFS_ACL_PROTECTED) @@ -1615,13 +1615,13 @@ zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode) * strip off write_owner and write_acl */ static void -zfs_securemode_update(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, void *acep) +zfs_restricted_update(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, void *acep) { uint32_t mask = aclp->z_ops.ace_mask_get(acep); - if ((zfsvfs->z_acl_inherit == ZFS_ACL_SECURE) && + if ((zfsvfs->z_acl_inherit == ZFS_ACL_RESTRICTED) && (aclp->z_ops.ace_type_get(acep) == ALLOW)) { - mask &= ~SECURE_CLEAR; + mask &= ~RESTRICTED_CLEAR; aclp->z_ops.ace_mask_set(acep, mask); } } @@ -1647,7 +1647,7 @@ zfs_ace_can_use(znode_t *zp, uint16_t acep_flags) * inherit inheritable ACEs from parent */ static zfs_acl_t * -zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp) +zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp, boolean_t *need_chmod) { zfsvfs_t *zfsvfs = zp->z_zfsvfs; void *pacep; @@ -1660,7 +1660,9 @@ zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp) size_t ace_size; void *data1, *data2; size_t data1sz, data2sz; + enum vtype vntype = ZTOV(zp)->v_type; + *need_chmod = B_TRUE; pacep = NULL; aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); if (zfsvfs->z_acl_inherit != ZFS_ACL_DISCARD) { @@ -1673,82 +1675,90 @@ zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp) ace_size = aclp->z_ops.ace_size(pacep); - if (zfs_ace_can_use(zp, iflags)) { - aclnode = - zfs_acl_node_alloc(ace_size); + if (!zfs_ace_can_use(zp, iflags)) + continue; + + /* + * If owner@, group@, or everyone@ inheritable + * then zfs_acl_chmod() isn't needed. + */ + if (zfsvfs->z_acl_inherit == + ZFS_ACL_PASSTHROUGH && + ((iflags & (ACE_OWNER|ACE_EVERYONE)) || + ((iflags & OWNING_GROUP) == + OWNING_GROUP)) && (vntype == VREG || + (vntype == VDIR && + (iflags & ACE_DIRECTORY_INHERIT_ACE)))) + *need_chmod = B_FALSE; + + aclnode = zfs_acl_node_alloc(ace_size); + list_insert_tail(&aclp->z_acl, aclnode); + acep = aclnode->z_acldata; + zfs_set_ace(aclp, acep, access_mask, type, + who, iflags|ACE_INHERITED_ACE); + + /* + * Copy special opaque data if any + */ + if ((data1sz = paclp->z_ops.ace_data(pacep, + &data1)) != 0) { + VERIFY((data2sz = aclp->z_ops.ace_data(acep, + &data2)) == data1sz); + bcopy(data1, data2, data2sz); + } + aclp->z_acl_count++; + aclnode->z_ace_count++; + aclp->z_acl_bytes += aclnode->z_size; + newflags = aclp->z_ops.ace_flags_get(acep); - list_insert_tail(&aclp->z_acl, aclnode); - acep = aclnode->z_acldata; - zfs_set_ace(aclp, acep, access_mask, type, - who, iflags|ACE_INHERITED_ACE); + if (vntype == VDIR) + aclp->z_hints |= ZFS_INHERIT_ACE; + + if ((iflags & ACE_NO_PROPAGATE_INHERIT_ACE) || + (vntype != VDIR)) { + newflags &= ~ALL_INHERIT; + aclp->z_ops.ace_flags_set(acep, + newflags|ACE_INHERITED_ACE); + zfs_restricted_update(zfsvfs, aclp, acep); + continue; + } + + ASSERT(vntype == VDIR); + + newflags = aclp->z_ops.ace_flags_get(acep); + if ((iflags & (ACE_FILE_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 = paclp->z_ops.ace_data(pacep, + if ((data1sz = aclp->z_ops.ace_data(acep, &data1)) != 0) { VERIFY((data2sz = - aclp->z_ops.ace_data(acep, + aclp->z_ops.ace_data(acep2, &data2)) == data1sz); - bcopy(data1, data2, data2sz); + bcopy(data1, data2, data1sz); } aclp->z_acl_count++; - aclnode->z_ace_count++; + aclnode2->z_ace_count++; aclp->z_acl_bytes += aclnode->z_size; - newflags = aclp->z_ops.ace_flags_get(acep); - if ((iflags & - ACE_NO_PROPAGATE_INHERIT_ACE) || - (ZTOV(zp)->v_type != VDIR)) { - newflags &= ~ALL_INHERIT; - aclp->z_ops.ace_flags_set(acep, - newflags|ACE_INHERITED_ACE); - zfs_securemode_update(zfsvfs, - aclp, acep); - continue; - } - - ASSERT(ZTOV(zp)->v_type == VDIR); - - newflags = aclp->z_ops.ace_flags_get(acep); - if ((iflags & (ACE_FILE_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_securemode_update(zfsvfs, - aclp, acep2); - } else { - newflags |= ACE_INHERIT_ONLY_ACE; - aclp->z_ops.ace_flags_set(acep, - newflags|ACE_INHERITED_ACE); - } - + zfs_restricted_update(zfsvfs, aclp, acep2); + } else { + newflags |= ACE_INHERIT_ONLY_ACE; + aclp->z_ops.ace_flags_set(acep, + newflags|ACE_INHERITED_ACE); } } } @@ -1771,6 +1781,7 @@ zfs_perm_init(znode_t *zp, znode_t *parent, int flag, zfs_acl_t *paclp; xvattr_t *xvap = (xvattr_t *)vap; gid_t gid; + boolean_t need_chmod = B_TRUE; if (setaclp) aclp = setaclp; @@ -1837,7 +1848,7 @@ zfs_perm_init(znode_t *zp, znode_t *parent, int flag, mutex_enter(&parent->z_acl_lock); VERIFY(0 == zfs_acl_node_read(parent, &paclp, B_FALSE)); mutex_exit(&parent->z_acl_lock); - aclp = zfs_acl_inherit(zp, paclp); + aclp = zfs_acl_inherit(zp, paclp, &need_chmod); zfs_acl_free(paclp); } else { aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); @@ -1845,7 +1856,8 @@ zfs_perm_init(znode_t *zp, znode_t *parent, int flag, mutex_exit(&parent->z_lock); mutex_enter(&zp->z_lock); mutex_enter(&zp->z_acl_lock); - zfs_acl_chmod(zp, mode, aclp); + if (need_chmod) + zfs_acl_chmod(zp, mode, aclp); } else { mutex_enter(&zp->z_lock); mutex_enter(&zp->z_acl_lock); |