Skip to contentSkip to conversation

FAILED: patch "[PATCH] smb: client: pin DFS superblock in iterator callback" failed to apply to 5.10-stable tree

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

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 5.10-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-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x d806d5a85dcbe2a0f181b2f0f9f61ddfbefa1818
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091644-blouse-acre-e296@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

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

From d806d5a85dcbe2a0f181b2f0f9f61ddfbefa1818 Mon Sep 17 00:00:00 2001
From: Karl Mehltretter <[email protected]>
Date: Wed, 2 Sep 2026 20:28:14 +0200
Subject: [PATCH] smb: client: pin DFS superblock in iterator callback

tcon_super_cb() stores a raw superblock pointer, but __cifs_get_super() takes its active reference only after iterate_supers_type() has dropped s_umount and its passive reference. Concurrent DFS automount expiry can therefore free the superblock before cifs_sb_active() uses it.

A deterministic KASAN test reproduces the race as:

  BUG: KASAN: slab-use-after-free in cifs_sb_active+0x77/0x80

The same test passes with this change applied.

Take the active reference in the callback while iterate_supers_type() still holds s_umount shared. cifs_put_tcp_super() remains the matching release.

Fixes bacd704a95ad ("cifs: handle prefix paths in reconnect")
Assisted-by LLM
fs/smb/client/misc.c +8 -9
index 46e1382e8e04..d4db3f91a91f 100644
@@ -891,8 +891,14 @@ static void tcon_super_cb(struct super_block *sb, void *arg)
 	     t1->ses->dfs_root_ses == t2->ses->dfs_root_ses) &&
 	    t1->ses->server == t2->ses->server &&
 	    t2->origin_fullpath &&
-	    dfs_src_pathname_equal(t2->origin_fullpath, t1->origin_fullpath))
+	    dfs_src_pathname_equal(t2->origin_fullpath, t1->origin_fullpath)) {
+		/*
+		 * Take the active reference while iterate_supers_type() still
+		 * holds s_umount shared.
+		 */
+		cifs_sb_active(sb);
 		sd->sb = sb;
+	}
 	spin_unlock(&t2->tc_lock);
 }
 
@@ -909,15 +915,8 @@ static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void
 
 	for (; *fs_type; fs_type++) {
 		iterate_supers_type(*fs_type, f, &sd);
-		if (sd.sb) {
-			/*
-			 * Grab an active reference in order to prevent automounts (DFS links)
-			 * of expiring and then freeing up our cifs superblock pointer while
-			 * we're doing failover.
-			 */
-			cifs_sb_active(sd.sb);
+		if (sd.sb)
 			return sd.sb;
-		}
 	}
 	pr_warn_once("%s: could not find dfs superblock\n", __func__);
 	return ERR_PTR(-EINVAL);
maintainer
#1 lore raw

PATCH 1/1 smb: client: pin DFS superblock in iterator callback

From: Karl Mehltretter <[email protected]>

[ Upstream commit d806d5a85dcbe2a0f181b2f0f9f61ddfbefa1818 ]

tcon_super_cb() stores a raw superblock pointer, but __cifs_get_super() takes its active reference only after iterate_supers_type() has dropped s_umount and its passive reference. Concurrent DFS automount expiry can therefore free the superblock before cifs_sb_active() uses it.

A deterministic KASAN test reproduces the race as:

  BUG: KASAN: slab-use-after-free in cifs_sb_active+0x77/0x80

The same test passes with this change applied.

Take the active reference in the callback while iterate_supers_type() still holds s_umount shared. cifs_put_tcp_super() remains the matching release.

Fixes bacd704a95ad ("cifs: handle prefix paths in reconnect")
Assisted-by LLM
[ Adapted tcon_super_cb() changes to the older tcp_super_cb() callback and its server-only matching logic. ]
---
 fs/cifs/misc.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)
fs/cifs/misc.c +8 -9
index b4199b4085db3..d6542b073add4 100644
@@ -1054,8 +1054,14 @@ static void tcp_super_cb(struct super_block *sb, void *arg)
 
 	cifs_sb = CIFS_SB(sb);
 	tcon = cifs_sb_master_tcon(cifs_sb);
-	if (tcon->ses->server == server)
+	if (tcon->ses->server == server) {
+		/*
+		 * Take the active reference while iterate_supers_type() still
+		 * holds s_umount shared.
+		 */
+		cifs_sb_active(sb);
 		sd->sb = sb;
+	}
 }
 
 static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *),
@@ -1071,15 +1077,8 @@ static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void
 
 	for (; *fs_type; fs_type++) {
 		iterate_supers_type(*fs_type, f, &sd);
-		if (sd.sb) {
-			/*
-			 * Grab an active reference in order to prevent automounts (DFS links)
-			 * of expiring and then freeing up our cifs superblock pointer while
-			 * we're doing failover.
-			 */
-			cifs_sb_active(sd.sb);
+		if (sd.sb)
 			return sd.sb;
-		}
 	}
 	return ERR_PTR(-EINVAL);
 }
Signature · 1 line
2.53.0