aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-13 21:36:19 -0500
committerNick Piggin <npiggin@hera.kernel.org>2011-01-13 21:36:19 -0500
commit90dbb77ba48dddb87445d238e84cd137cf97dd98 (patch)
tree446772602e5944075a6c614db05dd06681f3f3d8 /fs/namei.c
parentbb20c18db6fbb5e6ba499c76473a487d35073467 (diff)
fs: fix dropping of rcu-walk from force_reval_path
As J. R. Okajima noted, force_reval_path passes in the same dentry to d_revalidate as the one in the nameidata structure (other callers pass in a child), so the locking breaks. This can oops with a chrooted nfs mount, for example. Similarly there can be other problems with revalidating a dentry which is already in nameidata of the path walk. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 0f02359ce685..14c73edca9ce 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -479,6 +479,14 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry
479 struct fs_struct *fs = current->fs; 479 struct fs_struct *fs = current->fs;
480 struct dentry *parent = nd->path.dentry; 480 struct dentry *parent = nd->path.dentry;
481 481
482 /*
483 * It can be possible to revalidate the dentry that we started
484 * the path walk with. force_reval_path may also revalidate the
485 * dentry already committed to the nameidata.
486 */
487 if (unlikely(parent == dentry))
488 return nameidata_drop_rcu(nd);
489
482 BUG_ON(!(nd->flags & LOOKUP_RCU)); 490 BUG_ON(!(nd->flags & LOOKUP_RCU));
483 if (nd->root.mnt) { 491 if (nd->root.mnt) {
484 spin_lock(&fs->lock); 492 spin_lock(&fs->lock);