Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754309AbcKYJDe (ORCPT ); Fri, 25 Nov 2016 04:03:34 -0500 Received: from mx2.suse.de ([195.135.220.15]:45275 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752379AbcKYIbE (ORCPT ); Fri, 25 Nov 2016 03:31:04 -0500 X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" From: Jiri Slaby To: stable@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Richard Weinberger , Jiri Slaby Subject: [PATCH 3.12 016/127] ubifs: Abort readdir upon error Date: Fri, 25 Nov 2016 09:28:49 +0100 Message-Id: <3d4434afe9bbb8b75da9ca7bc10fa941e40dd23d.1480062521.git.jslaby@suse.cz> X-Mailer: git-send-email 2.10.2 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1988 Lines: 61 From: Richard Weinberger 3.12-stable review patch. If anyone has any objections, please let me know. =============== commit c83ed4c9dbb358b9e7707486e167e940d48bfeed upstream. If UBIFS is facing an error while walking a directory, it reports this error and ubifs_readdir() returns the error code. But the VFS readdir logic does not make the getdents system call fail in all cases. When the readdir cursor indicates that more entries are present, the system call will just return and the libc wrapper will try again since it also knows that more entries are present. This causes the libc wrapper to busy loop for ever when a directory is corrupted on UBIFS. A common approach do deal with corrupted directory entries is skipping them by setting the cursor to the next entry. On UBIFS this approach is not possible since we cannot compute the next directory entry cursor position without reading the current entry. So all we can do is setting the cursor to the "no more entries" position and make getdents exit. Signed-off-by: Richard Weinberger Signed-off-by: Jiri Slaby --- fs/ubifs/dir.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 9bd17a857667..0b1d1b046132 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -348,7 +348,7 @@ static unsigned int vfs_dent_type(uint8_t type) */ static int ubifs_readdir(struct file *file, struct dir_context *ctx) { - int err; + int err = 0; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; @@ -450,14 +450,12 @@ out: kfree(file->private_data); file->private_data = NULL; - if (err != -ENOENT) { + if (err != -ENOENT) ubifs_err("cannot find next direntry, error %d", err); - return err; - } /* 2 is a special value indicating that there are no more direntries */ ctx->pos = 2; - return 0; + return err; } /* Free saved readdir() state when the directory is closed */ -- 2.10.2