Commit 5aba1dc0 authored by Al Viro's avatar Al Viro Committed by Greg Kroah-Hartman

affs_lookup(): close a race with affs_remove_link()

commit 30da870c upstream.

we unlock the directory hash too early - if we are looking at secondary
link and primary (in another directory) gets removed just as we unlock,
we could have the old primary moved in place of the secondary, leaving
us to look into freed entry (and leaving our dentry with ->d_fsdata
pointing to a freed entry).

Cc: stable@vger.kernel.org # 2.4.4+
Acked-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 211922cf
...@@ -224,9 +224,10 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) ...@@ -224,9 +224,10 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
affs_lock_dir(dir); affs_lock_dir(dir);
bh = affs_find_entry(dir, dentry); bh = affs_find_entry(dir, dentry);
affs_unlock_dir(dir); if (IS_ERR(bh)) {
if (IS_ERR(bh)) affs_unlock_dir(dir);
return ERR_CAST(bh); return ERR_CAST(bh);
}
if (bh) { if (bh) {
u32 ino = bh->b_blocknr; u32 ino = bh->b_blocknr;
...@@ -240,10 +241,13 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) ...@@ -240,10 +241,13 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
} }
affs_brelse(bh); affs_brelse(bh);
inode = affs_iget(sb, ino); inode = affs_iget(sb, ino);
if (IS_ERR(inode)) if (IS_ERR(inode)) {
affs_unlock_dir(dir);
return ERR_CAST(inode); return ERR_CAST(inode);
}
} }
d_add(dentry, inode); d_add(dentry, inode);
affs_unlock_dir(dir);
return NULL; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment