From patchwork Tue Feb 19 11:51:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boaz Harrosh X-Patchwork-Id: 10819751 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EDC5F1399 for ; Tue, 19 Feb 2019 11:52:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D9FB82B5BF for ; Tue, 19 Feb 2019 11:52:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CE3962B94D; Tue, 19 Feb 2019 11:52:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EC5812B690 for ; Tue, 19 Feb 2019 11:52:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728155AbfBSLwN (ORCPT ); Tue, 19 Feb 2019 06:52:13 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:52828 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726384AbfBSLwN (ORCPT ); Tue, 19 Feb 2019 06:52:13 -0500 Received: by mail-wm1-f67.google.com with SMTP id m1so2316984wml.2 for ; Tue, 19 Feb 2019 03:52:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=plexistor-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=YKIeOM4a8SusG+erjX4hs8PFEO4JES5Y0XzSmZM14hA=; b=E4cJci+vCFdjwFK5Xj2jnWzcy5Sr8/TFi8Ltf+LCR/MgzZ+VLfaXpKGTSQEzi5oFKl wBO4aFXMTmIqh1CEafjF1okuOglE77fiZ5EL8tVu0G5W1wlAGUeceYZb+ntDmKkLQq6R BwalaQMwz70hn3bZlI1cI50EmnP9xPTKrX8Zw2EekfWAXHCAMPt5m8O+JKmQU7q1qhox /jDTNw+HJNnSGbNDvxRn2/hR+7JbAiFQHpGTrwl6mYPqbF9y8xKe9HNWwkjxp3yQmJ3B 6DC8qM4TPltp1HAPH/ew82vE8tZJnESRNBITcHkplJ1PK8vaH154iKDbIy9pyEruR7Dp 9IXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=YKIeOM4a8SusG+erjX4hs8PFEO4JES5Y0XzSmZM14hA=; b=BcuU6Wlr+oqH2AL0KSbuG//5n6cYiZzDx5+wvUaJ/our8VN1I+wNtHZINx+ho4ynMo ZIrYlrLAuqptXq5BIdU0iZK7EV9afjW0T7hYJIExYKyfJZ5WXncn6O147WYihgEYTduw 7jWJP0a6Hd7GidWzMbv9sh5hPy4LJJsH0rRfWrZylpI4d8qgYkaf6PjrnesKaaZZT6xw ueebDvCUk0geIwr6spTWMZ6509iKmKWGBF20HM+fCMXUhpoAn1UwbGGHTfEOeQb7dMLU DP1qpXkWmsQDYNg+yJoodh0c+u3gdB7slUkmeVPXm4YxZVipcaQrrAfgc0QTjbSOwVMx RACA== X-Gm-Message-State: AHQUAuZAvYgUHw/n5aQNgEozMbOTkF2ON2X0J6KAgbsx8JV9mcQ7dZVT URXaLLR/Uucryd50CIjsXfpwACMFq94= X-Google-Smtp-Source: AHgI3IZsot9L/cEJJBDK7pwGaTAJYbW1LFRvZntS7wsunLwYmL9LZKv7nnIc0L2d0dZqmPDhHPOeDg== X-Received: by 2002:a1c:47:: with SMTP id 68mr2481248wma.89.1550577129696; Tue, 19 Feb 2019 03:52:09 -0800 (PST) Received: from Bfire.plexistor.com ([207.232.55.62]) by smtp.gmail.com with ESMTPSA id t18sm3605830wmt.8.2019.02.19.03.52.07 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 19 Feb 2019 03:52:09 -0800 (PST) From: Boaz harrosh To: linux-fsdevel , Anna Schumaker , Al Viro Cc: Ric Wheeler , Miklos Szeredi , Steven Whitehouse , Jefff moyer , Amir Goldstein , Amit Golander , Sagi Manole Subject: [RFC PATCH 15/17] zuf: ACL support Date: Tue, 19 Feb 2019 13:51:34 +0200 Message-Id: <20190219115136.29952-16-boaz@plexistor.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190219115136.29952-1-boaz@plexistor.com> References: <20190219115136.29952-1-boaz@plexistor.com> MIME-Version: 1.0 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Boaz Harrosh The ACL support is all in Kernel. There is no new API with zusFS. We define the internal structure of the ACL inside an opec xattr and store via the xattr zus_api. TODO: Future FSs that has their own ACL on-disk-format, Or Network zusFS that have their own verifiers for the ACL will need to establish an alternative API for the acl. Signed-off-by: Boaz Harrosh --- fs/zuf/Makefile | 2 +- fs/zuf/_extern.h | 9 ++ fs/zuf/_pr.h | 1 + fs/zuf/acl.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++ fs/zuf/file.c | 2 + fs/zuf/inode.c | 11 ++ fs/zuf/namei.c | 4 + fs/zuf/zuf.h | 6 + 8 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 fs/zuf/acl.c diff --git a/fs/zuf/Makefile b/fs/zuf/Makefile index 5d638760a82f..f53504b47c2a 100644 --- a/fs/zuf/Makefile +++ b/fs/zuf/Makefile @@ -17,7 +17,7 @@ zuf-y += md.o t1.o t2.o zuf-y += zuf-core.o zuf-root.o # Main FS -zuf-y += xattr.o +zuf-y += acl.o xattr.o zuf-y += rw.o mmap.o ioctl.o zuf-y += super.o inode.o directory.o namei.o file.o symlink.o zuf-y += module.o diff --git a/fs/zuf/_extern.h b/fs/zuf/_extern.h index 1f4b39911a5d..2e515af0bb22 100644 --- a/fs/zuf/_extern.h +++ b/fs/zuf/_extern.h @@ -83,6 +83,15 @@ int __zuf_setxattr(struct inode *inode, int type, const char *name, ssize_t zuf_listxattr(struct dentry *dentry, char *buffer, size_t size); extern const struct xattr_handler *zuf_xattr_handlers[]; +/* acl.c */ +int zuf_set_acl(struct inode *inode, struct posix_acl *acl, int type); +struct posix_acl *zuf_get_acl(struct inode *inode, int type); +int zuf_acls_create_pre(struct inode *dir, struct inode *inode, + struct posix_acl **user_acl); +int zuf_acls_create_post(struct inode *dir, struct inode *inode, + struct posix_acl *acl); +extern const struct xattr_handler zuf_acl_access_xattr_handler; +extern const struct xattr_handler zuf_acl_default_xattr_handler; /* super.c */ int zuf_init_inodecache(void); diff --git a/fs/zuf/_pr.h b/fs/zuf/_pr.h index 04b99f57f2b5..7d7e4808dcf0 100644 --- a/fs/zuf/_pr.h +++ b/fs/zuf/_pr.h @@ -43,6 +43,7 @@ #define zuf_dbg_rw(s, args ...) zuf_chan_debug("rw ", s, ##args) #define zuf_dbg_t1(s, args ...) zuf_chan_debug("t1 ", s, ##args) #define zuf_dbg_xattr(s, args ...) zuf_chan_debug("xattr", s, ##args) +#define zuf_dbg_acl(s, args ...) zuf_chan_debug("acl ", s, ##args) #define zuf_dbg_t2(s, args ...) zuf_chan_debug("t2dbg", s, ##args) #define zuf_dbg_t2_rw(s, args ...) zuf_chan_debug("t2grw", s, ##args) #define zuf_dbg_core(s, args ...) zuf_chan_debug("core ", s, ##args) diff --git a/fs/zuf/acl.c b/fs/zuf/acl.c new file mode 100644 index 000000000000..ccea8ce455fb --- /dev/null +++ b/fs/zuf/acl.c @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Access Control List + * + * Copyright (c) 2018 NetApp Inc. All rights reserved. + * + * ZUFS-License: GPL-2.0. See module.c for LICENSE details. + * + * Authors: + * Boaz Harrosh + */ + +#include +#include +#include +#include "zuf.h" + +static void _acl_to_value(const struct posix_acl *acl, void *value) +{ + int n; + struct zuf_acl *macl = value; + + zuf_dbg_acl("acl->count=%d\n", acl->a_count); + + for (n = 0; n < acl->a_count; n++) { + const struct posix_acl_entry *entry = &acl->a_entries[n]; + + zuf_dbg_acl("aclno=%d tag=0x%x perm=0x%x\n", + n, entry->e_tag, entry->e_perm); + + macl->tag = cpu_to_le16(entry->e_tag); + macl->perm = cpu_to_le16(entry->e_perm); + + switch (entry->e_tag) { + case ACL_USER: + macl->id = cpu_to_le32(__kuid_val(entry->e_uid)); + break; + case ACL_GROUP: + macl->id = cpu_to_le32(__kgid_val(entry->e_gid)); + break; + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + break; + default: + zuf_dbg_err("e_tag=0x%x\n", entry->e_tag); + return; + } + macl++; + } +} + +int zuf_set_acl(struct inode *inode, struct posix_acl *acl, int type) +{ + char *name = NULL; + void *buf; + int err; + size_t size; + + zuf_dbg_acl("[%ld] acl=%p type=0x%x\n", inode->i_ino, acl, type); + + switch (type) { + case ACL_TYPE_ACCESS: { + struct zus_inode *zi = ZUII(inode)->zi; + + name = XATTR_POSIX_ACL_ACCESS; + if (acl) { + err = posix_acl_update_mode(inode, &inode->i_mode, + &acl); + if (err < 0) + return err; + + inode->i_ctime = current_time(inode); + timespec_to_mt(&zi->i_ctime, &inode->i_ctime); + } + zi->i_mode = cpu_to_le16(inode->i_mode); + break; + } + case ACL_TYPE_DEFAULT: + name = XATTR_POSIX_ACL_DEFAULT; + if (!S_ISDIR(inode->i_mode)) + return acl ? -EACCES : 0; + break; + default: + return -EINVAL; + } + + size = acl ? acl->a_count * sizeof(struct zuf_acl) : 0; + buf = kmalloc(size, GFP_KERNEL); + if (unlikely(!buf)) + return -ENOMEM; + + if (acl) + _acl_to_value(acl, buf); + + err = __zuf_setxattr(inode, ZUF_XF_SYSTEM, name, buf, size, 0); + if (!err) + set_cached_acl(inode, type, acl); + + kfree(buf); + return err; +} + +static struct posix_acl *_value_to_acl(void *value, size_t size) +{ + int n, count; + struct posix_acl *acl; + struct zuf_acl *macl = value; + void *end = value + size; + + if (!value) + return NULL; + + count = size / sizeof(struct zuf_acl); + if (count < 0) + return ERR_PTR(-EINVAL); + if (count == 0) + return NULL; + + acl = posix_acl_alloc(count, GFP_NOFS); + if (unlikely(!acl)) + return ERR_PTR(-ENOMEM); + + for (n = 0; n < count; n++) { + if (end < (void *)macl + sizeof(struct zuf_acl)) + goto fail; + + zuf_dbg_acl("aclno=%d tag=0x%x perm=0x%x id=0x%x\n", + n, le16_to_cpu(macl->tag), le16_to_cpu(macl->perm), + le32_to_cpu(macl->id)); + + acl->a_entries[n].e_tag = le16_to_cpu(macl->tag); + acl->a_entries[n].e_perm = le16_to_cpu(macl->perm); + + switch (acl->a_entries[n].e_tag) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + macl++; + break; + case ACL_USER: + acl->a_entries[n].e_uid = + KUIDT_INIT(le32_to_cpu(macl->id)); + macl++; + if (end < (void *)macl) + goto fail; + break; + case ACL_GROUP: + acl->a_entries[n].e_gid = + KGIDT_INIT(le32_to_cpu(macl->id)); + macl++; + if (end < (void *)macl) + goto fail; + break; + + default: + goto fail; + } + } + if (macl != end) + goto fail; + return acl; + +fail: + posix_acl_release(acl); + return ERR_PTR(-EINVAL); +} + +struct posix_acl *zuf_get_acl(struct inode *inode, int type) +{ + struct zuf_inode_info *zii = ZUII(inode); + char *name = NULL; + void *buf; + struct posix_acl *acl = NULL; + int ret; + + zuf_dbg_acl("[%ld] type=0x%x\n", inode->i_ino, type); + + buf = (void *)__get_free_page(GFP_KERNEL); + if (unlikely(!buf)) + return ERR_PTR(-ENOMEM); + + switch (type) { + case ACL_TYPE_ACCESS: + name = XATTR_POSIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + name = XATTR_POSIX_ACL_DEFAULT; + break; + default: + WARN_ON(1); + return ERR_PTR(-EINVAL); + } + + zuf_smr_lock(zii); + + ret = __zuf_getxattr(inode, ZUF_XF_SYSTEM, name, buf, PAGE_SIZE); + if (likely(ret > 0)) { + acl = _value_to_acl(buf, ret); + } else if (ret != -ENODATA) { + if (ret != 0) + zuf_dbg_err("failed to getattr ret=%d\n", ret); + acl = ERR_PTR(ret); + } + + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); + + zuf_smr_unlock(zii); + + free_page((ulong)buf); + + return acl; +} + +/* Used by creation of new inodes */ +int zuf_acls_create_pre(struct inode *dir, struct inode *inode, + struct posix_acl **user_acl) +{ + struct posix_acl *acl; + + if (!IS_POSIXACL(dir)) + return 0; + + zuf_dbg_acl("[%ld] i_ino=%ld i_mode=o%o\n", + dir->i_ino, inode->i_ino, inode->i_mode); + + if (S_ISLNK(inode->i_mode)) + return 0; + + acl = get_acl(dir, ACL_TYPE_DEFAULT); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (!acl) + inode->i_mode &= ~current_umask(); + else + *user_acl = acl; + + return 0; +} + +int zuf_acls_create_post(struct inode *dir, struct inode *inode, + struct posix_acl *acl) +{ + int err; + + zuf_dbg_acl("[%ld] i_ino=%ld i_mode=o%o\n", + dir->i_ino, inode->i_ino, inode->i_mode); + + if (S_ISDIR(inode->i_mode)) { + err = zuf_set_acl(inode, acl, ACL_TYPE_DEFAULT); + if (err) + goto cleanup; + } + err = __posix_acl_create(&acl, GFP_NOFS, &inode->i_mode); + if (unlikely(err < 0)) + return err; + + zus_zi(inode)->i_mode = cpu_to_le16(inode->i_mode); + if (err > 0) { /* This is an extended ACL */ + err = zuf_set_acl(inode, acl, ACL_TYPE_ACCESS); + } else { + /* NOTE: Boaz think we will cry over this... */ + struct zufs_ioc_attr ioc_attr = { + .hdr.in_len = sizeof(ioc_attr), + .hdr.out_len = sizeof(ioc_attr), + .hdr.operation = ZUFS_OP_SETATTR, + .zus_ii = ZUII(inode)->zus_ii, + .zuf_attr = STATX_MODE, + }; + + err = zufc_dispatch(ZUF_ROOT(SBI(inode->i_sb)), + &ioc_attr.hdr, NULL, 0); + if (unlikely(err && err != -EINTR)) + zuf_err("zufc_dispatch failed => %d\n", err); + } + +cleanup: + posix_acl_release(acl); + return err; +} diff --git a/fs/zuf/file.c b/fs/zuf/file.c index 814a75105321..0ec87ec4d078 100644 --- a/fs/zuf/file.c +++ b/fs/zuf/file.c @@ -521,5 +521,7 @@ const struct inode_operations zuf_file_inode_operations = { .getattr = zuf_getattr, .update_time = zuf_update_time, .fiemap = tozu_fiemap, + .get_acl = zuf_get_acl, + .set_acl = zuf_set_acl, .listxattr = zuf_listxattr, }; diff --git a/fs/zuf/inode.c b/fs/zuf/inode.c index 73f94e7062e5..3b9e78feab06 100644 --- a/fs/zuf/inode.c +++ b/fs/zuf/inode.c @@ -342,6 +342,7 @@ struct inode *zuf_new_inode(struct inode *dir, umode_t mode, .flags = tmpfile ? ZI_TMPFILE : 0, .str.len = qstr->len, }; + struct posix_acl *acl = NULL; struct inode *inode; struct zus_inode *zi = NULL; struct page *pages[2]; @@ -366,6 +367,10 @@ struct inode *zuf_new_inode(struct inode *dir, umode_t mode, if (err && err != -EOPNOTSUPP) goto fail; + err = zuf_acls_create_pre(dir, inode, &acl); + if (unlikely(err)) + goto fail; + zuf_set_inode_flags(inode, &ioc_new_inode.zi); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || @@ -406,6 +411,12 @@ struct inode *zuf_new_inode(struct inode *dir, umode_t mode, zuf_dbg_verbose("allocating inode %ld (zi=%p)\n", _zi_ino(zi), zi); + if (acl && !symname) { + err = zuf_acls_create_post(dir, inode, acl); + if (unlikely(err)) + goto fail; + } + err = insert_inode_locked(inode); if (unlikely(err)) { zuf_dbg_err("[%ld:%s] generation=%lld insert_inode_locked => %d\n", diff --git a/fs/zuf/namei.c b/fs/zuf/namei.c index 803069423674..a33745c328b9 100644 --- a/fs/zuf/namei.c +++ b/fs/zuf/namei.c @@ -420,6 +420,8 @@ const struct inode_operations zuf_dir_inode_operations = { .setattr = zuf_setattr, .getattr = zuf_getattr, .update_time = zuf_update_time, + .get_acl = zuf_get_acl, + .set_acl = zuf_set_acl, .listxattr = zuf_listxattr, }; @@ -427,5 +429,7 @@ const struct inode_operations zuf_special_inode_operations = { .setattr = zuf_setattr, .getattr = zuf_getattr, .update_time = zuf_update_time, + .get_acl = zuf_get_acl, + .set_acl = zuf_set_acl, .listxattr = zuf_listxattr, }; diff --git a/fs/zuf/zuf.h b/fs/zuf/zuf.h index 13b246189d8b..b6347dc6eb6a 100644 --- a/fs/zuf/zuf.h +++ b/fs/zuf/zuf.h @@ -335,6 +335,12 @@ enum { ZUF_XF_SECURITY = 1, ZUF_XF_USER = 4, }; +struct zuf_acl { + __le16 tag; + __le16 perm; + __le32 id; +} __packed; + enum big_alloc_type { ba_stack, ba_kmalloc, ba_vmalloc }; static inline