* [PATCH 5.15 780/843] cifs: Add tracing for the cifs_tcon struct refcounting
[not found] <20260721152405.946368001@linuxfoundation.org>
@ 2026-07-21 15:26 ` Greg Kroah-Hartman
2026-07-21 15:27 ` [PATCH 5.15 786/843] ksmbd: fix mechToken leak when SPNEGO decode fails after token alloc Greg Kroah-Hartman
1 sibling, 0 replies; 2+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-21 15:26 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells,
Paulo Alcantara (Red Hat), Shyam Prasad N, linux-cifs,
linux-fsdevel, Steve French, Sasha Levin
5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit afc23febd51c7e24361e3a9c09f3e892eb0a41ea ]
Add tracing for the refcounting/lifecycle of the cifs_tcon struct, marking
different events with different labels and giving each tcon its own debug
ID so that the tracelines corresponding to individual tcons can be
distinguished. This can be enabled with:
echo 1 >/sys/kernel/debug/tracing/events/cifs/smb3_tcon_ref/enable
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
cc: Shyam Prasad N <nspmangalore@gmail.com>
cc: linux-cifs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>
Stable-dep-of: ec457f9afe5a ("smb: client: resolve SWN tcon from live registrations")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/cifs/cifs_swn.c | 13 +++---
fs/cifs/cifsfs.c | 2 +
fs/cifs/cifsglob.h | 1
fs/cifs/cifsproto.h | 9 +---
fs/cifs/connect.c | 21 ++++++----
fs/cifs/dfs_cache.c | 2 -
fs/cifs/misc.c | 10 +++--
fs/cifs/smb2misc.c | 10 +++--
fs/cifs/smb2ops.c | 7 +++
fs/cifs/smb2pdu.c | 4 +-
fs/cifs/smb2transport.c | 2 +
fs/cifs/trace.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++--
12 files changed, 141 insertions(+), 33 deletions(-)
--- a/fs/cifs/cifs_swn.c
+++ b/fs/cifs/cifs_swn.c
@@ -313,17 +313,15 @@ static struct cifs_swn_reg *cifs_get_swn
reg = cifs_find_swn_reg(tcon);
if (!IS_ERR(reg)) {
kref_get(®->ref_count);
- mutex_unlock(&cifs_swnreg_idr_mutex);
- return reg;
+ goto unlock;
} else if (PTR_ERR(reg) != -EEXIST) {
- mutex_unlock(&cifs_swnreg_idr_mutex);
- return reg;
+ goto unlock;
}
reg = kmalloc(sizeof(struct cifs_swn_reg), GFP_ATOMIC);
if (reg == NULL) {
- mutex_unlock(&cifs_swnreg_idr_mutex);
- return ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
+ goto fail_unlock;
}
kref_init(®->ref_count);
@@ -354,7 +352,7 @@ static struct cifs_swn_reg *cifs_get_swn
reg->ip_notify = (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT);
reg->tcon = tcon;
-
+unlock:
mutex_unlock(&cifs_swnreg_idr_mutex);
return reg;
@@ -365,6 +363,7 @@ fail_idr:
idr_remove(&cifs_swnreg_idr, reg->id);
fail:
kfree(reg);
+fail_unlock:
mutex_unlock(&cifs_swnreg_idr_mutex);
return ERR_PTR(ret);
}
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -705,6 +705,8 @@ static void cifs_umount_begin(struct sup
tcon = cifs_sb_master_tcon(cifs_sb);
spin_lock(&cifs_tcp_ses_lock);
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_see_umount);
if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
/* we have other mounts to same share or we have
already tried to force umount this and woken up
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1025,6 +1025,7 @@ struct cached_fid {
*/
struct cifs_tcon {
struct list_head tcon_list;
+ int debug_id; /* Debugging for tracing */
int tc_count;
struct list_head rlist; /* reconnect list */
atomic_t num_local_opens; /* num of all opens including disconnected */
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -273,7 +273,7 @@ extern void cifs_close_deferred_file_und
extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx);
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
int from_reconnect);
-extern void cifs_put_tcon(struct cifs_tcon *tcon);
+extern void cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
extern void cifs_dfs_release_automount_timer(void);
@@ -489,8 +489,8 @@ extern int CIFSSMBLogoff(const unsigned
extern struct cifs_ses *sesInfoAlloc(void);
extern void sesInfoFree(struct cifs_ses *);
-extern struct cifs_tcon *tconInfoAlloc(void);
-extern void tconInfoFree(struct cifs_tcon *);
+extern struct cifs_tcon *tconInfoAlloc(enum smb3_tcon_ref_trace trace);
+extern void tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
__u32 *pexpected_response_sequence_number);
@@ -634,9 +634,6 @@ static inline int cifs_create_options(st
return options;
}
-struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
-void cifs_put_tcon_super(struct super_block *sb);
-
static inline void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
{
kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1663,7 +1663,7 @@ cifs_setup_ipc(struct cifs_ses *ses, str
}
}
- tcon = tconInfoAlloc();
+ tcon = tconInfoAlloc(netfs_trace_tcon_ref_new_ipc);
if (tcon == NULL)
return -ENOMEM;
@@ -1678,7 +1678,7 @@ cifs_setup_ipc(struct cifs_ses *ses, str
if (rc) {
cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
- tconInfoFree(tcon);
+ tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail);
goto out;
}
@@ -1709,7 +1709,7 @@ cifs_free_ipc(struct cifs_ses *ses)
if (tcon == NULL)
return 0;
- tconInfoFree(tcon);
+ tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc);
ses->tcon_ipc = NULL;
return 0;
}
@@ -2114,6 +2114,8 @@ cifs_find_tcon(struct cifs_ses *ses, str
if (!match_tcon(tcon, ctx))
continue;
++tcon->tc_count;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_get_find);
spin_unlock(&cifs_tcp_ses_lock);
return tcon;
}
@@ -2122,7 +2124,7 @@ cifs_find_tcon(struct cifs_ses *ses, str
}
void
-cifs_put_tcon(struct cifs_tcon *tcon)
+cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
{
unsigned int xid;
struct cifs_ses *ses;
@@ -2137,6 +2139,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
ses = tcon->ses;
cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
spin_lock(&cifs_tcp_ses_lock);
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count - 1, trace);
if (--tcon->tc_count > 0) {
spin_unlock(&cifs_tcp_ses_lock);
return;
@@ -2164,7 +2167,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
_free_xid(xid);
cifs_fscache_release_super_cookie(tcon);
- tconInfoFree(tcon);
+ tconInfoFree(tcon, netfs_trace_tcon_ref_free);
cifs_put_smb_ses(ses);
}
@@ -2212,7 +2215,7 @@ cifs_get_tcon(struct cifs_ses *ses, stru
goto out_fail;
}
- tcon = tconInfoAlloc();
+ tcon = tconInfoAlloc(netfs_trace_tcon_ref_new);
if (tcon == NULL) {
rc = -ENOMEM;
goto out_fail;
@@ -2388,7 +2391,7 @@ cifs_get_tcon(struct cifs_ses *ses, stru
return tcon;
out_fail:
- tconInfoFree(tcon);
+ tconInfoFree(tcon, netfs_trace_tcon_ref_free_fail);
return ERR_PTR(rc);
}
@@ -2405,7 +2408,7 @@ cifs_put_tlink(struct tcon_link *tlink)
}
if (!IS_ERR(tlink_tcon(tlink)))
- cifs_put_tcon(tlink_tcon(tlink));
+ cifs_put_tcon(tlink_tcon(tlink), netfs_trace_tcon_ref_put_tlink);
kfree(tlink);
return;
}
@@ -2959,7 +2962,7 @@ static inline void mount_put_conns(struc
int rc = 0;
if (mnt_ctx->tcon)
- cifs_put_tcon(mnt_ctx->tcon);
+ cifs_put_tcon(mnt_ctx->tcon, netfs_trace_tcon_ref_put_mnt_ctx);
else if (mnt_ctx->ses)
cifs_put_smb_ses(mnt_ctx->ses);
else if (mnt_ctx->server)
--- a/fs/cifs/dfs_cache.c
+++ b/fs/cifs/dfs_cache.c
@@ -1544,7 +1544,7 @@ static void refresh_mounts(struct cifs_s
mutex_unlock(&server->refpath_lock);
__refresh_tcon(server->origin_fullpath + 1, sessions, tcon, false);
- cifs_put_tcon(tcon);
+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_dfs_refer);
}
}
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -101,9 +101,10 @@ sesInfoFree(struct cifs_ses *buf_to_free
}
struct cifs_tcon *
-tconInfoAlloc(void)
+tconInfoAlloc(enum smb3_tcon_ref_trace trace)
{
struct cifs_tcon *ret_buf;
+ static atomic_t tcon_debug_id;
ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
if (!ret_buf)
@@ -116,7 +117,8 @@ tconInfoAlloc(void)
atomic_inc(&tconInfoAllocCount);
ret_buf->tidStatus = CifsNew;
- ++ret_buf->tc_count;
+ ret_buf->debug_id = atomic_inc_return(&tcon_debug_id);
+ ret_buf->tc_count = 1;
INIT_LIST_HEAD(&ret_buf->openFileList);
INIT_LIST_HEAD(&ret_buf->tcon_list);
spin_lock_init(&ret_buf->open_file_lock);
@@ -124,17 +126,19 @@ tconInfoAlloc(void)
spin_lock_init(&ret_buf->stat_lock);
atomic_set(&ret_buf->num_local_opens, 0);
atomic_set(&ret_buf->num_remote_opens, 0);
+ trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace);
return ret_buf;
}
void
-tconInfoFree(struct cifs_tcon *buf_to_free)
+tconInfoFree(struct cifs_tcon *buf_to_free, enum smb3_tcon_ref_trace trace)
{
if (buf_to_free == NULL) {
cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
return;
}
+ trace_smb3_tcon_ref(buf_to_free->debug_id, buf_to_free->tc_count, trace);
atomic_dec(&tconInfoAllocCount);
kfree(buf_to_free->nativeFileSystem);
kfree_sensitive(buf_to_free->password);
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -773,7 +773,7 @@ smb2_cancelled_close_fid(struct work_str
if (rc)
cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc);
- cifs_put_tcon(tcon);
+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close_fid);
kfree(cancelled);
}
@@ -817,6 +817,8 @@ smb2_handle_cancelled_close(struct cifs_
if (tcon->tc_count <= 0) {
struct TCP_Server_Info *server = NULL;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_see_cancelled_close);
WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
spin_unlock(&cifs_tcp_ses_lock);
@@ -830,12 +832,14 @@ smb2_handle_cancelled_close(struct cifs_
return 0;
}
tcon->tc_count++;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_get_cancelled_close);
spin_unlock(&cifs_tcp_ses_lock);
rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
persistent_fid, volatile_fid);
if (rc)
- cifs_put_tcon(tcon);
+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close);
return rc;
}
@@ -863,7 +867,7 @@ smb2_handle_cancelled_mid(struct mid_q_e
rsp->PersistentFileId,
rsp->VolatileFileId);
if (rc)
- cifs_put_tcon(tcon);
+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_mid);
return rc;
}
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -2895,8 +2895,11 @@ smb2_get_dfs_refer(const unsigned int xi
tcon = list_first_entry_or_null(&ses->tcon_list,
struct cifs_tcon,
tcon_list);
- if (tcon)
+ if (tcon) {
tcon->tc_count++;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_get_dfs_refer);
+ }
spin_unlock(&cifs_tcp_ses_lock);
}
@@ -2960,6 +2963,8 @@ smb2_get_dfs_refer(const unsigned int xi
/* ipc tcons are not refcounted */
spin_lock(&cifs_tcp_ses_lock);
tcon->tc_count--;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_dec_dfs_refer);
/* tc_count can never go negative */
WARN_ON(tcon->tc_count < 0);
spin_unlock(&cifs_tcp_ses_lock);
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -3769,6 +3769,8 @@ void smb2_reconnect_server(struct work_s
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
if (tcon->need_reconnect || tcon->need_reopen_files) {
tcon->tc_count++;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_get_reconnect_server);
list_add_tail(&tcon->rlist, &tmp_list);
tcon_exist = true;
}
@@ -3802,7 +3804,7 @@ void smb2_reconnect_server(struct work_s
if (tcon->ipc)
cifs_put_smb_ses(tcon->ses);
else
- cifs_put_tcon(tcon);
+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_reconnect_server);
}
cifs_dbg(FYI, "Reconnecting tcons finished\n");
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -168,6 +168,8 @@ smb2_find_smb_sess_tcon_unlocked(struct
if (tcon->tid != tid)
continue;
++tcon->tc_count;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_get_find_sess_tcon);
return tcon;
}
--- a/fs/cifs/trace.h
+++ b/fs/cifs/trace.h
@@ -3,6 +3,9 @@
* Copyright (C) 2018, Microsoft Corporation.
*
* Author(s): Steve French <stfrench@microsoft.com>
+ *
+ * Please use this 3-part article as a reference for writing new tracepoints:
+ * https://lwn.net/Articles/379903/
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM cifs
@@ -13,9 +16,71 @@
#include <linux/tracepoint.h>
/*
- * Please use this 3-part article as a reference for writing new tracepoints:
- * https://lwn.net/Articles/379903/
+ * Specify enums for tracing information.
+ */
+#define smb3_tcon_ref_traces \
+ EM(netfs_trace_tcon_ref_dec_dfs_refer, "DEC DfsRef") \
+ EM(netfs_trace_tcon_ref_free, "FRE ") \
+ EM(netfs_trace_tcon_ref_free_fail, "FRE Fail ") \
+ EM(netfs_trace_tcon_ref_free_ipc, "FRE Ipc ") \
+ EM(netfs_trace_tcon_ref_free_ipc_fail, "FRE Ipc-F ") \
+ EM(netfs_trace_tcon_ref_free_reconnect_server, "FRE Reconn") \
+ EM(netfs_trace_tcon_ref_get_cancelled_close, "GET Cn-Cls") \
+ EM(netfs_trace_tcon_ref_get_dfs_refer, "GET DfsRef") \
+ EM(netfs_trace_tcon_ref_get_find, "GET Find ") \
+ EM(netfs_trace_tcon_ref_get_find_sess_tcon, "GET FndSes") \
+ EM(netfs_trace_tcon_ref_get_reconnect_server, "GET Reconn") \
+ EM(netfs_trace_tcon_ref_new, "NEW ") \
+ EM(netfs_trace_tcon_ref_new_ipc, "NEW Ipc ") \
+ EM(netfs_trace_tcon_ref_new_reconnect_server, "NEW Reconn") \
+ EM(netfs_trace_tcon_ref_put_cancelled_close, "PUT Cn-Cls") \
+ EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \
+ EM(netfs_trace_tcon_ref_put_cancelled_mid, "PUT Cn-Mid") \
+ EM(netfs_trace_tcon_ref_put_mnt_ctx, "PUT MntCtx") \
+ EM(netfs_trace_tcon_ref_put_dfs_refer, "PUT DfsRfr") \
+ EM(netfs_trace_tcon_ref_put_reconnect_server, "PUT Reconn") \
+ EM(netfs_trace_tcon_ref_put_tlink, "PUT Tlink ") \
+ EM(netfs_trace_tcon_ref_see_cancelled_close, "SEE Cn-Cls") \
+ EM(netfs_trace_tcon_ref_see_fscache_collision, "SEE FV-CO!") \
+ EM(netfs_trace_tcon_ref_see_fscache_okay, "SEE FV-Ok ") \
+ EM(netfs_trace_tcon_ref_see_fscache_relinq, "SEE FV-Rlq") \
+ E_(netfs_trace_tcon_ref_see_umount, "SEE Umount")
+
+#undef EM
+#undef E_
+
+/*
+ * Define those tracing enums.
*/
+#ifndef __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY
+#define __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY
+
+#define EM(a, b) a,
+#define E_(a, b) a
+
+enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte);
+
+#undef EM
+#undef E_
+#endif
+
+/*
+ * Export enum symbols via userspace.
+ */
+#define EM(a, b) TRACE_DEFINE_ENUM(a);
+#define E_(a, b) TRACE_DEFINE_ENUM(a);
+
+smb3_tcon_ref_traces;
+
+#undef EM
+#undef E_
+
+/*
+ * Now redefine the EM() and E_() macros to map the enums to the strings that
+ * will be printed in the output.
+ */
+#define EM(a, b) { a, b },
+#define E_(a, b) { a, b }
/* For logging errors in read or write */
DECLARE_EVENT_CLASS(smb3_rw_err_class,
@@ -937,6 +1002,30 @@ DEFINE_SMB3_CREDIT_EVENT(too_many_credit
DEFINE_SMB3_CREDIT_EVENT(add_credits);
DEFINE_SMB3_CREDIT_EVENT(set_credits);
+
+TRACE_EVENT(smb3_tcon_ref,
+ TP_PROTO(unsigned int tcon_debug_id, int ref,
+ enum smb3_tcon_ref_trace trace),
+ TP_ARGS(tcon_debug_id, ref, trace),
+ TP_STRUCT__entry(
+ __field(unsigned int, tcon)
+ __field(int, ref)
+ __field(enum smb3_tcon_ref_trace, trace)
+ ),
+ TP_fast_assign(
+ __entry->tcon = tcon_debug_id;
+ __entry->ref = ref;
+ __entry->trace = trace;
+ ),
+ TP_printk("TC=%08x %s r=%u",
+ __entry->tcon,
+ __print_symbolic(__entry->trace, smb3_tcon_ref_traces),
+ __entry->ref)
+ );
+
+
+#undef EM
+#undef E_
#endif /* _CIFS_TRACE_H */
#undef TRACE_INCLUDE_PATH
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH 5.15 786/843] ksmbd: fix mechToken leak when SPNEGO decode fails after token alloc
[not found] <20260721152405.946368001@linuxfoundation.org>
2026-07-21 15:26 ` [PATCH 5.15 780/843] cifs: Add tracing for the cifs_tcon struct refcounting Greg Kroah-Hartman
@ 2026-07-21 15:27 ` Greg Kroah-Hartman
1 sibling, 0 replies; 2+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-21 15:27 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Namjae Jeon, Steve French,
Sergey Senozhatsky, Tom Talpey, linux-cifs, stable, Steve French,
Sasha Levin
5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ Upstream commit ad0057fb91218914d6c98268718ceb9d59b388e1 ]
The kernel ASN.1 BER decoder calls action callbacks incrementally as it
walks the input. When ksmbd_decode_negTokenInit() reaches the mechToken
[2] OCTET STRING element, ksmbd_neg_token_alloc() allocates
conn->mechToken immediately via kmemdup_nul(). If a later element in
the same blob is malformed, then the decoder will return nonzero after
the allocation is already live. This could happen if mechListMIC [3]
overrunse the enclosing SEQUENCE.
decode_negotiation_token() then sets conn->use_spnego = false because
both the negTokenInit and negTokenTarg grammars failed. The cleanup at
the bottom of smb2_sess_setup() is gated on use_spnego:
if (conn->use_spnego && conn->mechToken) {
kfree(conn->mechToken);
conn->mechToken = NULL;
}
so the kfree is skipped, causing the mechToken to never be freed.
This codepath is reachable pre-authentication, so untrusted clients can
cause slow memory leaks on a server without even being properly
authenticated.
Fix this up by not checking check for use_spnego, as it's not required,
so the memory will always be properly freed. At the same time, always
free the memory in ksmbd_conn_free() incase some other failure path
forgot to free it.
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: Steve French <smfrench@gmail.com>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Tom Talpey <tom@talpey.com>
Cc: linux-cifs@vger.kernel.org
Cc: <stable@kernel.org>
Assisted-by: gregkh_clanker_t1000
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Stable-dep-of: c1016dd1d8b2 ("ksmbd: track the connection owning a byte-range lock")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ksmbd/connection.c | 1 +
fs/ksmbd/smb2pdu.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -39,6 +39,7 @@ void ksmbd_conn_free(struct ksmbd_conn *
xa_destroy(&conn->sessions);
kvfree(conn->request_buf);
kfree(conn->preauth_info);
+ kfree(conn->mechToken);
kfree(conn);
}
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -1920,7 +1920,7 @@ out_err:
else if (rc)
rsp->hdr.Status = STATUS_LOGON_FAILURE;
- if (conn->use_spnego && conn->mechToken) {
+ if (conn->mechToken) {
kfree(conn->mechToken);
conn->mechToken = NULL;
}
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-21 22:27 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260721152405.946368001@linuxfoundation.org>
2026-07-21 15:26 ` [PATCH 5.15 780/843] cifs: Add tracing for the cifs_tcon struct refcounting Greg Kroah-Hartman
2026-07-21 15:27 ` [PATCH 5.15 786/843] ksmbd: fix mechToken leak when SPNEGO decode fails after token alloc Greg Kroah-Hartman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox