From patchwork Mon Nov 30 21:43:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Gruenbacher X-Patchwork-Id: 7730161 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7D23E9F39B for ; Mon, 30 Nov 2015 21:47:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9CEB3204CF for ; Mon, 30 Nov 2015 21:47:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8B9CC204A7 for ; Mon, 30 Nov 2015 21:47:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755232AbbK3Vqp (ORCPT ); Mon, 30 Nov 2015 16:46:45 -0500 Received: from mx1.redhat.com ([209.132.183.28]:60109 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755030AbbK3VoD (ORCPT ); Mon, 30 Nov 2015 16:44:03 -0500 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id 991D3120487; Mon, 30 Nov 2015 21:44:03 +0000 (UTC) Received: from nux.redhat.com (vpn1-6-54.ams2.redhat.com [10.36.6.54]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tAULhiRM010792; Mon, 30 Nov 2015 16:44:00 -0500 From: Andreas Gruenbacher To: Alexander Viro , Christoph Hellwig , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Cc: Andreas Gruenbacher Subject: [PATCH 04/10] vfs: Distinguish between full xattr names and proper prefixes Date: Mon, 30 Nov 2015 22:43:37 +0100 Message-Id: <1448919823-27103-5-git-send-email-agruenba@redhat.com> In-Reply-To: <1448919823-27103-1-git-send-email-agruenba@redhat.com> References: <1448919823-27103-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_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 Add an additional "name" field to struct xattr_handler. When the name is set, the handler matches attributes with exactly that name. When the prefix is set instead, the handler matches attributes with the given prefix and with a non-empty suffix. This patch should avoid bugs like the one fixed in commit c361016a in the future. Signed-off-by: Andreas Gruenbacher Reviewed-by: James Morris --- fs/9p/acl.c | 16 +++++----------- fs/9p/xattr.c | 4 ---- fs/ext2/xattr_security.c | 4 ---- fs/ext2/xattr_trusted.c | 4 ---- fs/ext2/xattr_user.c | 4 ---- fs/ext4/xattr_security.c | 4 ---- fs/ext4/xattr_trusted.c | 4 ---- fs/ext4/xattr_user.c | 4 ---- fs/f2fs/xattr.c | 19 +++++-------------- fs/f2fs/xattr.h | 2 +- fs/hfsplus/xattr.c | 12 ------------ fs/jffs2/security.c | 6 ------ fs/jffs2/xattr_trusted.c | 4 ---- fs/jffs2/xattr_user.c | 4 ---- fs/nfs/nfs4proc.c | 8 +------- fs/ocfs2/xattr.c | 19 +++---------------- fs/posix_acl.c | 10 +++------- fs/reiserfs/xattr.c | 3 ++- fs/squashfs/xattr.c | 3 --- fs/xattr.c | 27 +++++++++++++++++---------- fs/xfs/xfs_xattr.c | 6 ------ include/linux/xattr.h | 6 ++++++ 22 files changed, 43 insertions(+), 130 deletions(-) diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 6ff30b1..9da967f 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -220,15 +220,12 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler, struct posix_acl *acl; int error; - if (strcmp(name, "") != 0) - return -EINVAL; - v9ses = v9fs_dentry2v9ses(dentry); /* * We allow set/get/list of acl when access=client is not specified */ if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) - return v9fs_xattr_get(dentry, handler->prefix, buffer, size); + return v9fs_xattr_get(dentry, handler->name, buffer, size); acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags); if (IS_ERR(acl)) @@ -250,16 +247,13 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, struct v9fs_session_info *v9ses; struct inode *inode = d_inode(dentry); - if (strcmp(name, "") != 0) - return -EINVAL; - v9ses = v9fs_dentry2v9ses(dentry); /* * set the attribute on the remote. Without even looking at the * xattr value. We leave it to the server to validate */ if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) - return v9fs_xattr_set(dentry, handler->prefix, value, size, + return v9fs_xattr_set(dentry, handler->name, value, size, flags); if (S_ISLNK(inode->i_mode)) @@ -319,7 +313,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, default: BUG(); } - retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags); + retval = v9fs_xattr_set(dentry, handler->name, value, size, flags); if (!retval) set_cached_acl(inode, handler->flags, acl); err_out: @@ -328,14 +322,14 @@ err_out: } const struct xattr_handler v9fs_xattr_acl_access_handler = { - .prefix = XATTR_NAME_POSIX_ACL_ACCESS, + .name = XATTR_NAME_POSIX_ACL_ACCESS, .flags = ACL_TYPE_ACCESS, .get = v9fs_xattr_get_acl, .set = v9fs_xattr_set_acl, }; const struct xattr_handler v9fs_xattr_acl_default_handler = { - .prefix = XATTR_NAME_POSIX_ACL_DEFAULT, + .name = XATTR_NAME_POSIX_ACL_DEFAULT, .flags = ACL_TYPE_DEFAULT, .get = v9fs_xattr_get_acl, .set = v9fs_xattr_set_acl, diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c index e3d026a..9dd9b47 100644 --- a/fs/9p/xattr.c +++ b/fs/9p/xattr.c @@ -143,8 +143,6 @@ static int v9fs_xattr_handler_get(const struct xattr_handler *handler, { const char *full_name = xattr_full_name(handler, name); - if (strcmp(name, "") == 0) - return -EINVAL; return v9fs_xattr_get(dentry, full_name, buffer, size); } @@ -154,8 +152,6 @@ static int v9fs_xattr_handler_set(const struct xattr_handler *handler, { const char *full_name = xattr_full_name(handler, name); - if (strcmp(name, "") == 0) - return -EINVAL; return v9fs_xattr_set(dentry, full_name, value, size, flags); } diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index dfb0875..118bf23 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c @@ -28,8 +28,6 @@ ext2_xattr_security_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strcmp(name, "") == 0) - return -EINVAL; return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name, buffer, size); } @@ -39,8 +37,6 @@ ext2_xattr_security_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - if (strcmp(name, "") == 0) - return -EINVAL; return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name, value, size, flags); } diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c index 3150dd3..3f8f2bc 100644 --- a/fs/ext2/xattr_trusted.c +++ b/fs/ext2/xattr_trusted.c @@ -32,8 +32,6 @@ ext2_xattr_trusted_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strcmp(name, "") == 0) - return -EINVAL; return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name, buffer, size); } @@ -43,8 +41,6 @@ ext2_xattr_trusted_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - if (strcmp(name, "") == 0) - return -EINVAL; return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name, value, size, flags); } diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c index 339a49b..afd45ab 100644 --- a/fs/ext2/xattr_user.c +++ b/fs/ext2/xattr_user.c @@ -34,8 +34,6 @@ ext2_xattr_user_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strcmp(name, "") == 0) - return -EINVAL; if (!test_opt(dentry->d_sb, XATTR_USER)) return -EOPNOTSUPP; return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_USER, @@ -47,8 +45,6 @@ ext2_xattr_user_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - if (strcmp(name, "") == 0) - return -EINVAL; if (!test_opt(dentry->d_sb, XATTR_USER)) return -EOPNOTSUPP; diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c index 36f4c1a..195abc4 100644 --- a/fs/ext4/xattr_security.c +++ b/fs/ext4/xattr_security.c @@ -33,8 +33,6 @@ ext4_xattr_security_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strcmp(name, "") == 0) - return -EINVAL; return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY, name, buffer, size); } @@ -44,8 +42,6 @@ ext4_xattr_security_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - if (strcmp(name, "") == 0) - return -EINVAL; return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY, name, value, size, flags); } diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c index 4880890..121fdf9 100644 --- a/fs/ext4/xattr_trusted.c +++ b/fs/ext4/xattr_trusted.c @@ -36,8 +36,6 @@ ext4_xattr_trusted_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strcmp(name, "") == 0) - return -EINVAL; return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED, name, buffer, size); } @@ -47,8 +45,6 @@ ext4_xattr_trusted_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - if (strcmp(name, "") == 0) - return -EINVAL; return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED, name, value, size, flags); } diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c index d2dec33..577fc12 100644 --- a/fs/ext4/xattr_user.c +++ b/fs/ext4/xattr_user.c @@ -35,8 +35,6 @@ ext4_xattr_user_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strcmp(name, "") == 0) - return -EINVAL; if (!test_opt(dentry->d_sb, XATTR_USER)) return -EOPNOTSUPP; return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_USER, @@ -48,8 +46,6 @@ ext4_xattr_user_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - if (strcmp(name, "") == 0) - return -EINVAL; if (!test_opt(dentry->d_sb, XATTR_USER)) return -EOPNOTSUPP; return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_USER, diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 862368a..b2cc7a0 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -30,6 +30,7 @@ static size_t f2fs_xattr_generic_list(const struct xattr_handler *handler, const char *name, size_t len) { struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); + const char *prefix = handler->prefix ?: handler->name; int total_len, prefix_len; switch (handler->flags) { @@ -47,10 +48,10 @@ static size_t f2fs_xattr_generic_list(const struct xattr_handler *handler, return -EINVAL; } - prefix_len = strlen(handler->prefix); + prefix_len = strlen(prefix); total_len = prefix_len + len + 1; if (list && total_len <= list_size) { - memcpy(list, handler->prefix, prefix_len); + memcpy(list, prefix, prefix_len); memcpy(list + prefix_len, name, len); list[prefix_len + len] = '\0'; } @@ -77,8 +78,6 @@ static int f2fs_xattr_generic_get(const struct xattr_handler *handler, default: return -EINVAL; } - if (strcmp(name, "") == 0) - return -EINVAL; return f2fs_getxattr(d_inode(dentry), handler->flags, name, buffer, size, NULL); } @@ -103,9 +102,6 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler, default: return -EINVAL; } - if (strcmp(name, "") == 0) - return -EINVAL; - return f2fs_setxattr(d_inode(dentry), handler->flags, name, value, size, NULL, flags); } @@ -114,7 +110,7 @@ static size_t f2fs_xattr_advise_list(const struct xattr_handler *handler, struct dentry *dentry, char *list, size_t list_size, const char *name, size_t len) { - const char *xname = F2FS_SYSTEM_ADVISE_PREFIX; + const char *xname = F2FS_SYSTEM_ADVISE_NAME; size_t size; size = strlen(xname) + 1; @@ -129,9 +125,6 @@ static int f2fs_xattr_advise_get(const struct xattr_handler *handler, { struct inode *inode = d_inode(dentry); - if (strcmp(name, "") != 0) - return -EINVAL; - if (buffer) *((char *)buffer) = F2FS_I(inode)->i_advise; return sizeof(char); @@ -143,8 +136,6 @@ static int f2fs_xattr_advise_set(const struct xattr_handler *handler, { struct inode *inode = d_inode(dentry); - if (strcmp(name, "") != 0) - return -EINVAL; if (!inode_owner_or_capable(inode)) return -EPERM; if (value == NULL) @@ -197,7 +188,7 @@ const struct xattr_handler f2fs_xattr_trusted_handler = { }; const struct xattr_handler f2fs_xattr_advise_handler = { - .prefix = F2FS_SYSTEM_ADVISE_PREFIX, + .name = F2FS_SYSTEM_ADVISE_NAME, .flags = F2FS_XATTR_INDEX_ADVISE, .list = f2fs_xattr_advise_list, .get = f2fs_xattr_advise_get, diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index 71a7100..79dccc8 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h @@ -27,7 +27,7 @@ #define F2FS_XATTR_REFCOUNT_MAX 1024 /* Name indexes */ -#define F2FS_SYSTEM_ADVISE_PREFIX "system.advise" +#define F2FS_SYSTEM_ADVISE_NAME "system.advise" #define F2FS_XATTR_INDEX_USER 1 #define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT 3 diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index e41a010..ab01530 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -431,9 +431,6 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name, char *xattr_name; int res; - if (!strcmp(name, "")) - return -EINVAL; - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, GFP_KERNEL); if (!xattr_name) @@ -589,9 +586,6 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, int res; char *xattr_name; - if (!strcmp(name, "")) - return -EINVAL; - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, GFP_KERNEL); if (!xattr_name) @@ -853,9 +847,6 @@ static int hfsplus_osx_getxattr(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (!strcmp(name, "")) - return -EINVAL; - /* * Don't allow retrieving properly prefixed attributes * by prepending them with "osx." @@ -876,9 +867,6 @@ static int hfsplus_osx_setxattr(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags) { - if (!strcmp(name, "")) - return -EINVAL; - /* * Don't allow setting properly prefixed attributes * by prepending them with "osx." diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c index bf12fe5..ea79932 100644 --- a/fs/jffs2/security.c +++ b/fs/jffs2/security.c @@ -52,9 +52,6 @@ static int jffs2_security_getxattr(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (!strcmp(name, "")) - return -EINVAL; - return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY, name, buffer, size); } @@ -63,9 +60,6 @@ static int jffs2_security_setxattr(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags) { - if (!strcmp(name, "")) - return -EINVAL; - return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY, name, buffer, size, flags); } diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c index a562da0..8b55fe4 100644 --- a/fs/jffs2/xattr_trusted.c +++ b/fs/jffs2/xattr_trusted.c @@ -20,8 +20,6 @@ static int jffs2_trusted_getxattr(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (!strcmp(name, "")) - return -EINVAL; return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED, name, buffer, size); } @@ -30,8 +28,6 @@ static int jffs2_trusted_setxattr(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags) { - if (!strcmp(name, "")) - return -EINVAL; return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags); } diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c index cbc0472..b04335b 100644 --- a/fs/jffs2/xattr_user.c +++ b/fs/jffs2/xattr_user.c @@ -20,8 +20,6 @@ static int jffs2_user_getxattr(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (!strcmp(name, "")) - return -EINVAL; return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_USER, name, buffer, size); } @@ -30,8 +28,6 @@ static int jffs2_user_setxattr(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags) { - if (!strcmp(name, "")) - return -EINVAL; return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_USER, name, buffer, size, flags); } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8981803..f6f40aa 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6253,9 +6253,6 @@ static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler, const void *buf, size_t buflen, int flags) { - if (strcmp(key, "") != 0) - return -EINVAL; - return nfs4_proc_set_acl(d_inode(dentry), buf, buflen); } @@ -6263,9 +6260,6 @@ static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler, struct dentry *dentry, const char *key, void *buf, size_t buflen) { - if (strcmp(key, "") != 0) - return -EINVAL; - return nfs4_proc_get_acl(d_inode(dentry), buf, buflen); } @@ -8834,7 +8828,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { }; static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { - .prefix = XATTR_NAME_NFSV4_ACL, + .name = XATTR_NAME_NFSV4_ACL, .list = nfs4_xattr_list_nfs4_acl, .get = nfs4_xattr_get_nfs4_acl, .set = nfs4_xattr_set_nfs4_acl, diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e9164f0..906022d 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -544,8 +544,9 @@ static inline const char *ocfs2_xattr_prefix(int name_index) if (name_index > 0 && name_index < OCFS2_XATTR_MAX) handler = ocfs2_xattr_handler_map[name_index]; - - return handler ? handler->prefix : NULL; + if (!handler) + return NULL; + return handler->prefix ?: handler->name; } static u32 ocfs2_xattr_name_hash(struct inode *inode, @@ -7249,8 +7250,6 @@ static int ocfs2_xattr_security_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strcmp(name, "") == 0) - return -EINVAL; return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY, name, buffer, size); } @@ -7259,9 +7258,6 @@ static int ocfs2_xattr_security_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - if (strcmp(name, "") == 0) - return -EINVAL; - return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY, name, value, size, flags); } @@ -7345,8 +7341,6 @@ static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler, struct dentry *dentry, const char *name, void *buffer, size_t size) { - if (strcmp(name, "") == 0) - return -EINVAL; return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED, name, buffer, size); } @@ -7355,9 +7349,6 @@ static int ocfs2_xattr_trusted_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - if (strcmp(name, "") == 0) - return -EINVAL; - return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED, name, value, size, flags); } @@ -7398,8 +7389,6 @@ static int ocfs2_xattr_user_get(const struct xattr_handler *handler, { struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); - if (strcmp(name, "") == 0) - return -EINVAL; if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR) return -EOPNOTSUPP; return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_USER, name, @@ -7412,8 +7401,6 @@ static int ocfs2_xattr_user_set(const struct xattr_handler *handler, { struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); - if (strcmp(name, "") == 0) - return -EINVAL; if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR) return -EOPNOTSUPP; diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 571465d..17efd76 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -769,8 +769,6 @@ posix_acl_xattr_get(const struct xattr_handler *handler, struct posix_acl *acl; int error; - if (strcmp(name, "") != 0) - return -EINVAL; if (!IS_POSIXACL(d_backing_inode(dentry))) return -EOPNOTSUPP; if (d_is_symlink(dentry)) @@ -797,8 +795,6 @@ posix_acl_xattr_set(const struct xattr_handler *handler, struct posix_acl *acl = NULL; int ret; - if (strcmp(name, "") != 0) - return -EINVAL; if (!IS_POSIXACL(inode)) return -EOPNOTSUPP; if (!inode->i_op->set_acl) @@ -832,7 +828,7 @@ posix_acl_xattr_list(const struct xattr_handler *handler, struct dentry *dentry, char *list, size_t list_size, const char *name, size_t name_len) { - const char *xname = handler->prefix; + const char *xname = handler->name; size_t size; if (!IS_POSIXACL(d_backing_inode(dentry))) @@ -845,7 +841,7 @@ posix_acl_xattr_list(const struct xattr_handler *handler, } const struct xattr_handler posix_acl_access_xattr_handler = { - .prefix = XATTR_NAME_POSIX_ACL_ACCESS, + .name = XATTR_NAME_POSIX_ACL_ACCESS, .flags = ACL_TYPE_ACCESS, .list = posix_acl_xattr_list, .get = posix_acl_xattr_get, @@ -854,7 +850,7 @@ const struct xattr_handler posix_acl_access_xattr_handler = { EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler); const struct xattr_handler posix_acl_default_xattr_handler = { - .prefix = XATTR_NAME_POSIX_ACL_DEFAULT, + .name = XATTR_NAME_POSIX_ACL_DEFAULT, .flags = ACL_TYPE_DEFAULT, .list = posix_acl_xattr_list, .get = posix_acl_xattr_get, diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 66b26fd..5c3c2fe 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -756,7 +756,8 @@ find_xattr_handler_prefix(const struct xattr_handler **handlers, return NULL; for_each_xattr_handler(handlers, xah) { - if (strncmp(xah->prefix, name, strlen(xah->prefix)) == 0) + const char *prefix = xah->prefix ?: xah->name; + if (strncmp(prefix, name, strlen(prefix)) == 0) break; } diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c index 6a4cc34..2f0ccba 100644 --- a/fs/squashfs/xattr.c +++ b/fs/squashfs/xattr.c @@ -228,9 +228,6 @@ static int squashfs_xattr_handler_get(const struct xattr_handler *handler, struct dentry *d, const char *name, void *buffer, size_t size) { - if (name[0] == '\0') - return -EINVAL; - return squashfs_xattr_get(d_inode(d), handler->flags, name, buffer, size); } diff --git a/fs/xattr.c b/fs/xattr.c index 58bdabc..aaea9e4 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -681,13 +681,20 @@ xattr_resolve_name(const struct xattr_handler **handlers, const char **name) return NULL; for_each_xattr_handler(handlers, handler) { - const char *n = strcmp_prefix(*name, handler->prefix); + const char *n; + + n = strcmp_prefix(*name, handler->prefix ?: handler->name); if (n) { + if (!handler->prefix ^ !*n) { + if (*n) + continue; + return ERR_PTR(-EINVAL); + } *name = n; - break; + return handler; } } - return handler; + return ERR_PTR(-EOPNOTSUPP); } /* @@ -699,8 +706,8 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s const struct xattr_handler *handler; handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); - if (!handler) - return -EOPNOTSUPP; + if (IS_ERR(handler)) + return PTR_ERR(handler); return handler->get(handler, dentry, name, buffer, size); } @@ -746,8 +753,8 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz if (size == 0) value = ""; /* empty EA, do not remove */ handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); - if (!handler) - return -EOPNOTSUPP; + if (IS_ERR(handler)) + return PTR_ERR(handler); return handler->set(handler, dentry, name, value, size, flags); } @@ -761,8 +768,8 @@ generic_removexattr(struct dentry *dentry, const char *name) const struct xattr_handler *handler; handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); - if (!handler) - return -EOPNOTSUPP; + if (IS_ERR(handler)) + return PTR_ERR(handler); return handler->set(handler, dentry, name, NULL, 0, XATTR_REPLACE); } @@ -789,7 +796,7 @@ EXPORT_SYMBOL(generic_removexattr); const char *xattr_full_name(const struct xattr_handler *handler, const char *name) { - size_t prefix_len = strlen(handler->prefix); + size_t prefix_len = strlen(handler->prefix ?: handler->name); return name - prefix_len; } diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 7288795..36a4385 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -39,9 +39,6 @@ xfs_xattr_get(const struct xattr_handler *handler, struct dentry *dentry, struct xfs_inode *ip = XFS_I(d_inode(dentry)); int error, asize = size; - if (strcmp(name, "") == 0) - return -EINVAL; - /* Convert Linux syscall to XFS internal ATTR flags */ if (!size) { xflags |= ATTR_KERNOVAL; @@ -84,9 +81,6 @@ xfs_xattr_set(const struct xattr_handler *handler, struct dentry *dentry, struct xfs_inode *ip = XFS_I(d_inode(dentry)); int error; - if (strcmp(name, "") == 0) - return -EINVAL; - /* Convert Linux syscall to XFS internal ATTR flags */ if (flags & XATTR_CREATE) xflags |= ATTR_CREATE; diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 45fa345..3099e16 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -19,7 +19,13 @@ struct inode; struct dentry; +/* + * struct xattr_handler: When @name is set, match attributes with exactly that + * name. When @prefix is set instead, match attributes with that prefix and + * with a non-empty suffix. + */ struct xattr_handler { + const char *name; const char *prefix; int flags; /* fs private flags */ size_t (*list)(const struct xattr_handler *, struct dentry *dentry,