[patch 23/25] vfs: fix lookup on deleted directory

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Greg KH
Date: Monday, August 4, 2008 - 2:30 pm

2.6.26-stable review patch.  If anyone has any objections, please let us
know.

------------------

From: Miklos Szeredi <mszeredi@suse.cz>

commit d70b67c8bc72ee23b55381bd6a884f4796692f77 upstream

Lookup can install a child dentry for a deleted directory.  This keeps
the directory dentry alive, and the inode pinned in the cache and on
disk, even after all external references have gone away.

This isn't a big problem normally, since memory pressure or umount
will clear out the directory dentry and its children, releasing the
inode.  But for UBIFS this causes problems because its orphan area can
overflow.

Fix this by returning ENOENT for all lookups on a S_DEAD directory
before creating a child dentry.

Thanks to Zoltan Sogor for noticing this while testing UBIFS, and
Artem for the excellent analysis of the problem and testing.

Reported-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Tested-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 fs/namei.c |   19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -519,7 +519,14 @@ static struct dentry * real_lookup(struc
 	 */
 	result = d_lookup(parent, name);
 	if (!result) {
-		struct dentry * dentry = d_alloc(parent, name);
+		struct dentry *dentry;
+
+		/* Don't create child dentry for a dead directory. */
+		result = ERR_PTR(-ENOENT);
+		if (IS_DEADDIR(dir))
+			goto out_unlock;
+
+		dentry = d_alloc(parent, name);
 		result = ERR_PTR(-ENOMEM);
 		if (dentry) {
 			result = dir->i_op->lookup(dir, dentry, nd);
@@ -528,6 +535,7 @@ static struct dentry * real_lookup(struc
 			else
 				result = dentry;
 		}
+out_unlock:
 		mutex_unlock(&dir->i_mutex);
 		return result;
 	}
@@ -1317,7 +1325,14 @@ static struct dentry *__lookup_hash(stru
 
 	dentry = cached_lookup(base, name, nd);
 	if (!dentry) {
-		struct dentry *new = d_alloc(base, name);
+		struct dentry *new;
+
+		/* Don't create child dentry for a dead directory. */
+		dentry = ERR_PTR(-ENOENT);
+		if (IS_DEADDIR(inode))
+			goto out;
+
+		new = d_alloc(base, name);
 		dentry = ERR_PTR(-ENOMEM);
 		if (!new)
 			goto out;

-- 
--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[patch 00/25] 2.6.26-stable review, Greg KH, (Mon Aug 4, 2:27 pm)
[patch 07/25] Close race in md_probe, Greg KH, (Mon Aug 4, 2:29 pm)
[patch 11/25] SCSI: ch: fix ch_remove oops, Greg KH, (Mon Aug 4, 2:30 pm)
[patch 23/25] vfs: fix lookup on deleted directory, Greg KH, (Mon Aug 4, 2:30 pm)
[patch 24/25] Ath5k: fix memory corruption, Greg KH, (Mon Aug 4, 2:30 pm)
[patch 25/25] Ath5k: kill tasklets on shutdown, Greg KH, (Mon Aug 4, 2:30 pm)
Re: [patch 01/25] ftrace: remove unneeded documentation, Steven Rostedt, (Mon Aug 4, 2:42 pm)
Re: [patch 01/25] ftrace: remove unneeded documentation, Steven Rostedt, (Mon Aug 4, 3:02 pm)
Re: [patch 01/25] ftrace: remove unneeded documentation, Steven Rostedt, (Mon Aug 4, 3:16 pm)