From patchwork Wed May 11 15:54:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Simmons X-Patchwork-Id: 9072301 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 03ABDBF29F for ; Wed, 11 May 2016 15:54:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7076D2012D for ; Wed, 11 May 2016 15:54:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 34183200ED for ; Wed, 11 May 2016 15:54:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751561AbcEKPyK (ORCPT ); Wed, 11 May 2016 11:54:10 -0400 Received: from casper.infradead.org ([85.118.1.10]:38702 "EHLO casper.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751405AbcEKPyJ (ORCPT ); Wed, 11 May 2016 11:54:09 -0400 Received: from jsimmons (helo=localhost) by casper.infradead.org with local-esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1b0WSX-0003TB-VL; Wed, 11 May 2016 15:54:02 +0000 Date: Wed, 11 May 2016 16:54:01 +0100 (BST) From: James Simmons To: Alexander Viro cc: Andreas Gruenbacher , linux-fsdevel , Tyler Hicks , ecryptfs@vger.kernel.org, Miklos Szeredi , linux-unionfs@vger.kernel.org, fuse-devel@lists.sourceforge.net, Mimi Zohar , linux-ima-devel@lists.sourceforge.net, linux-security-module@vger.kernel.org, David Howells , Serge Hallyn , Dmitry Kasatkin , Paul Moore , Stephen Smalley , Eric Paris , Casey Schaufler , Oleg Drokin , Andreas Dilger , Lustre Developement Subject: [PATCH] xattr handlers: fixup generic_listxattr In-Reply-To: <551ED650-CBF8-40D6-85A0-BDB3C281C247@dilger.ca> Message-ID: References: <1462229118-13123-1-git-send-email-agruenba@redhat.com> <551ED650-CBF8-40D6-85A0-BDB3C281C247@dilger.ca> User-Agent: Alpine 2.20 (LFD 67 2015-01-07) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160511_165402_027210_01281D7D X-CRM114-Status: GOOD ( 18.70 ) X-Spam-Score: -1.9 (-) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-8.3 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 While looking at porting lustre to use xattr handlers I noticed issues in generic_listxattr() when handle->list() is used. The function generic_listxattr() generates it results from the handle->name field. If the current handle name field is NULL then generic_listxattr() will call handle->list() if it exist. Calling handle->list() has no affect on the output since their is no way to set the name field of the handler. This patch allows the passing in of the handler to *list() so the handle->name field can be set. Now with the ability to create the name field after its contents are transfer to the passed in buffer the name field has to be freed to prevent memory leaks. Also freeing the memory of the name field ensures that the *list() function will be called at a latter time which ensures the xattr list is not stale. This patch is against Viro's work.xattrs branch. Signed-off-by: James Simmons --- fs/ext2/xattr.c | 2 +- fs/ext4/xattr.c | 2 +- fs/f2fs/xattr.c | 2 +- fs/reiserfs/xattr.c | 2 +- fs/squashfs/xattr.c | 2 +- fs/xattr.c | 8 ++++++-- include/linux/xattr.h | 2 +- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 1a5e3bf..0aab6a5 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -290,7 +290,7 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_list", const struct xattr_handler *handler = ext2_xattr_handler(entry->e_name_index); - if (handler && (!handler->list || handler->list(dentry))) { + if (handler && (!handler->list || handler->list(handler, dentry))) { const char *prefix = handler->prefix ?: handler->name; size_t prefix_len = strlen(prefix); size_t size = prefix_len + entry->e_name_len + 1; diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 0441e05..0941198 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -402,7 +402,7 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry, const struct xattr_handler *handler = ext4_xattr_handler(entry->e_name_index); - if (handler && (!handler->list || handler->list(dentry))) { + if (handler && (!handler->list || handler->list(handler, dentry))) { const char *prefix = handler->prefix ?: handler->name; size_t prefix_len = strlen(prefix); size_t size = prefix_len + entry->e_name_len + 1; diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 17fd2b1..0cb0fc1 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -412,7 +412,7 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) size_t prefix_len; size_t size; - if (!handler || (handler->list && !handler->list(dentry))) + if (!handler || (handler->list && !handler->list(handler, dentry))) continue; prefix = handler->prefix ?: handler->name; diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 02137bb..509d2a0 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -787,7 +787,7 @@ static int listxattr_filler(struct dir_context *ctx, const char *name, handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr, name); if (!handler /* Unsupported xattr name */ || - (handler->list && !handler->list(b->dentry))) + (handler->list && !handler->list(handler, b->dentry))) return 0; size = namelen + 1; if (b->buf) { diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c index 1548b37..64e8573 100644 --- a/fs/squashfs/xattr.c +++ b/fs/squashfs/xattr.c @@ -67,7 +67,7 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer, name_size = le16_to_cpu(entry.size); handler = squashfs_xattr_handler(le16_to_cpu(entry.type)); - if (handler && (!handler->list || handler->list(d))) { + if (handler && (!handler->list || handler->list(handler, d))) { const char *prefix = handler->prefix ?: handler->name; size_t prefix_size = strlen(prefix); diff --git a/fs/xattr.c b/fs/xattr.c index b11945e..1ec51a7 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -716,9 +716,11 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) if (!buffer) { for_each_xattr_handler(handlers, handler) { if (!handler->name || - (handler->list && !handler->list(dentry))) + (handler->list && !handler->list(handler, dentry))) continue; size += strlen(handler->name) + 1; + if (handler->list) + kfree(handler->name); } } else { char *buf = buffer; @@ -726,7 +728,7 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) for_each_xattr_handler(handlers, handler) { if (!handler->name || - (handler->list && !handler->list(dentry))) + (handler->list && !handler->list(handler, dentry))) continue; len = strlen(handler->name); if (len + 1 > buffer_size) @@ -734,6 +736,8 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) memcpy(buf, handler->name, len + 1); buf += len + 1; buffer_size -= len + 1; + if (handler->list) + kfree(handler->name); } size = buf - buffer; } diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 1cc4c57..e4fb463 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -28,7 +28,7 @@ struct xattr_handler { const char *name; const char *prefix; int flags; /* fs private flags */ - bool (*list)(struct dentry *dentry); + bool (*list)(const struct xattr_handler *, struct dentry *dentry); int (*get)(const struct xattr_handler *, struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size);