From patchwork Thu Jun 30 13:47:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Gruenbacher X-Patchwork-Id: 9207635 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 14EBE60752 for ; Thu, 30 Jun 2016 13:49:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 05081285BA for ; Thu, 30 Jun 2016 13:49:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EB7B628673; Thu, 30 Jun 2016 13:49:53 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from oss.sgi.com (oss.sgi.com [192.48.182.195]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A5689285BA for ; Thu, 30 Jun 2016 13:49:52 +0000 (UTC) Received: from oss.sgi.com (localhost [IPv6:::1]) by oss.sgi.com (Postfix) with ESMTP id 8B14B7CF7; Thu, 30 Jun 2016 08:49:32 -0500 (CDT) X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 679557CF6 for ; Thu, 30 Jun 2016 08:49:30 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2AFE98F8054 for ; Thu, 30 Jun 2016 06:49:30 -0700 (PDT) X-ASG-Debug-ID: 1467294568-04cb6c063f2c46b0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id A9UFZwt1dWJJM8zC (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 30 Jun 2016 06:49:28 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C7256627C5; Thu, 30 Jun 2016 13:49:27 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDst005273; Thu, 30 Jun 2016 09:49:21 -0400 From: Andreas Gruenbacher To: Alexander Viro Subject: [PATCH v23 18/22] richacl: xattr mapping functions Date: Thu, 30 Jun 2016 15:47:09 +0200 X-ASG-Orig-Subj: [PATCH v23 18/22] richacl: xattr mapping functions Message-Id: <1467294433-3222-19-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 30 Jun 2016 13:49:27 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294568 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9922 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Cc: "J. Bruce Fields" , linux-nfs@vger.kernel.org, Theodore Ts'o , Andreas Gruenbacher , linux-cifs@vger.kernel.org, linux-api@vger.kernel.org, Trond Myklebust , linux-kernel@vger.kernel.org, xfs@oss.sgi.com, Christoph Hellwig , Andreas Dilger , linux-fsdevel@vger.kernel.org, Jeff Layton , linux-ext4@vger.kernel.org, Anna Schumaker X-BeenThere: xfs@oss.sgi.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: XFS Filesystem from SGI List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xfs-bounces@oss.sgi.com Sender: xfs-bounces@oss.sgi.com X-Virus-Scanned: ClamAV using ClamSMTP Map between "system.richacl" xattrs and the in-kernel representation. Signed-off-by: Andreas Gruenbacher Reviewed-by: Jeff Layton --- fs/Makefile | 2 +- fs/richacl_xattr.c | 161 +++++++++++++++++++++++++++++++++++++ include/linux/richacl_xattr.h | 29 +++++++ include/uapi/linux/Kbuild | 1 + include/uapi/linux/richacl_xattr.h | 44 ++++++++++ include/uapi/linux/xattr.h | 2 + 6 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 fs/richacl_xattr.c create mode 100644 include/linux/richacl_xattr.h create mode 100644 include/uapi/linux/richacl_xattr.h diff --git a/fs/Makefile b/fs/Makefile index 2b3e6f1..262fd67 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -49,7 +49,7 @@ obj-$(CONFIG_COREDUMP) += coredump.o obj-$(CONFIG_SYSCTL) += drop_caches.o obj-$(CONFIG_FHANDLE) += fhandle.o -obj-$(CONFIG_FS_RICHACL) += richacl.o +obj-$(CONFIG_FS_RICHACL) += richacl.o richacl_xattr.o obj-y += quota/ diff --git a/fs/richacl_xattr.c b/fs/richacl_xattr.c new file mode 100644 index 0000000..dc1ad36 --- /dev/null +++ b/fs/richacl_xattr.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2006, 2010 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * Written by Andreas Gruenbacher + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include +#include + +/** + * richacl_from_xattr - convert a richacl xattr into the in-memory representation + */ +struct richacl * +richacl_from_xattr(struct user_namespace *user_ns, + const void *value, size_t size, int invalid_error) +{ + const struct richacl_xattr *xattr_acl = value; + const struct richace_xattr *xattr_ace = (void *)(xattr_acl + 1); + struct richacl *acl; + struct richace *ace; + int count; + + if (size < sizeof(*xattr_acl) || + xattr_acl->a_version != RICHACL_XATTR_VERSION || + (xattr_acl->a_flags & ~RICHACL_VALID_FLAGS)) + goto invalid; + size -= sizeof(*xattr_acl); + count = le16_to_cpu(xattr_acl->a_count); + if (count > RICHACL_XATTR_MAX_COUNT) + goto invalid; + if (size != count * sizeof(*xattr_ace)) + goto invalid; + + acl = richacl_alloc(count, GFP_NOFS); + if (!acl) + return ERR_PTR(-ENOMEM); + + acl->a_flags = xattr_acl->a_flags; + acl->a_owner_mask = le32_to_cpu(xattr_acl->a_owner_mask); + if (acl->a_owner_mask & ~RICHACE_VALID_MASK) + goto put_invalid; + acl->a_group_mask = le32_to_cpu(xattr_acl->a_group_mask); + if (acl->a_group_mask & ~RICHACE_VALID_MASK) + goto put_invalid; + acl->a_other_mask = le32_to_cpu(xattr_acl->a_other_mask); + if (acl->a_other_mask & ~RICHACE_VALID_MASK) + goto put_invalid; + + richacl_for_each_entry(ace, acl) { + ace->e_type = le16_to_cpu(xattr_ace->e_type); + ace->e_flags = le16_to_cpu(xattr_ace->e_flags); + ace->e_mask = le32_to_cpu(xattr_ace->e_mask); + + if (ace->e_flags & ~RICHACE_VALID_FLAGS) + goto put_invalid; + if (ace->e_flags & RICHACE_SPECIAL_WHO) { + ace->e_id.special = le32_to_cpu(xattr_ace->e_id); + if (ace->e_id.special > RICHACE_EVERYONE_SPECIAL_ID) + goto put_invalid; + } else if (ace->e_flags & RICHACE_IDENTIFIER_GROUP) { + u32 id = le32_to_cpu(xattr_ace->e_id); + + ace->e_id.gid = make_kgid(user_ns, id); + if (!gid_valid(ace->e_id.gid)) + goto put_invalid; + } else { + u32 id = le32_to_cpu(xattr_ace->e_id); + + ace->e_id.uid = make_kuid(user_ns, id); + if (!uid_valid(ace->e_id.uid)) + goto put_invalid; + } + if (ace->e_type > RICHACE_ACCESS_DENIED_ACE_TYPE || + (ace->e_mask & ~RICHACE_VALID_MASK)) + goto put_invalid; + + xattr_ace++; + } + + return acl; + +put_invalid: + richacl_put(acl); +invalid: + return ERR_PTR(invalid_error); +} +EXPORT_SYMBOL_GPL(richacl_from_xattr); + +/** + * richacl_xattr_size - compute the size of the xattr representation of @acl + */ +size_t +richacl_xattr_size(const struct richacl *acl) +{ + size_t size = sizeof(struct richacl_xattr); + + size += sizeof(struct richace_xattr) * acl->a_count; + return size; +} +EXPORT_SYMBOL_GPL(richacl_xattr_size); + +/** + * richacl_to_xattr - convert @acl into its xattr representation + * @acl: the richacl to convert + * @buffer: buffer for the result + * @size: size of @buffer + */ +int +richacl_to_xattr(struct user_namespace *user_ns, + const struct richacl *acl, void *buffer, size_t size) +{ + struct richacl_xattr *xattr_acl = buffer; + struct richace_xattr *xattr_ace; + const struct richace *ace; + size_t real_size; + + real_size = richacl_xattr_size(acl); + if (!buffer) + return real_size; + if (real_size > size) + return -ERANGE; + + xattr_acl->a_version = RICHACL_XATTR_VERSION; + xattr_acl->a_flags = acl->a_flags; + xattr_acl->a_count = cpu_to_le16(acl->a_count); + + xattr_acl->a_owner_mask = cpu_to_le32(acl->a_owner_mask); + xattr_acl->a_group_mask = cpu_to_le32(acl->a_group_mask); + xattr_acl->a_other_mask = cpu_to_le32(acl->a_other_mask); + + xattr_ace = (void *)(xattr_acl + 1); + richacl_for_each_entry(ace, acl) { + xattr_ace->e_type = cpu_to_le16(ace->e_type); + xattr_ace->e_flags = cpu_to_le16(ace->e_flags); + xattr_ace->e_mask = cpu_to_le32(ace->e_mask); + if (ace->e_flags & RICHACE_SPECIAL_WHO) + xattr_ace->e_id = cpu_to_le32(ace->e_id.special); + else if (ace->e_flags & RICHACE_IDENTIFIER_GROUP) + xattr_ace->e_id = + cpu_to_le32(from_kgid(user_ns, ace->e_id.gid)); + else + xattr_ace->e_id = + cpu_to_le32(from_kuid(user_ns, ace->e_id.uid)); + xattr_ace++; + } + return real_size; +} +EXPORT_SYMBOL_GPL(richacl_to_xattr); diff --git a/include/linux/richacl_xattr.h b/include/linux/richacl_xattr.h new file mode 100644 index 0000000..0efa14b --- /dev/null +++ b/include/linux/richacl_xattr.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2006, 2010 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * Written by Andreas Gruenbacher + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef __RICHACL_XATTR_H +#define __RICHACL_XATTR_H + +#include +#include + +extern struct richacl *richacl_from_xattr(struct user_namespace *, const void *, + size_t, int); +extern size_t richacl_xattr_size(const struct richacl *); +extern int richacl_to_xattr(struct user_namespace *, const struct richacl *, + void *, size_t); + +#endif /* __RICHACL_XATTR_H */ diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index abeaa98..c24e106 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -356,6 +356,7 @@ header-y += reiserfs_fs.h header-y += reiserfs_xattr.h header-y += resource.h header-y += richacl.h +header-y += richacl_xattr.h header-y += rfkill.h header-y += rio_mport_cdev.h header-y += romfs_fs.h diff --git a/include/uapi/linux/richacl_xattr.h b/include/uapi/linux/richacl_xattr.h new file mode 100644 index 0000000..20da204 --- /dev/null +++ b/include/uapi/linux/richacl_xattr.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2006, 2010 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * Written by Andreas Gruenbacher + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#ifndef __UAPI_RICHACL_XATTR_H +#define __UAPI_RICHACL_XATTR_H + +#include +#include + +struct richace_xattr { + __le16 e_type; + __le16 e_flags; + __le32 e_mask; + __le32 e_id; +}; + +struct richacl_xattr { + __u8 a_version; + __u8 a_flags; + __le16 a_count; + __le32 a_owner_mask; + __le32 a_group_mask; + __le32 a_other_mask; +}; + +#define RICHACL_XATTR_VERSION 0 +#define RICHACL_XATTR_MAX_COUNT \ + ((XATTR_SIZE_MAX - sizeof(struct richacl_xattr)) / \ + sizeof(struct richace_xattr)) + +#endif /* __UAPI_RICHACL_XATTR_H */ diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h index 1590c49..1996903 100644 --- a/include/uapi/linux/xattr.h +++ b/include/uapi/linux/xattr.h @@ -73,5 +73,7 @@ #define XATTR_POSIX_ACL_DEFAULT "posix_acl_default" #define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT +#define XATTR_RICHACL "richacl" +#define XATTR_NAME_RICHACL XATTR_SYSTEM_PREFIX XATTR_RICHACL #endif /* _UAPI_LINUX_XATTR_H */