[PATCH] configfs: fix lockdep false positive in configfs_depend_item()

Yun Zhou posted 1 patch 2 months ago
fs/configfs/dir.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
[PATCH] configfs: fix lockdep false positive in configfs_depend_item()
Posted by Yun Zhou 2 months ago
configfs_depend_item() and configfs_depend_item_unlocked() acquire the
configfs root inode lock to prevent subsystem unregistration while
establishing a dependency. When called from a configfs mkdir callback
(which holds a parent directory inode lock), lockdep reports a circular
dependency because both locks share the same lock class
(sb->s_type->i_mutex_key).

In practice, the cross-subsystem depend path is only triggered when the
caller and target belong to different subsystems. In such cases, the
mkdir parent directory is always a subdirectory beneath a subsystem root,
never the configfs root itself. Therefore no real deadlock can occur.

Use inode_lock_nested() with I_MUTEX_PARENT2 to tell lockdep that
this is a different nesting level than the parent lock held by VFS.

Fixes: d79d75b5c518 ("fs: configfs: Add unlocked version of configfs_depend_item()")
Reported-by: syzbot+c9f9d646b08f3b6032fe@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=c9f9d646b08f3b6032fe
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
---
 fs/configfs/dir.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 3c88f13f1ca2..2b05af6fe335 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1161,7 +1161,7 @@ int configfs_depend_item(struct configfs_subsystem *subsys,
 	 * subsystem is really registered, and so we need to lock out
 	 * configfs_[un]register_subsystem().
 	 */
-	inode_lock(d_inode(root));
+	inode_lock_nested(d_inode(root), I_MUTEX_PARENT2);
 
 	subsys_sd = configfs_find_subsys_dentry(root->d_fsdata, s_item);
 	if (!subsys_sd) {
@@ -1256,7 +1256,8 @@ int configfs_depend_item_unlocked(struct configfs_subsystem *caller_subsys,
 		 * additional locking to prevent other subsystem from being
 		 * unregistered
 		 */
-		inode_lock(d_inode(root->cg_item.ci_dentry));
+		inode_lock_nested(d_inode(root->cg_item.ci_dentry),
+				  I_MUTEX_PARENT2);
 
 		/*
 		 * As we are trying to depend item from other subsystem
-- 
2.43.0