Skip to contentSkip to conversation

Patch "lock_parent() needs to recheck if dentry got __dentry_kill'ed under it" has been added to the 4.4-stable tree

PATCH [email protected] 1 participant 1 message Mar 19, 2018

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

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

to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 3b821409632ab778d46e807516b457dfa72736ed Mon Sep 17 00:00:00 2001

From: Al Viro <[email protected]>
Date: Fri, 23 Feb 2018 20:47:17 -0500
Subject: lock_parent() needs to recheck if dentry got __dentry_kill'ed under it

From: Al Viro <[email protected]>

commit 3b821409632ab778d46e807516b457dfa72736ed 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 [email protected] # 3.12+, counting backports
---
 fs/dcache.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
fs/dcache.c +8 -3
@@ -634,11 +634,16 @@ again:
 		spin_unlock(&parent->d_lock);
 		goto again;
 	}
-	rcu_read_unlock();
-	if (parent != dentry)
+	if (parent != dentry) {
 		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
-	else
+		if (unlikely(dentry->d_lockref.count < 0)) {
+			spin_unlock(&parent->d_lock);
+			parent = NULL;
+		}
+	} else {
 		parent = NULL;
+	}
+	rcu_read_unlock();
 	return parent;
 }
 

Patches currently in stable-queue which might be from [email protected] are

queue-4.4/fs-teach-path_connected-to-handle-nfs-filesystems-with-multiple-roots.patch queue-4.4/lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch