From patchwork Fri Apr 29 14:18:35 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Gruenbacher X-Patchwork-Id: 8983231 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 3F495BF29F for ; Fri, 29 Apr 2016 14:18:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 22759201E4 for ; Fri, 29 Apr 2016 14:18:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C99C0201DD for ; Fri, 29 Apr 2016 14:18:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753114AbcD2OSt (ORCPT ); Fri, 29 Apr 2016 10:18:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52562 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753550AbcD2OSs (ORCPT ); Fri, 29 Apr 2016 10:18:48 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (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 5CF1062653; Fri, 29 Apr 2016 14:18:48 +0000 (UTC) Received: from nux.redhat.com (vpn1-6-50.ams2.redhat.com [10.36.6.50]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u3TEIcEb022068; Fri, 29 Apr 2016 10:18:46 -0400 From: Andreas Gruenbacher To: Alexander Viro Cc: Andreas Gruenbacher , linux-fsdevel@vger.kernel.org, Greg Kroah-Hartman Subject: [PATCH 3/5] kernfs: Switch to generic xattr handlers Date: Fri, 29 Apr 2016 16:18:35 +0200 Message-Id: <1461939517-15497-4-git-send-email-agruenba@redhat.com> In-Reply-To: <1461939517-15497-1-git-send-email-agruenba@redhat.com> References: <1461939517-15497-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 29 Apr 2016 14:18:48 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Unlike with most other filesystems, xattrs in kernfs are attached to the dentries (dentry->d_fsdata). Once security modules start calling get xattr handlers with a NULL dentry (because of an unknown dentry), we'll have to start check for that in kernfs_xattr_get. Signed-off-by: Andreas Gruenbacher Cc: Greg Kroah-Hartman --- fs/kernfs/dir.c | 6 +- fs/kernfs/inode.c | 150 ++++++++++++++++++++++++-------------------- fs/kernfs/kernfs-internal.h | 6 +- fs/kernfs/mount.c | 1 + fs/kernfs/symlink.c | 6 +- 5 files changed, 91 insertions(+), 78 deletions(-) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 03b688d..f67d896 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -1125,9 +1125,9 @@ const struct inode_operations kernfs_dir_iops = { .permission = kernfs_iop_permission, .setattr = kernfs_iop_setattr, .getattr = kernfs_iop_getattr, - .setxattr = kernfs_iop_setxattr, - .removexattr = kernfs_iop_removexattr, - .getxattr = kernfs_iop_getxattr, + .setxattr = generic_setxattr, + .removexattr = generic_removexattr, + .getxattr = generic_getxattr, .listxattr = kernfs_iop_listxattr, .mkdir = kernfs_iop_mkdir, diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index b524722..1dfb44a 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -28,9 +28,9 @@ static const struct inode_operations kernfs_iops = { .permission = kernfs_iop_permission, .setattr = kernfs_iop_setattr, .getattr = kernfs_iop_getattr, - .setxattr = kernfs_iop_setxattr, - .removexattr = kernfs_iop_removexattr, - .getxattr = kernfs_iop_getxattr, + .setxattr = generic_setxattr, + .removexattr = generic_removexattr, + .getxattr = generic_getxattr, .listxattr = kernfs_iop_listxattr, }; @@ -157,70 +157,6 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata, return 0; } -int kernfs_iop_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - struct kernfs_node *kn = dentry->d_fsdata; - struct kernfs_iattrs *attrs; - void *secdata; - int error; - u32 secdata_len = 0; - - attrs = kernfs_iattrs(kn); - if (!attrs) - return -ENOMEM; - - if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { - const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; - error = security_inode_setsecurity(d_inode(dentry), suffix, - value, size, flags); - if (error) - return error; - error = security_inode_getsecctx(d_inode(dentry), - &secdata, &secdata_len); - if (error) - return error; - - mutex_lock(&kernfs_mutex); - error = kernfs_node_setsecdata(kn, &secdata, &secdata_len); - mutex_unlock(&kernfs_mutex); - - if (secdata) - security_release_secctx(secdata, secdata_len); - return error; - } else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) { - return simple_xattr_set(&attrs->xattrs, name, value, size, - flags); - } - - return -EINVAL; -} - -int kernfs_iop_removexattr(struct dentry *dentry, const char *name) -{ - struct kernfs_node *kn = dentry->d_fsdata; - struct kernfs_iattrs *attrs; - - attrs = kernfs_iattrs(kn); - if (!attrs) - return -ENOMEM; - - return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE); -} - -ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode, - const char *name, void *buf, size_t size) -{ - struct kernfs_node *kn = inode->i_private; - struct kernfs_iattrs *attrs; - - attrs = kernfs_iattrs(kn); - if (!attrs) - return -ENOMEM; - - return simple_xattr_get(&attrs->xattrs, name, buf, size); -} - ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) { struct kernfs_node *kn = dentry->d_fsdata; @@ -370,3 +306,83 @@ int kernfs_iop_permission(struct inode *inode, int mask) return generic_permission(inode, mask); } + +static int kernfs_xattr_get(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *suffix, void *value, size_t size) +{ + const char *name = xattr_full_name(handler, suffix); + struct kernfs_node *kn; + struct kernfs_iattrs *attrs; + + kn = dentry->d_fsdata; + attrs = kernfs_iattrs(kn); + if (!attrs) + return -ENOMEM; + + return simple_xattr_get(&attrs->xattrs, name, value, size); +} + +static int kernfs_xattr_set(const struct xattr_handler *handler, + struct dentry *dentry, const char *suffix, + const void *value, size_t size, int flags) +{ + const char *name = xattr_full_name(handler, suffix); + struct kernfs_node *kn = dentry->d_fsdata; + struct kernfs_iattrs *attrs; + + attrs = kernfs_iattrs(kn); + if (!attrs) + return -ENOMEM; + + return simple_xattr_set(&attrs->xattrs, name, value, size, flags); +} + +const struct xattr_handler kernfs_trusted_xattr_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .get = kernfs_xattr_get, + .set = kernfs_xattr_set, +}; + +static int kernfs_security_xattr_set(const struct xattr_handler *handler, + struct dentry *dentry, const char *suffix, + const void *value, size_t size, int flags) +{ + struct kernfs_node *kn = dentry->d_fsdata; + struct inode *inode = d_inode(dentry); + struct kernfs_iattrs *attrs; + void *secdata; + u32 secdata_len = 0; + int error; + + attrs = kernfs_iattrs(kn); + if (!attrs) + return -ENOMEM; + + error = security_inode_setsecurity(inode, suffix, value, size, flags); + if (error) + return error; + error = security_inode_getsecctx(inode, &secdata, &secdata_len); + if (error) + return error; + + mutex_lock(&kernfs_mutex); + error = kernfs_node_setsecdata(kn, &secdata, &secdata_len); + mutex_unlock(&kernfs_mutex); + + if (secdata) + security_release_secctx(secdata, secdata_len); + return error; +} + +const struct xattr_handler kernfs_security_xattr_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .get = kernfs_xattr_get, + .set = kernfs_security_xattr_set, +}; + +const struct xattr_handler *kernfs_xattr_handlers[] = { + &kernfs_trusted_xattr_handler, + &kernfs_security_xattr_handler, + NULL +}; diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 45c9192..bfd551b 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -76,16 +76,12 @@ extern struct kmem_cache *kernfs_node_cache; /* * inode.c */ +extern const struct xattr_handler *kernfs_xattr_handlers[]; void kernfs_evict_inode(struct inode *inode); int kernfs_iop_permission(struct inode *inode, int mask); int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr); int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); -int kernfs_iop_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t size, int flags); -int kernfs_iop_removexattr(struct dentry *dentry, const char *name); -ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode, - const char *name, void *buf, size_t size); ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size); /* diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index b67dbcc..5446c3b 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c @@ -142,6 +142,7 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic) sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = magic; sb->s_op = &kernfs_sops; + sb->s_xattr = kernfs_xattr_handlers; sb->s_time_gran = 1; /* get root inode, initialize and unlock it */ diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 117b8b3..549a14c7 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -134,9 +134,9 @@ static const char *kernfs_iop_get_link(struct dentry *dentry, } const struct inode_operations kernfs_symlink_iops = { - .setxattr = kernfs_iop_setxattr, - .removexattr = kernfs_iop_removexattr, - .getxattr = kernfs_iop_getxattr, + .setxattr = generic_setxattr, + .removexattr = generic_removexattr, + .getxattr = generic_getxattr, .listxattr = kernfs_iop_listxattr, .readlink = generic_readlink, .get_link = kernfs_iop_get_link,