xfs
[Top] [All Lists]

Re: [PATCH v23 16/22] richacl: Create-time inheritance

To: Andreas Gruenbacher <agruenba@xxxxxxxxxx>, Alexander Viro <viro@xxxxxxxxxxxxxxxxxx>
Subject: Re: [PATCH v23 16/22] richacl: Create-time inheritance
From: Jeff Layton <jlayton@xxxxxxxxxx>
Date: Tue, 12 Jul 2016 07:41:55 -0400
Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx>, Theodore Ts'o <tytso@xxxxxxx>, Andreas Dilger <adilger.kernel@xxxxxxxxx>, "J. Bruce Fields" <bfields@xxxxxxxxxxxx>, Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx>, Anna Schumaker <anna.schumaker@xxxxxxxxxx>, Dave Chinner <david@xxxxxxxxxxxxx>, linux-ext4@xxxxxxxxxxxxxxx, xfs@xxxxxxxxxxx, linux-kernel@xxxxxxxxxxxxxxx, linux-fsdevel@xxxxxxxxxxxxxxx, linux-nfs@xxxxxxxxxxxxxxx, linux-cifs@xxxxxxxxxxxxxxx, linux-api@xxxxxxxxxxxxxxx
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1467294433-3222-17-git-send-email-agruenba@xxxxxxxxxx>
References: <1467294433-3222-1-git-send-email-agruenba@xxxxxxxxxx> <1467294433-3222-17-git-send-email-agruenba@xxxxxxxxxx>
On Thu, 2016-06-30 at 15:47 +0200, Andreas Gruenbacher wrote:
> When a new file is created, it can inherit an acl from its parent
> directory; this is similar to how default acls work in POSIX ACLs.
> 
> As with POSIX ACLs, if a file inherits an acl from its parent directory,
> the intersection between the create mode and the permissions granted by
> the inherited acl determines the file masks and file permission bits,
> and the umask is ignored.
> 
> Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx>
> ---
> Âfs/richacl.cÂÂÂÂÂÂÂÂÂÂÂÂ| 151 
> ++++++++++++++++++++++++++++++++++++++++++++++++
> Âinclude/linux/richacl.h |ÂÂÂ2 +
> Â2 files changed, 153 insertions(+)
> 
> diff --git a/fs/richacl.c b/fs/richacl.c
> index e8a383b..29eaf89 100644
> --- a/fs/richacl.c
> +++ b/fs/richacl.c
> @@ -722,3 +722,154 @@ richacl_equiv_mode(const struct richacl *acl, umode_t 
> *mode_p)
> Â     return 0;
> Â}
> ÂEXPORT_SYMBOL_GPL(richacl_equiv_mode);
> +
> +static inline bool
> +ace_inherits_to_directory(const struct richace *ace)
> +{
> +     if (ace->e_flags & RICHACE_DIRECTORY_INHERIT_ACE)
> +             return true;
> +     if ((ace->e_flags & RICHACE_FILE_INHERIT_ACE) &&
> +     ÂÂÂÂ!(ace->e_flags & RICHACE_NO_PROPAGATE_INHERIT_ACE))
> +             return true;
> +     return false;
> +}
> +
> +/**
> + * richacl_inheritÂÂ-ÂÂcompute the inherited acl of a new file
> + * @dir_acl: acl of the containing directory
> + * @isdir:   inherit by a directory or non-directory?
> + *
> + * A directory can have acl entries which files and/or directories created
> + * inside the directory will inherit.ÂÂThis function computes the acl for 
> such
> + * a new file.ÂÂIf there is no inheritable acl, it will return %NULL.
> + */
> +struct richacl *
> +richacl_inherit(const struct richacl *dir_acl, int isdir)
> +{
> +     const struct richace *dir_ace;
> +     struct richacl *acl = NULL;
> +     struct richace *ace;
> +     int count = 0;
> +
> +     if (isdir) {
> +             richacl_for_each_entry(dir_ace, dir_acl) {
> +                     if (!ace_inherits_to_directory(dir_ace))
> +                             continue;
> +                     count++;
> +             }
> +             if (!count)
> +                     return NULL;
> +             acl = richacl_alloc(count, GFP_KERNEL);
> +             if (!acl)
> +                     return ERR_PTR(-ENOMEM);
> +             ace = acl->a_entries;
> +             richacl_for_each_entry(dir_ace, dir_acl) {
> +                     if (!ace_inherits_to_directory(dir_ace))
> +                             continue;
> +                     richace_copy(ace, dir_ace);
> +                     if (dir_ace->e_flags & RICHACE_NO_PROPAGATE_INHERIT_ACE)
> +                             ace->e_flags &= ~RICHACE_INHERITANCE_FLAGS;
> +                     else if (dir_ace->e_flags & 
> RICHACE_DIRECTORY_INHERIT_ACE)
> +                             ace->e_flags &= ~RICHACE_INHERIT_ONLY_ACE;
> +                     else
> +                             ace->e_flags |= RICHACE_INHERIT_ONLY_ACE;
> +                     ace++;
> +             }
> +     } else {
> +             richacl_for_each_entry(dir_ace, dir_acl) {
> +                     if (!(dir_ace->e_flags & RICHACE_FILE_INHERIT_ACE))
> +                             continue;
> +                     count++;
> +             }
> +             if (!count)
> +                     return NULL;
> +             acl = richacl_alloc(count, GFP_KERNEL);
> +             if (!acl)
> +                     return ERR_PTR(-ENOMEM);
> +             ace = acl->a_entries;
> +             richacl_for_each_entry(dir_ace, dir_acl) {
> +                     if (!(dir_ace->e_flags & RICHACE_FILE_INHERIT_ACE))
> +                             continue;
> +                     richace_copy(ace, dir_ace);
> +                     ace->e_flags &= ~RICHACE_INHERITANCE_FLAGS;
> +                     /*
> +                     Â* RICHACE_DELETE_CHILD is meaningless for
> +                     Â* non-directories, so clear it.
> +                     Â*/
> +                     ace->e_mask &= ~RICHACE_DELETE_CHILD;
> +                     ace++;
> +             }
> +     }
> +
> +     return acl;
> +}
> +
> +/*
> + * richacl_inherit_inodeÂÂ-ÂÂcompute inherited acl and file mode
> + * @dir_acl: acl of the containing directory
> + * @mode_p:  mode of the new inode
> + *
> + * The file permission bits in @mode_p must be set to the create mode by the
> + * caller.
> + *
> + * If there is an inheritable acl, the maximum permissions that the acl 
> grants
> + * are computed and the file masks of the new acl are set accordingly.
> + */
> +static struct richacl *
> +richacl_inherit_inode(const struct richacl *dir_acl, umode_t *mode_p)
> +{
> +     struct richacl *acl;
> +     umode_t mode = *mode_p;
> +
> +     acl = richacl_inherit(dir_acl, S_ISDIR(mode));
> +     if (acl) {
> +             if (richacl_equiv_mode(acl, &mode) == 0) {
> +                     *mode_p &= mode;
> +                     richacl_put(acl);
> +                     acl = NULL;
> +             } else {
> +                     richacl_compute_max_masks(acl);
> +                     /*
> +                     Â* Ensure that the acl will not grant any permissions
> +                     Â* beyond the create mode.
> +                     Â*/
> +                     acl->a_flags |= RICHACL_MASKED;
> +                     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);
> +             }
> +     } else
> +             *mode_p &= ~current_umask();
> +
> +     return acl;
> +}
> +
> +/**
> + * richacl_createÂÂ-ÂÂfilesystem create helper
> + * @mode_p:  mode of the new inode
> + * @dir:     containing directory
> + *
> + * Compute the inherited acl for a new inode.ÂÂIf there is no acl to inherit,
> + * apply the umask.ÂÂUse when creating a new inode on a richacl enabled file
> + * system.
> + */
> +struct richacl *richacl_create(umode_t *mode_p, struct inode *dir)
> +{
> +     struct richacl *dir_acl, *acl = NULL;
> +
> +     if (S_ISLNK(*mode_p))
> +             return NULL;
> +     dir_acl = get_richacl(dir);
> +     if (dir_acl) {
> +             if (IS_ERR(dir_acl))
> +                     return dir_acl;
> +             acl = richacl_inherit_inode(dir_acl, mode_p);
> +             richacl_put(dir_acl);
> +     } else
> +             *mode_p &= ~current_umask();
> +     return acl;
> +}
> +EXPORT_SYMBOL_GPL(richacl_create);
> diff --git a/include/linux/richacl.h b/include/linux/richacl.h
> index 9212edb..7aca1a3 100644
> --- a/include/linux/richacl.h
> +++ b/include/linux/richacl.h
> @@ -192,5 +192,7 @@ extern void richacl_compute_max_masks(struct richacl *);
> Âextern int richacl_permission(struct inode *, const struct richacl *, int);
> Âextern int richacl_chmod(struct inode *, umode_t);
> Âextern int richacl_equiv_mode(const struct richacl *, umode_t *);
> +extern struct richacl *richacl_inherit(const struct richacl *, int);
> +extern struct richacl *richacl_create(umode_t *, struct inode *);
> Â
> Â#endif /* __RICHACL_H */

Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>

<Prev in Thread] Current Thread [Next in Thread>
  • Re: [PATCH v23 16/22] richacl: Create-time inheritance, Jeff Layton <=