[RFC PATCH 1/5] ubifs: Implement POSIX Access Control Lists (ACLs)
Li Zetao
lizetao1 at huawei.com
Fri Mar 22 04:36:10 PDT 2024
Hi,
On 2024/3/21 10:55, Zhihao Cheng wrote:
> 在 2024/3/20 0:16, Li Zetao 写道:
>> Implement the ACLs feature for ubifs based on vfs Posix ACLs,
>> details as follows:
>> * Initialize acl for newly created inode.
>> * Provides get/set interface to access ACLs.
>>
>> ACLs feature relies on xattr implementation which using specific key
>> names "system.posix_acl_default" and "system.posix_acl_access". Now Only
>> the v2 version of POSIX ACLs is supported, and ubifs does not need to
>> customize the storage format, which can simplify the implementation.
>>
>> Signed-off-by: Li Zetao <lizetao1 at huawei.com>
>> ---
>> fs/ubifs/acl.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++
>> fs/ubifs/ubifs.h | 13 +++++
>> fs/ubifs/xattr.c | 1 -
>> 3 files changed, 153 insertions(+), 1 deletion(-)
>> create mode 100644 fs/ubifs/acl.c
>>
>> diff --git a/fs/ubifs/acl.c b/fs/ubifs/acl.c
>> new file mode 100644
>> index 000000000000..253568baf097
>> --- /dev/null
>> +++ b/fs/ubifs/acl.c
>> @@ -0,0 +1,140 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * This file is part of UBIFS.
>> + *
>> + * Copyright (C) 2024 Huawei Tech. Co., Ltd.
>> + *
>> + * Authors: Li Zetao <lizetao1 at huawei.com>
>> + */
>> +
>> +/* This file implements POSIX Access Control Lists (ACLs) */
>> +
>> +#include "ubifs.h"
>> +
>> +#include <linux/posix_acl_xattr.h>
>> +
>> +struct posix_acl *ubifs_get_inode_acl(struct inode *inode, int type,
>> bool rcu)
>> +{
>> + char *xattr_value = NULL;
>> + const char *xattr_name;
>> + struct posix_acl *acl;
>> + ssize_t size;
>> +
>> + if (rcu)
>> + return ERR_PTR(-ECHILD);
>> +
>> + xattr_name = posix_acl_xattr_name(type);
>> + if (unlikely(!strcmp(xattr_name, "")))
>> + return ERR_PTR(-EINVAL);
> The acl type has been guaranteed valid from vfs caller, there is no need
> to check converted name by 'strcmp', in theory, we can use it directly
> just like f2fs does. For this case, I suggest to unfold the
> posix_acl_xattr_name and convert it to corresponding name just like
> btrfs does.
Ok, I will modify it in the next version.
>> +
>> + size = ubifs_xattr_get(inode, xattr_name, NULL, 0);
>> + if (size > 0) {
>> + xattr_value = kzalloc(size, GFP_KERNEL);
>> + if (unlikely(!xattr_value))
>> + return ERR_PTR(-ENOMEM);
>> +
>> + size = ubifs_xattr_get(inode, xattr_name, xattr_value, size);
>> + }
>> +
>> + if (size > 0)
>> + acl = posix_acl_from_xattr(&init_user_ns, xattr_value, size);
>> + else if (size == -ENODATA || size == 0)
>> + acl = NULL;
>> + else
>> + acl = ERR_PTR(size);
>> +
>> + kfree(xattr_value);
>> +
>> + return acl;
>> +}
>> +
>> +static int __ubifs_set_acl(struct inode *inode, int type, struct
>> posix_acl *acl, int flags)
>> +{
>> + void *xattr_value = NULL;
>> + const char *xattr_name;
>> + size_t size = 0;
>> + int error;
>> +
>
>> + xattr_name = posix_acl_xattr_name(type);
>> + if (unlikely(!strcmp(xattr_name, "")))
>> + return -EINVAL;
>> +
>> + if (unlikely(!strcmp(xattr_name, XATTR_NAME_POSIX_ACL_DEFAULT) &&
>> !S_ISDIR(inode->i_mode)))
>> + return acl ? -EACCES : 0;
>> +
> Similar to previous, replace above 6 lines, refer to __btrfs_set_acl but
> keep the error code same with __ext4_set_acl.
Ok.
>> + if (acl) {
>> + size = posix_acl_xattr_size(acl->a_count);
>> + xattr_value = kmalloc(size, GFP_KERNEL);
>> + if (unlikely(!xattr_value))
>> + return -ENOMEM;
>> +
>> + error = posix_acl_to_xattr(&init_user_ns, acl, xattr_value,
>> size);
>> + if (unlikely(error < 0))
>> + goto out;
>> + }
>> +
>> + error = ubifs_xattr_set(inode, xattr_name, xattr_value, size,
>> flags, false);
> There are 2 situations here, Updating acl and Removing acl. For the
> later case, funcion vfs_remove_acl will remove corresponding xattr, the
> xattr removing function in ubifs is ubifs_xattr_remove.
Thanks. Indeed, ubifs_xattr_set() is is different from other file
systems, it will not delete xattr when value is NULL.
>> + if (likely(!error))
> I prefer to remove the 'likely', UBIFS limits the max xattr count for
> each file(Goto create_xattr), non zero error returned is a common case
> on a small LEB flash.
Ok.
>> + set_cached_acl(inode, type, acl);
>> +out:
>> + kfree(xattr_value);
>> + return error;
>> +}
>> +
>> +int ubifs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
>> struct posix_acl *acl, int type)
>> +{
>> + struct inode *inode = d_inode(dentry);
>> + umode_t old_mode = inode->i_mode;
>> + int error;
>> +
>> + if (type == ACL_TYPE_ACCESS && acl) {
>> + error = posix_acl_update_mode(idmap, inode, &inode->i_mode,
>> &acl);
>> + if (unlikely(error))
>> + return error;
>> + }
>> +
>> + error = __ubifs_set_acl(inode, type, acl, 0);
>> + if (unlikely(error))
> Mentioned in __ubifs_set_acl, error could be returned, just remove
> 'unlikely'.
Ok.
>> + inode->i_mode = old_mode;
>> +
>> + return error;
>> +
>> +}
>> +
>> +/**
>> + * ubifs_init_acl - initialize the ACLs for a new inode.
>> + * @inode: newly created inode
>> + * @dir: parent directory inode
>> + *
>> + * This function initialize ACLs, including inheriting the
> initialize -> initializes
Ok.
>> + * default ACLs of parent directory or modifying the default
>> + * ACLs according to the mode parameter in open() / creat()
>> + * system calls.
>> + */
>> +int ubifs_init_acl(struct inode *inode, struct inode *dir)
>> +{
>> + struct posix_acl *default_acl;
>> + struct posix_acl *acl;
>> + int error;
>> +
>> + error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
>> + if (unlikely(error))
>> + return error;
>> +
>> + if (default_acl) {
>> + error = __ubifs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl,
>> XATTR_CREATE);
>> + posix_acl_release(default_acl);
>> + } else {
>> + inode->i_default_acl = NULL;
>> + }
>> +
>> + if (acl) {
>> + if (likely(!error))
> Remove 'likely'.
Ok.
>> + error = __ubifs_set_acl(inode, ACL_TYPE_ACCESS, acl,
>> XATTR_CREATE);
>> + posix_acl_release(acl);
>> + } else {
>> + inode->i_acl = NULL;
>> + }
>> +
>> + return error;
>> +}
>> diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
>> index 3916dc4f30ca..b0d3b076290d 100644
>> --- a/fs/ubifs/ubifs.h
>> +++ b/fs/ubifs/ubifs.h
>> @@ -2069,6 +2069,19 @@ static inline int ubifs_init_security(struct
>> inode *dentry,
>> }
>> #endif
>> +#ifdef CONFIG_UBIFS_FS_POSIX_ACL
>> +struct posix_acl *ubifs_get_inode_acl(struct inode *inode, int type,
>> bool rcu);
>> +int ubifs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
>> struct posix_acl *acl, int type);
>> +int ubifs_init_acl(struct inode *inode, struct inode *dir);
>> +
>> +#else /* CONFIG_UBIFS_FS_POSIX_ACL */
>> +#define ubifs_get_inode_acl NULL
>> +#define ubifs_set_acl NULL
>> +static inline int ubifs_init_acl(struct inode *inode, struct inode *dir)
>> +{
>> + return 0;
>> +}
>> +#endif /* CONFIG_UBIFS_FS_POSIX_ACL */
>> /* super.c */
>> struct inode *ubifs_iget(struct super_block *sb, unsigned long inum);
>> diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
>> index 0847db521984..eb1c1f5d10df 100644
>> --- a/fs/ubifs/xattr.c
>> +++ b/fs/ubifs/xattr.c
>> @@ -40,7 +40,6 @@
>> * in the VFS inode cache. The xentries are cached in the LNC cache
>> (see
>> * tnc.c).
>> *
>> - * ACL support is not implemented.
>> */
>> #include "ubifs.h"
>>
>
More information about the linux-mtd
mailing list