aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ubifs
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2016-10-19 06:43:07 -0400
committerRichard Weinberger <richard@nod.at>2016-10-19 18:06:11 -0400
commitc83ed4c9dbb358b9e7707486e167e940d48bfeed (patch)
tree89f1cd092e2b89f71407cdf784d3e5b7c95d1f68 /fs/ubifs
parent884a3b647809cb31cf6bd948f814e93753b38502 (diff)
ubifs: Abort readdir upon error
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. Cc: stable@vger.kernel.org Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'fs/ubifs')
-rw-r--r--fs/ubifs/dir.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 668ec3b90ea1..bd4a5e8ce441 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -439,7 +439,7 @@ static unsigned int vfs_dent_type(uint8_t type)
439 */ 439 */
440static int ubifs_readdir(struct file *file, struct dir_context *ctx) 440static int ubifs_readdir(struct file *file, struct dir_context *ctx)
441{ 441{
442 int err; 442 int err = 0;
443 struct qstr nm; 443 struct qstr nm;
444 union ubifs_key key; 444 union ubifs_key key;
445 struct ubifs_dent_node *dent; 445 struct ubifs_dent_node *dent;
@@ -541,14 +541,12 @@ out:
541 kfree(file->private_data); 541 kfree(file->private_data);
542 file->private_data = NULL; 542 file->private_data = NULL;
543 543
544 if (err != -ENOENT) { 544 if (err != -ENOENT)
545 ubifs_err(c, "cannot find next direntry, error %d", err); 545 ubifs_err(c, "cannot find next direntry, error %d", err);
546 return err;
547 }
548 546
549 /* 2 is a special value indicating that there are no more direntries */ 547 /* 2 is a special value indicating that there are no more direntries */
550 ctx->pos = 2; 548 ctx->pos = 2;
551 return 0; 549 return err;
552} 550}
553 551
554/* Free saved readdir() state when the directory is closed */ 552/* Free saved readdir() state when the directory is closed */