Skip to contentSkip to conversation

FAILED: patch "[PATCH] configfs: unhash the dentry before dropping the item in rmdir" failed to apply to 6.1-stable tree

PATCH New [email protected] 2 participants 2 messages Sep 16

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x f06c2d26d1999d37e93299db0ecead04ca7d0b9f
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091658-data-urchin-e973@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From f06c2d26d1999d37e93299db0ecead04ca7d0b9f Mon Sep 17 00:00:00 2001
From: Vasileios Almpanis <[email protected]>
Date: Thu, 30 Jul 2026 11:30:25 +0200
Subject: [PATCH] configfs: unhash the dentry before dropping the item in rmdir

configfs_get_config_item() treats a hashed dentry as proof that sd->s_element is a live config_item. configfs_rmdir() breaks that:
simple_rmdir() leaves the dentry hashed, the last reference to the item is dropped right after, and the dentry is only unhashed by d_delete() once ->rmdir() has returned. configfs_symlink() resolves its target holding no lock on it, so get_target() can land in that window:

  BUG: KASAN: slab-use-after-free in config_item_get+0x26/0x90
   get_target fs/configfs/symlink.c:128 [inline]
   configfs_symlink+0x4ab/0x1030 fs/configfs/symlink.c:185

Unhash in configfs_remove_dir(), while the item is still guaranteed to be there. A reference obtained just before that stays harmless, as create_link() rechecks CONFIGFS_USET_DROPPING, already set by configfs_detach_prep(). Both configfs_unregister_subsystem() paths d_drop() after detaching, so this only makes rmdir match them.

fs/configfs/dir.c +9 -0
index 3c88f13f1ca2..eda80c2a2d38 100644
@@ -416,6 +416,15 @@ static void configfs_remove_dir(struct dentry *d)
 	if (d_really_is_positive(d)) {
 		if (unlikely(simple_rmdir(d_inode(parent), d)))
 			pr_warn("remove_dir (%pd): attributes remain", d);
+		else
+			/*
+			 * configfs_get_config_item() takes a hashed dentry as
+			 * proof that ->s_element is still alive.  Our caller
+			 * is about to drop the last reference to the item and
+			 * the VFS will not unhash until after we return, so
+			 * unhash it here.
+			 */
+			d_drop(d);
 	}
 
 	pr_debug(" o %pd removing done (%d)\n", d, d_count(d));
maintainer
#1 lore raw

PATCH 1/1 configfs: unhash the dentry before dropping the item in rmdir

From: Vasileios Almpanis <[email protected]>

[ Upstream commit f06c2d26d1999d37e93299db0ecead04ca7d0b9f ]

configfs_get_config_item() treats a hashed dentry as proof that sd->s_element is a live config_item. configfs_rmdir() breaks that:
simple_rmdir() leaves the dentry hashed, the last reference to the item is dropped right after, and the dentry is only unhashed by d_delete() once ->rmdir() has returned. configfs_symlink() resolves its target holding no lock on it, so get_target() can land in that window:

  BUG: KASAN: slab-use-after-free in config_item_get+0x26/0x90
   get_target fs/configfs/symlink.c:128 [inline]
   configfs_symlink+0x4ab/0x1030 fs/configfs/symlink.c:185

Unhash in configfs_remove_dir(), while the item is still guaranteed to be there. A reference obtained just before that stays harmless, as create_link() rechecks CONFIGFS_USET_DROPPING, already set by configfs_detach_prep(). Both configfs_unregister_subsystem() paths d_drop() after detaching, so this only makes rmdir match them.

Reported-by [email protected]
Fixes 7063fbf22611 ("[PATCH] configfs: User-driven configuration filesystem")
[ adapted the configfs_remove_dir() change to the older remove_dir() helper. ]
---
 fs/configfs/dir.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
fs/configfs/dir.c +11 -2
index 01c9d54833b30..6269085ba1748 100644
@@ -395,8 +395,17 @@ static void remove_dir(struct dentry * d)
 
 	configfs_remove_dirent(d);
 
-	if (d_really_is_positive(d))
-		simple_rmdir(d_inode(parent),d);
+	if (d_really_is_positive(d)) {
+		if (!simple_rmdir(d_inode(parent), d))
+			/*
+			 * configfs_get_config_item() takes a hashed dentry as
+			 * proof that ->s_element is still alive.  Our caller
+			 * is about to drop the last reference to the item and
+			 * the VFS will not unhash until after we return, so
+			 * unhash it here.
+			 */
+			d_drop(d);
+	}
 
 	pr_debug(" o %pd removing done (%d)\n", d, d_count(d));
 
Signature · 1 line
2.53.0