Skip to content

Commit

Permalink
742 Resurrect the ZFS "aclmode" property
Browse files Browse the repository at this point in the history
664 Umask masking "deny" ACL entries.
279 Bug in the new ACL (post-PSARC/2010/029) semantics
Reviewed by: Aram Hăvărneanu <[email protected]>
Reviewed by: Gordon Ross <[email protected]>
Reviewed by: Robert Gordon <[email protected]>
Reviewed by: [email protected]
Approved by: Garrett D'Amore <[email protected]>
  • Loading branch information
trisk committed May 14, 2011
1 parent ad6bdd0 commit a3c49ce
Show file tree
Hide file tree
Showing 13 changed files with 189 additions and 190 deletions.
117 changes: 61 additions & 56 deletions usr/src/common/acl/acl_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/

#include <sys/types.h>
Expand Down Expand Up @@ -372,7 +373,7 @@ access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow)
* by nfsace, assuming aclent_t -> nfsace semantics.
*/
static uint32_t
mode_to_ace_access(mode_t mode, int isdir, int isowner, int isallow)
mode_to_ace_access(mode_t mode, boolean_t isdir, int isowner, int isallow)
{
uint32_t access = 0;
int haswriteperm = 0;
Expand Down Expand Up @@ -415,7 +416,7 @@ mode_to_ace_access(mode_t mode, int isdir, int isowner, int isallow)
access |= ACE_DELETE_CHILD;
}
/* exec */
if (mode & 01) {
if (mode & S_IXOTH) {
access |= ACE_EXECUTE;
}

Expand Down Expand Up @@ -666,7 +667,7 @@ ln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir)
}

static int
convert_aent_to_ace(aclent_t *aclentp, int aclcnt, int isdir,
convert_aent_to_ace(aclent_t *aclentp, int aclcnt, boolean_t isdir,
ace_t **retacep, int *retacecnt)
{
ace_t *acep;
Expand All @@ -692,7 +693,7 @@ convert_aent_to_ace(aclent_t *aclentp, int aclcnt, int isdir,
dfaclcnt = aclcnt - i;
}

if (dfaclcnt && isdir == 0) {
if (dfaclcnt && !isdir) {
return (EINVAL);
}

Expand Down Expand Up @@ -730,7 +731,7 @@ convert_aent_to_ace(aclent_t *aclentp, int aclcnt, int isdir,
}

static int
ace_mask_to_mode(uint32_t mask, o_mode_t *modep, int isdir)
ace_mask_to_mode(uint32_t mask, o_mode_t *modep, boolean_t isdir)
{
int error = 0;
o_mode_t mode = 0;
Expand Down Expand Up @@ -1027,7 +1028,7 @@ ace_to_aent_legal(ace_t *acep)
}

static int
ace_allow_to_mode(uint32_t mask, o_mode_t *modep, int isdir)
ace_allow_to_mode(uint32_t mask, o_mode_t *modep, boolean_t isdir)
{
/* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */
if ((mask & (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) !=
Expand All @@ -1040,7 +1041,7 @@ ace_allow_to_mode(uint32_t mask, o_mode_t *modep, int isdir)

static int
acevals_to_aent(acevals_t *vals, aclent_t *dest, ace_list_t *list,
uid_t owner, gid_t group, int isdir)
uid_t owner, gid_t group, boolean_t isdir)
{
int error;
uint32_t flips = ACE_POSIX_SUPPORTED_BITS;
Expand Down Expand Up @@ -1080,7 +1081,7 @@ acevals_to_aent(acevals_t *vals, aclent_t *dest, ace_list_t *list,

static int
ace_list_to_aent(ace_list_t *list, aclent_t **aclentp, int *aclcnt,
uid_t owner, gid_t group, int isdir)
uid_t owner, gid_t group, boolean_t isdir)
{
int error = 0;
aclent_t *aent, *result = NULL;
Expand Down Expand Up @@ -1260,7 +1261,7 @@ acevals_compare(const void *va, const void *vb)
static int
ln_ace_to_aent(ace_t *ace, int n, uid_t owner, gid_t group,
aclent_t **aclentp, int *aclcnt, aclent_t **dfaclentp, int *dfaclcnt,
int isdir)
boolean_t isdir)
{
int error = 0;
ace_t *acep;
Expand Down Expand Up @@ -1455,7 +1456,7 @@ ln_ace_to_aent(ace_t *ace, int n, uid_t owner, gid_t group,
}

static int
convert_ace_to_aent(ace_t *acebufp, int acecnt, int isdir,
convert_ace_to_aent(ace_t *acebufp, int acecnt, boolean_t isdir,
uid_t owner, gid_t group, aclent_t **retaclentp, int *retaclcnt)
{
int error = 0;
Expand Down Expand Up @@ -1497,7 +1498,7 @@ convert_ace_to_aent(ace_t *acebufp, int acecnt, int isdir,


int
acl_translate(acl_t *aclp, int target_flavor, int isdir, uid_t owner,
acl_translate(acl_t *aclp, int target_flavor, boolean_t isdir, uid_t owner,
gid_t group)
{
int aclcnt;
Expand Down Expand Up @@ -1568,101 +1569,105 @@ acl_translate(acl_t *aclp, int target_flavor, int isdir, uid_t owner,
}

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)
acl_trivial_access_masks(mode_t mode, boolean_t isdir, trivial_acl_t *masks)
{
*deny1 = *deny2 = *allow0 = *group = 0;
uint32_t read_mask = ACE_READ_DATA;
uint32_t write_mask = ACE_WRITE_DATA|ACE_APPEND_DATA;
uint32_t execute_mask = ACE_EXECUTE;

(void) isdir; /* will need this later */

masks->deny1 = 0;
if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))
*deny1 |= ACE_READ_DATA;
masks->deny1 |= read_mask;
if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH)))
*deny1 |= ACE_WRITE_DATA;
masks->deny1 |= write_mask;
if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH)))
*deny1 |= ACE_EXECUTE;
masks->deny1 |= execute_mask;

masks->deny2 = 0;
if (!(mode & S_IRGRP) && (mode & S_IROTH))
*deny2 = ACE_READ_DATA;
masks->deny2 |= read_mask;
if (!(mode & S_IWGRP) && (mode & S_IWOTH))
*deny2 |= ACE_WRITE_DATA;
masks->deny2 |= write_mask;
if (!(mode & S_IXGRP) && (mode & S_IXOTH))
*deny2 |= ACE_EXECUTE;
masks->deny2 |= execute_mask;

masks->allow0 = 0;
if ((mode & S_IRUSR) && (!(mode & S_IRGRP) && (mode & S_IROTH)))
*allow0 |= ACE_READ_DATA;
masks->allow0 |= read_mask;
if ((mode & S_IWUSR) && (!(mode & S_IWGRP) && (mode & S_IWOTH)))
*allow0 |= ACE_WRITE_DATA;
masks->allow0 |= write_mask;
if ((mode & S_IXUSR) && (!(mode & S_IXGRP) && (mode & S_IXOTH)))
*allow0 |= ACE_EXECUTE;
masks->allow0 |= execute_mask;

*owner = ACE_WRITE_ATTRIBUTES|ACE_WRITE_OWNER|ACE_WRITE_ACL|
masks->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;
masks->owner |= read_mask;
if (mode & S_IWUSR)
*owner |= ACE_WRITE_DATA|ACE_APPEND_DATA;
masks->owner |= write_mask;
if (mode & S_IXUSR)
*owner |= ACE_EXECUTE;
masks->owner |= execute_mask;

*group = ACE_READ_ACL|ACE_READ_ATTRIBUTES| ACE_READ_NAMED_ATTRS|
masks->group = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
ACE_SYNCHRONIZE;
if (mode & S_IRGRP)
*group |= ACE_READ_DATA;
masks->group |= read_mask;
if (mode & S_IWGRP)
*group |= ACE_WRITE_DATA|ACE_APPEND_DATA;
masks->group |= write_mask;
if (mode & S_IXGRP)
*group |= ACE_EXECUTE;
masks->group |= execute_mask;

*everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES| ACE_READ_NAMED_ATTRS|
masks->everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
ACE_SYNCHRONIZE;
if (mode & S_IROTH)
*everyone |= ACE_READ_DATA;
masks->everyone |= read_mask;
if (mode & S_IWOTH)
*everyone |= ACE_WRITE_DATA|ACE_APPEND_DATA;
masks->everyone |= write_mask;
if (mode & S_IXOTH)
*everyone |= ACE_EXECUTE;
masks->everyone |= execute_mask;
}

int
acl_trivial_create(mode_t mode, ace_t **acl, int *count)
acl_trivial_create(mode_t mode, boolean_t isdir, ace_t **acl, int *count)
{
uint32_t deny1, deny2;
uint32_t allow0;
uint32_t owner, group, everyone;
int index = 0;
int error;
trivial_acl_t masks;

*count = 3;
acl_trivial_access_masks(mode, &allow0, &deny1, &deny2, &owner, &group,
&everyone);
acl_trivial_access_masks(mode, isdir, &masks);

if (allow0)
if (masks.allow0)
(*count)++;
if (deny1)
if (masks.deny1)
(*count)++;
if (deny2)
if (masks.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 (masks.allow0) {
SET_ACE(acl, index, -1, masks.allow0,
ACE_ACCESS_ALLOWED_ACE_TYPE, ACE_OWNER);
}
if (deny1) {
SET_ACE(acl, index, -1, deny1, ACE_ACCESS_DENIED_ACE_TYPE,
ACE_OWNER);
if (masks.deny1) {
SET_ACE(acl, index, -1, masks.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);
if (masks.deny2) {
SET_ACE(acl, index, -1, masks.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,
SET_ACE(acl, index, -1, masks.owner, ACE_ACCESS_ALLOWED_ACE_TYPE,
ACE_OWNER);
SET_ACE(acl, index, -1, masks.group, ACE_ACCESS_ALLOWED_ACE_TYPE,
ACE_IDENTIFIER_GROUP|ACE_GROUP);
SET_ACE(acl, index, -1, everyone, ACE_ACCESS_ALLOWED_ACE_TYPE,
SET_ACE(acl, index, -1, masks.everyone, ACE_ACCESS_ALLOWED_ACE_TYPE,
ACE_EVERYONE);

return (0);
Expand Down
20 changes: 14 additions & 6 deletions usr/src/common/acl/acl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/

#ifndef _ACL_COMMON_H
Expand All @@ -33,7 +34,14 @@
extern "C" {
#endif

extern ace_t trivial_acl[6];
typedef struct trivial_acl {
uint32_t allow0; /* allow mask for bits only in owner */
uint32_t deny1; /* deny mask for bits not in owner */
uint32_t deny2; /* deny mask for bits not in group */
uint32_t owner; /* allow mask matching mode */
uint32_t group; /* allow mask matching mode */
uint32_t everyone; /* allow mask matching mode */
} trivial_acl_t;

extern int acltrivial(const char *);
extern void adjust_ace_pair(ace_t *pair, mode_t mode);
Expand All @@ -44,13 +52,13 @@ extern int ace_trivial_common(void *, int,
uint32_t *mask));
extern acl_t *acl_alloc(acl_type_t);
extern void acl_free(acl_t *aclp);
extern int acl_translate(acl_t *aclp, int target_flavor,
int isdir, uid_t owner, gid_t group);
extern int acl_translate(acl_t *aclp, int target_flavor, boolean_t 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);
int acl_trivial_create(mode_t mode, boolean_t isdir, ace_t **acl, int *count);
void acl_trivial_access_masks(mode_t mode, boolean_t isdir,
trivial_acl_t *masks);

#ifdef __cplusplus
}
Expand Down
17 changes: 10 additions & 7 deletions usr/src/common/zfs/zfs_prop.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ 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 },
Expand Down Expand Up @@ -207,6 +214,9 @@ 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_DISCARD,
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",
Expand Down Expand Up @@ -370,13 +380,6 @@ 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,
Expand Down
11 changes: 9 additions & 2 deletions usr/src/lib/libsec/common/aclutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/


Expand Down Expand Up @@ -393,9 +394,15 @@ acl_strip(const char *file, uid_t owner, gid_t group, mode_t mode)
ace_t *min_ace_acl;
int acl_flavor;
int aclcnt;
struct stat64 statbuf;

acl_flavor = pathconf(file, _PC_ACL_ENABLED);

if (stat64(file, &statbuf) != 0) {
error = 1;
return (error);
}

/*
* force it through aclent flavor when file system doesn't
* understand question
Expand All @@ -419,8 +426,8 @@ 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) {
if ((error = acl_trivial_create(mode, &min_ace_acl,
&aclcnt)) != 0)
if ((error = acl_trivial_create(mode, S_ISDIR(statbuf.st_mode),
&min_ace_acl, &aclcnt)) != 0)
return (error);
error = acl(file, ACE_SETACL, aclcnt, min_ace_acl);
free(min_ace_acl);
Expand Down
Loading

0 comments on commit a3c49ce

Please sign in to comment.