* FAILED: patch "[PATCH] smb: client: hold server info until cifsd exits" failed to apply to 6.12-stable tree
@ 2026-11-04 14:34 gregkh
2026-11-05 3:01 ` [PATCH 6.12.y] smb: client: hold server info until cifsd exits Sasha Levin
0 siblings, 1 reply; 2+ messages in thread
From: gregkh @ 2026-11-04 14:34 UTC (permalink / raw)
To: hackerowskiy, mike.michalo, pc; +Cc: stable
The patch below does not apply to the 6.12-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 <stable@vger.kernel.org>.
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.12.y
git checkout FETCH_HEAD
git cherry-pick -x 482c117c6dbeee382790168af10959810450ab09
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026110420-crunching-excess-eb90@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 482c117c6dbeee382790168af10959810450ab09 Mon Sep 17 00:00:00 2001
From: Eduard Zateev <hackerowskiy@gmail.com>
Date: Tue, 20 Oct 2026 21:45:45 +0200
Subject: [PATCH] smb: client: hold server info until cifsd exits
The last session reference can be dropped while the cifsd demultiplex
thread is still running clean_demultiplex_info(). That thread frees
TCP_Server_Info there, racing with cifs_put_tcp_session() as it releases
the server crypto state. syzbot reported a KASAN use-after-free in
cifs_crypto_secmech_release().
Keep an object reference for the cifsd thread. Defer final crypto,
session-key, network namespace, string, and structure cleanup until both
the last session reference and the thread reference are dropped. Drop the
thread reference after clean_demultiplex_info() has finished using the
server.
Build-tested with ARCH=arm64 and W=1 for
fs/smb/client/connect.o. The KASAN reproducer was not run on the patched
kernel.
Fixes: a5c3e1c725af ("Revert "cifs: No need to send SIGKILL to demux_thread during umount"")
Reported-by: syzbot+5c3ed2a0de3270efc921@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=5c3ed2a0de3270efc921
Reported-by: syzbot+c2ec61adfbcb24e5ec20@syzkaller.appspotmail.com
Closes: https://syzbot.org/bug?extid=c2ec61adfbcb24e5ec20
Assisted-by: LLM OpenAI Codex
Signed-off-by: Eduard Zateev <hackerowskiy@gmail.com>
Cc: stable@vger.kernel.org
Tested-by: Michail Andreas Michalopoulos <mike.michalo@gmail.com>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 73b49dcb5215..d3ca688b6aba 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -16,6 +16,7 @@
#include <linux/scatterlist.h>
#include <linux/mm.h>
#include <linux/mempool.h>
+#include <linux/refcount.h>
#include <linux/workqueue.h>
#include <linux/utsname.h>
#include <linux/sched/mm.h>
@@ -681,6 +682,7 @@ struct TCP_Server_Info {
spinlock_t srv_lock; /* protect anything here that is not protected */
__u64 conn_id; /* connection identifier (useful for debugging) */
int srv_count; /* reference counter */
+ refcount_t obj_refs; /* struct lifetime: srv_count users + cifsd */
int rfc1001_sessinit; /* whether to estasblish netbios session */
bool with_rfc1001; /* if netbios session is used */
/* 15 character server name + 0x20 16th byte indicating type = srv */
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index c3614c077746..e68fffb2ab2e 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -1083,6 +1083,19 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
return 0;
}
+static void cifs_tcp_server_put(struct TCP_Server_Info *server)
+{
+ if (!refcount_dec_and_test(&server->obj_refs))
+ return;
+
+ cifs_crypto_secmech_release(server);
+ kfree_sensitive(server->session_key.response);
+ put_net(cifs_net_ns(server));
+ kfree(server->leaf_fullpath);
+ kfree(server->hostname);
+ kfree_sensitive(server);
+}
+
static noinline_for_stack void
clean_demultiplex_info(struct TCP_Server_Info *server)
{
@@ -1168,14 +1181,11 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
*/
}
- put_net(cifs_net_ns(server));
- kfree(server->leaf_fullpath);
- kfree(server->hostname);
- kfree_sensitive(server);
-
length = atomic_dec_return(&tcpSesAllocCount);
if (length > 0)
mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
+
+ cifs_tcp_server_put(server);
}
static int
@@ -1751,7 +1761,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
else
cancel_delayed_work_sync(&server->reconnect);
- /* For secondary channels, we pick up ref-count on the primary server */
+ /* For secondary channels, drop the reference on the primary server */
if (SERVER_IS_CHAN(server))
cifs_put_tcp_session(server->primary_server, from_reconnect);
@@ -1759,15 +1769,11 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
server->tcpStatus = CifsExiting;
spin_unlock(&server->srv_lock);
- cifs_crypto_secmech_release(server);
-
- kfree_sensitive(server->session_key.response);
- server->session_key.response = NULL;
- server->session_key.len = 0;
-
task = xchg(&server->tsk, NULL);
if (task)
send_sig(SIGKILL, task, 1);
+
+ cifs_tcp_server_put(server);
}
struct TCP_Server_Info *
@@ -1789,6 +1795,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
rc = -ENOMEM;
goto out_err;
}
+ refcount_set(&tcp_ses->obj_refs, 1);
tcp_ses->hostname = kstrdup(ctx->server_hostname, GFP_KERNEL);
if (!tcp_ses->hostname) {
@@ -1927,6 +1934,8 @@ smbd_connected:
module_put(THIS_MODULE);
goto out_err_crypto_release;
}
+ /* Keep the server alive until the demultiplex thread has exited */
+ refcount_inc(&tcp_ses->obj_refs);
/* thread created, put it on the list */
spin_lock(&cifs_tcp_ses_lock);
list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
^ permalink raw reply related [flat|nested] 2+ messages in thread* [PATCH 6.12.y] smb: client: hold server info until cifsd exits
2026-11-04 14:34 FAILED: patch "[PATCH] smb: client: hold server info until cifsd exits" failed to apply to 6.12-stable tree gregkh
@ 2026-11-05 3:01 ` Sasha Levin
0 siblings, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2026-11-05 3:01 UTC (permalink / raw)
To: stable
Cc: Eduard Zateev, syzbot+5c3ed2a0de3270efc921,
syzbot+c2ec61adfbcb24e5ec20, Michail Andreas Michalopoulos,
Paulo Alcantara, Sasha Levin
From: Eduard Zateev <hackerowskiy@gmail.com>
[ Upstream commit 482c117c6dbeee382790168af10959810450ab09 ]
The last session reference can be dropped while the cifsd demultiplex
thread is still running clean_demultiplex_info(). That thread frees
TCP_Server_Info there, racing with cifs_put_tcp_session() as it releases
the server crypto state. syzbot reported a KASAN use-after-free in
cifs_crypto_secmech_release().
Keep an object reference for the cifsd thread. Defer final crypto,
session-key, network namespace, string, and structure cleanup until both
the last session reference and the thread reference are dropped. Drop the
thread reference after clean_demultiplex_info() has finished using the
server.
Build-tested with ARCH=arm64 and W=1 for
fs/smb/client/connect.o. The KASAN reproducer was not run on the patched
kernel.
Fixes: a5c3e1c725af ("Revert "cifs: No need to send SIGKILL to demux_thread during umount"")
Reported-by: syzbot+5c3ed2a0de3270efc921@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=5c3ed2a0de3270efc921
Reported-by: syzbot+c2ec61adfbcb24e5ec20@syzkaller.appspotmail.com
Closes: https://syzbot.org/bug?extid=c2ec61adfbcb24e5ec20
Assisted-by: LLM OpenAI Codex
Signed-off-by: Eduard Zateev <hackerowskiy@gmail.com>
Cc: stable@vger.kernel.org
Tested-by: Michail Andreas Michalopoulos <mike.michalo@gmail.com>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
[ sashal: Adjusted patch context for missing NetBIOS fields and existing kfree() cleanup instead of kfree_sensitive(). ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/client/cifsglob.h | 2 ++
fs/smb/client/connect.c | 33 +++++++++++++++++++++------------
2 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index f5ca2cd653e95..8ffc8b2ab6db4 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -16,6 +16,7 @@
#include <linux/scatterlist.h>
#include <linux/mm.h>
#include <linux/mempool.h>
+#include <linux/refcount.h>
#include <linux/workqueue.h>
#include <linux/utsname.h>
#include <linux/sched/mm.h>
@@ -647,6 +648,7 @@ struct TCP_Server_Info {
spinlock_t srv_lock; /* protect anything here that is not protected */
__u64 conn_id; /* connection identifier (useful for debugging) */
int srv_count; /* reference counter */
+ refcount_t obj_refs; /* struct lifetime: srv_count users + cifsd */
/* 15 character server name + 0x20 16th byte indicating type = srv */
char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
struct smb_version_operations *ops;
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index 81961a54c9f1c..225bcd149a32f 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -977,6 +977,19 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
return 0;
}
+static void cifs_tcp_server_put(struct TCP_Server_Info *server)
+{
+ if (!refcount_dec_and_test(&server->obj_refs))
+ return;
+
+ cifs_crypto_secmech_release(server);
+ kfree_sensitive(server->session_key.response);
+ put_net(cifs_net_ns(server));
+ kfree(server->leaf_fullpath);
+ kfree(server->hostname);
+ kfree_sensitive(server);
+}
+
static noinline_for_stack void
clean_demultiplex_info(struct TCP_Server_Info *server)
{
@@ -1062,14 +1075,11 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
*/
}
- put_net(cifs_net_ns(server));
- kfree(server->leaf_fullpath);
- kfree(server->hostname);
- kfree(server);
-
length = atomic_dec_return(&tcpSesAllocCount);
if (length > 0)
mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
+
+ cifs_tcp_server_put(server);
}
static int
@@ -1678,7 +1688,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
else
cancel_delayed_work_sync(&server->reconnect);
- /* For secondary channels, we pick up ref-count on the primary server */
+ /* For secondary channels, drop the reference on the primary server */
if (SERVER_IS_CHAN(server))
cifs_put_tcp_session(server->primary_server, from_reconnect);
@@ -1686,15 +1696,11 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
server->tcpStatus = CifsExiting;
spin_unlock(&server->srv_lock);
- cifs_crypto_secmech_release(server);
-
- kfree_sensitive(server->session_key.response);
- server->session_key.response = NULL;
- server->session_key.len = 0;
-
task = xchg(&server->tsk, NULL);
if (task)
send_sig(SIGKILL, task, 1);
+
+ cifs_tcp_server_put(server);
}
struct TCP_Server_Info *
@@ -1716,6 +1722,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
rc = -ENOMEM;
goto out_err;
}
+ refcount_set(&tcp_ses->obj_refs, 1);
tcp_ses->hostname = kstrdup(ctx->server_hostname, GFP_KERNEL);
if (!tcp_ses->hostname) {
@@ -1856,6 +1863,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
module_put(THIS_MODULE);
goto out_err_crypto_release;
}
+ /* Keep the server alive until the demultiplex thread has exited */
+ refcount_inc(&tcp_ses->obj_refs);
/* thread created, put it on the list */
spin_lock(&cifs_tcp_ses_lock);
list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-05 3:01 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04 14:34 FAILED: patch "[PATCH] smb: client: hold server info until cifsd exits" failed to apply to 6.12-stable tree gregkh
2026-11-05 3:01 ` [PATCH 6.12.y] smb: client: hold server info until cifsd exits Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox