From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Eduard Zateev <hackerowskiy@gmail.com>,
syzbot+5c3ed2a0de3270efc921@syzkaller.appspotmail.com,
syzbot+c2ec61adfbcb24e5ec20@syzkaller.appspotmail.com,
Michail Andreas Michalopoulos <mike.michalo@gmail.com>,
Paulo Alcantara <pc@manguebit.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.18.y 2/2] smb: client: hold server info until cifsd exits
Date: Wed, 4 Nov 2026 21:36:34 -0500 [thread overview]
Message-ID: <20261105023627.1203080-2-sashal@kernel.org> (raw)
In-Reply-To: <20261105023627.1203080-1-sashal@kernel.org>
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>
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 8d751026dd4a2..d529446e4984b 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>
@@ -678,6 +679,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 fa7c2f70b6ed3..0a60c411aba67 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -1059,6 +1059,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)
{
@@ -1144,14 +1157,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
@@ -1730,7 +1740,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);
@@ -1738,15 +1748,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 *
@@ -1768,6 +1774,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) {
@@ -1906,6 +1913,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
prev parent reply other threads:[~2026-11-05 2:36 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 14:34 FAILED: patch "[PATCH] smb: client: hold server info until cifsd exits" failed to apply to 6.18-stable tree gregkh
2026-11-05 2:36 ` [PATCH 6.18.y 1/2] smb: client: Avoid leaking sensitive data to the heap in connect.c Sasha Levin
2026-11-05 2:36 ` Sasha Levin [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261105023627.1203080-2-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=hackerowskiy@gmail.com \
--cc=mike.michalo@gmail.com \
--cc=pc@manguebit.org \
--cc=stable@vger.kernel.org \
--cc=syzbot+5c3ed2a0de3270efc921@syzkaller.appspotmail.com \
--cc=syzbot+c2ec61adfbcb24e5ec20@syzkaller.appspotmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.