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

lock_parent() needs to recheck if dentry got __dentry_kill'ed under it

commit 3b821409 upstream.

In case when dentry passed to lock_parent() is protected from freeing only
by the fact that it's on a shrink list and trylock of parent fails, we
could get hit by __dentry_kill() (and subsequent dentry_kill(parent))
between unlocking dentry and locking presumed parent.  We need to recheck
that dentry is alive once we lock both it and parent *and* postpone
rcu_read_unlock() until after that point.  Otherwise we could return
a pointer to struct dentry that already is rcu-scheduled for freeing, with
->d_lock held on it; caller's subsequent attempt to unlock it can end
up with memory corruption.

Cc: # 3.12+, counting backports
Signed-off-by: default avatarAl Viro <>
Signed-off-by: default avatarGreg Kroah-Hartman <>
parent e693f133
......@@ -644,11 +644,16 @@ static inline struct dentry *lock_parent(struct dentry *dentry)
goto again;
if (parent != dentry)
if (parent != dentry) {
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
if (unlikely(dentry->d_lockref.count < 0)) {
parent = NULL;
} else {
parent = NULL;
return parent;
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment