[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20100201231816.GQ19418@fieldses.org>
Date: Mon, 1 Feb 2010 18:18:16 -0500
From: "J. Bruce Fields" <bfields@...i.umich.edu>
To: "Aneesh Kumar K.V" <aneesh.kumar@...ux.vnet.ibm.com>
Cc: sfrench@...ibm.com, ffilz@...ibm.com, agruen@...e.de,
adilger@....com, sandeen@...hat.com, tytso@....edu,
staubach@...hat.com, jlayton@...hat.com,
linux-fsdevel@...r.kernel.org, nfsv4@...ux-nfs.org,
linux-ext4@...r.kernel.org
Subject: Re: [PATCH 07/23] vfs: Add Posix acl to rich acl mapping helpers
On Mon, Feb 01, 2010 at 11:04:49AM +0530, Aneesh Kumar K.V wrote:
> This patch add helpers that can be used by the file system to map
> posix acls to rich acl format. This enables the file system to
> return rich acl mapping the posix acls stored on disk when the
You mean, to return a rich acl which is a mapped version of the posix
acl stored on disk?
> file system is enabled with rich acl format.
Then I assume if you modified the acl, the filesystem would replace
the existing posix acl by a "rich acl"?
The idea being to allow you to convert an existing posix-acl-using
filesystem to rich acl's? (But not the reverse.)
--b.
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@...ux.vnet.ibm.com>
> ---
> fs/Makefile | 2 +-
> fs/richacl_base.c | 2 +-
> fs/richacl_posix.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/richacl.h | 3 +
> 4 files changed, 228 insertions(+), 2 deletions(-)
> create mode 100644 fs/richacl_posix.c
>
> diff --git a/fs/Makefile b/fs/Makefile
> index 0a046a1..a5f3ee3 100644
> --- a/fs/Makefile
> +++ b/fs/Makefile
> @@ -53,7 +53,7 @@ obj-$(CONFIG_GENERIC_ACL) += generic_acl.o
>
> obj-$(CONFIG_FS_RICHACL) += richacl.o
> richacl-y := richacl_base.o richacl_xattr.o \
> - richacl_compat.o
> + richacl_compat.o richacl_posix.o
>
> obj-y += quota/
>
> diff --git a/fs/richacl_base.c b/fs/richacl_base.c
> index e75f713..a176399 100644
> --- a/fs/richacl_base.c
> +++ b/fs/richacl_base.c
> @@ -114,7 +114,7 @@ richacl_masks_to_mode(const struct richacl *acl)
> }
> EXPORT_SYMBOL_GPL(richacl_masks_to_mode);
>
> -static unsigned int
> +unsigned int
> richacl_mode_to_mask(mode_t mode)
> {
> unsigned int mask = ACE4_POSIX_ALWAYS_ALLOWED;
> diff --git a/fs/richacl_posix.c b/fs/richacl_posix.c
> new file mode 100644
> index 0000000..07db970
> --- /dev/null
> +++ b/fs/richacl_posix.c
> @@ -0,0 +1,223 @@
> +/*
> + * Copyright IBM Corporation, 2009
> + * Author Aneesh Kumar K.V <aneesh.kumar@...ux.vnet.ibm.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of version 2.1 of the GNU Lesser General Public License
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it would be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> + *
> + */
> +
> +
> +#include <linux/fs.h>
> +#include <linux/richacl.h>
> +#include <linux/posix_acl.h>
> +
> +static void posix_to_richacl(struct posix_acl *pacl, int type,
> + mode_t mode, struct richacl *acl)
> +{
> + int eflags;
> + struct richace *ace;
> + unsigned short deny;
> + struct posix_acl_entry *pa, *pe, *acl_other = NULL;
> +
> + if (type == ACL_TYPE_DEFAULT)
> + eflags = ACE4_FILE_INHERIT_ACE |
> + ACE4_DIRECTORY_INHERIT_ACE | ACE4_INHERIT_ONLY_ACE;
> + else
> + eflags = 0;
> +
> + BUG_ON(pacl->a_count < 3);
> + /* Go to the last saved entry */
> + ace = acl->a_entries + acl->a_count;
> + FOREACH_ACL_ENTRY(pa, pacl, pe) {
> + switch (pa->e_tag) {
> + case ACL_USER_OBJ:
> + {
> + /* Everything that is not granted we deny */
> + deny = ~pa->e_perm ;
> + if (deny & 0x7) {
> + ace->e_type = ACE4_ACCESS_DENIED_ACE_TYPE;
> + ace->e_flags = eflags;
> + ace->e_mask = richacl_mode_to_mask(deny);
> + richace_set_who(ace, richace_owner_who);
> + acl->a_count++;
> + ace++;
> + }
> + /* Add allow entry */
> + ace->e_type = ACE4_ACCESS_ALLOWED_ACE_TYPE;
> + ace->e_flags = eflags;
> + ace->e_mask = richacl_mode_to_mask(pa->e_perm);
> + ace->e_mask |= ACE4_WRITE_ATTRIBUTES | ACE4_WRITE_ACL;
> + richace_set_who(ace, richace_owner_who);
> + acl->a_count++;
> + ace++;
> + break;
> + }
> + case ACL_USER:
> + {
> + /* Everything that is not granted we deny */
> + deny = ~pa->e_perm ;
> + if (deny & 0x7) {
> + ace->e_type = ACE4_ACCESS_DENIED_ACE_TYPE;
> + ace->e_flags = eflags;
> + ace->e_mask = richacl_mode_to_mask(deny);
> + ace->u.e_id = pa->e_id;
> + acl->a_count++;
> + ace++;
> + }
> + /* Add allow entry */
> + ace->e_type = ACE4_ACCESS_ALLOWED_ACE_TYPE;
> + ace->e_flags = eflags;
> + ace->e_mask = richacl_mode_to_mask(pa->e_perm);
> + ace->u.e_id = pa->e_id;
> + acl->a_count++;
> + ace++;
> + break;
> +
> + }
> + case ACL_GROUP_OBJ:
> + {
> + /*
> + * In the case of group we apply allow first
> + * since a person can be in different group
> + */
> + ace->e_type = ACE4_ACCESS_ALLOWED_ACE_TYPE;
> + ace->e_flags = eflags;
> + ace->e_mask = richacl_mode_to_mask(pa->e_perm);
> + richace_set_who(ace, richace_group_who);
> + acl->a_count++;
> + ace++;
> + break;
> +
> + }
> + case ACL_GROUP:
> + {
> + /* Add allow entries only */
> + ace->e_type = ACE4_ACCESS_ALLOWED_ACE_TYPE;
> + ace->e_flags = eflags | ACE4_IDENTIFIER_GROUP;
> + ace->e_mask = richacl_mode_to_mask(pa->e_perm);
> + ace->u.e_id = pa->e_id;
> + acl->a_count++;
> + ace++;
> + break;
> +
> + }
> + case ACL_MASK:
> + {
> + /*
> + * We can ignore ACL_MASK values. We derive the
> + * respective values from the inode mode values
> + */
> + break;
> + }
> + case ACL_OTHER:
> + {
> + /*
> + * We should precess ACL_OTHER only after getting all
> + * user and group pa and then adding there respective
> + * deny entries
> + */
> + acl_other = pa;
> + break;
> +
> + }
> + }
> + }
> + /*
> + * Now add the deny entries for ACL_GROUP and ACL_GROUP_OBJ entries
> + */
> + FOREACH_ACL_ENTRY(pa, pacl, pe) {
> + switch (pa->e_tag) {
> + case ACL_USER_OBJ:
> + case ACL_USER:
> + case ACL_MASK:
> + case ACL_OTHER:
> + break;
> + case ACL_GROUP_OBJ:
> + {
> + /* Everything that is not granted we deny */
> + deny = ~pa->e_perm ;
> + if (deny & 0x7) {
> + ace->e_type = ACE4_ACCESS_DENIED_ACE_TYPE;
> + ace->e_flags = eflags;
> + ace->e_mask = richacl_mode_to_mask(deny);
> + richace_set_who(ace, richace_group_who);
> + acl->a_count++;
> + ace++;
> + }
> + break;
> + }
> + case ACL_GROUP:
> + {
> + /* Everything that is not granted we deny */
> + deny = ~pa->e_perm ;
> + if (deny & 0x7) {
> + ace->e_type = ACE4_ACCESS_DENIED_ACE_TYPE;
> + ace->e_flags = eflags | ACE4_IDENTIFIER_GROUP;
> + ace->e_mask = richacl_mode_to_mask(deny);
> + ace->u.e_id = pa->e_id;
> + acl->a_count++;
> + ace++;
> + }
> + break;
> + }
> + }
> + }
> + /* Now handle ACL_OTHER entry */
> + if (acl_other) {
> + ace->e_type = ACE4_ACCESS_ALLOWED_ACE_TYPE;
> + ace->e_flags = eflags;
> + ace->e_mask = richacl_mode_to_mask(acl_other->e_perm);
> + richace_set_who(ace, richace_everyone_who);
> + acl->a_count++;
> + ace++;
> + }
> +
> + /* set acl mask values */
> + acl->a_owner_mask = richacl_mode_to_mask(mode >> 6);
> + acl->a_group_mask = richacl_mode_to_mask(mode >> 3);
> + acl->a_other_mask = richacl_mode_to_mask(mode);
> +
> + return;
> +}
> +
> +struct richacl *map_posix_to_richacl(struct inode *inode,
> + struct posix_acl *pacl,
> + struct posix_acl *dpacl)
> +{
> +
> + struct richacl *acl;
> + int size = 0;
> +
> + if (pacl) {
> + if (posix_acl_valid(pacl) < 0)
> + return ERR_PTR(-EINVAL);
> + size += 2*pacl->a_count;
> + }
> +
> + if (dpacl) {
> + if (posix_acl_valid(dpacl) < 0)
> + return ERR_PTR(-EINVAL);
> + size += 2*dpacl->a_count;
> + }
> +
> + /* Allocate the worst case one deny, allow pair each */
> + acl = richacl_alloc(size);
> + if (acl == NULL)
> + return ERR_PTR(-ENOMEM);
> +
> + /* We will count actual number of entries when we map */
> + acl->a_count = 0;
> + if (pacl)
> + posix_to_richacl(pacl, ACL_TYPE_ACCESS , inode->i_mode, acl);
> +
> + if (dpacl)
> + posix_to_richacl(dpacl, ACL_TYPE_DEFAULT, inode->i_mode, acl);
> +
> + return acl;
> +}
> diff --git a/include/linux/richacl.h b/include/linux/richacl.h
> index f9089dc..b08fdf1 100644
> --- a/include/linux/richacl.h
> +++ b/include/linux/richacl.h
> @@ -228,8 +228,11 @@ extern int richace_is_same_who(const struct richace *, const struct richace *);
> extern int richace_set_who(struct richace *ace, const char *who);
> extern struct richacl *richacl_inherit(const struct richacl *, mode_t);
> extern int richacl_masks_to_mode(const struct richacl *);
> +extern unsigned int richacl_mode_to_mask(mode_t mode);
> extern struct richacl *richacl_chmod(struct richacl *, mode_t);
> extern int richacl_apply_masks(struct richacl **acl);
> extern int richacl_write_through(struct richacl **acl);
> +extern struct richacl *map_posix_to_richacl(struct inode *, struct posix_acl *,
> + struct posix_acl *);
>
> #endif /* __RICHACL_H */
> --
> 1.7.0.rc0.48.gdace5
>
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists