[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aYXvLwb5PQ0jgwGg@stanley.mountain>
Date: Fri, 6 Feb 2026 16:39:59 +0300
From: Dan Carpenter <dan.carpenter@...aro.org>
To: Shyam Prasad N <sprasad@...rosoft.com>
Cc: Paulo Alcantara <pc@...guebit.org>,
Ronnie Sahlberg <ronniesahlberg@...il.com>,
Shyam Prasad N <sprasad@...rosoft.com>, Tom Talpey <tom@...pey.com>,
Bharath SM <bharathsm@...rosoft.com>, linux-cifs@...r.kernel.org,
samba-technical@...ts.samba.org,
linux-kernel <linux-kernel@...r.kernel.org>
Subject: [bug report] cifs: Fix locking usage for tcon fields
[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/aTaiGSbWZ9DJaGo7@stanley.mountain/ -dan ]
Hello Shyam Prasad N,
Commit 91c866a6abb0 ("cifs: Fix locking usage for tcon fields") from
Feb 1, 2026 (linux-next), leads to the following Smatch static
checker warning:
fs/smb/client/smb2ops.c:3179 smb2_get_dfs_refer()
error: dereferencing freed memory 'tcon' (line 3178)
fs/smb/client/smb2ops.c
3079 static int
3080 smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
3081 const char *search_name,
3082 struct dfs_info3_param **target_nodes,
3083 unsigned int *num_of_nodes,
3084 const struct nls_table *nls_codepage, int remap)
3085 {
3086 int rc;
3087 __le16 *utf16_path = NULL;
3088 int utf16_path_len = 0;
3089 struct cifs_tcon *tcon;
3090 struct fsctl_get_dfs_referral_req *dfs_req = NULL;
3091 struct get_dfs_referral_rsp *dfs_rsp = NULL;
3092 u32 dfs_req_size = 0, dfs_rsp_size = 0;
3093 int retry_once = 0;
3094
3095 cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name);
3096
3097 /*
3098 * Try to use the IPC tcon, otherwise just use any
3099 */
3100 tcon = ses->tcon_ipc;
3101 if (tcon == NULL) {
3102 spin_lock(&cifs_tcp_ses_lock);
3103 tcon = list_first_entry_or_null(&ses->tcon_list,
3104 struct cifs_tcon,
3105 tcon_list);
3106 if (tcon) {
3107 spin_lock(&tcon->tc_lock);
3108 tcon->tc_count++;
3109 spin_unlock(&tcon->tc_lock);
3110 trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
3111 netfs_trace_tcon_ref_get_dfs_refer);
3112 }
3113 spin_unlock(&cifs_tcp_ses_lock);
3114 }
3115
3116 if (tcon == NULL) {
3117 cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
3118 ses);
3119 rc = -ENOTCONN;
3120 goto out;
3121 }
3122
3123 utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
3124 &utf16_path_len,
3125 nls_codepage, remap);
3126 if (!utf16_path) {
3127 rc = -ENOMEM;
3128 goto out;
3129 }
3130
3131 dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
3132 dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
3133 if (!dfs_req) {
3134 rc = -ENOMEM;
3135 goto out;
3136 }
3137
3138 /* Highest DFS referral version understood */
3139 dfs_req->MaxReferralLevel = DFS_VERSION;
3140
3141 /* Path to resolve in an UTF-16 null-terminated string */
3142 memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
3143
3144 for (;;) {
3145 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
3146 FSCTL_DFS_GET_REFERRALS,
3147 (char *)dfs_req, dfs_req_size, CIFSMaxBufSize,
3148 (char **)&dfs_rsp, &dfs_rsp_size);
3149 if (fatal_signal_pending(current)) {
3150 rc = -EINTR;
3151 break;
3152 }
3153 if (!is_retryable_error(rc) || retry_once++)
3154 break;
3155 usleep_range(512, 2048);
3156 }
3157
3158 if (!rc && !dfs_rsp)
3159 rc = smb_EIO(smb_eio_trace_dfsref_no_rsp);
3160 if (rc) {
3161 if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP)
3162 cifs_tcon_dbg(FYI, "%s: ioctl error: rc=%d\n", __func__, rc);
3163 goto out;
3164 }
3165
3166 rc = parse_dfs_referrals(dfs_rsp, dfs_rsp_size,
3167 num_of_nodes, target_nodes,
3168 nls_codepage, remap, search_name,
3169 true /* is_unicode */);
3170 if (rc && rc != -ENOENT) {
3171 cifs_tcon_dbg(VFS, "%s: failed to parse DFS referral %s: %d\n",
3172 __func__, search_name, rc);
3173 }
3174
3175 out:
3176 if (tcon && !tcon->ipc) {
3177 /* ipc tcons are not refcounted */
3178 cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_dfs_refer);
^^^^
This free
--> 3179 trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
needs to happen after these dereferences.
3180 netfs_trace_tcon_ref_dec_dfs_refer);
3181 }
3182 kfree(utf16_path);
3183 kfree(dfs_req);
3184 kfree(dfs_rsp);
3185 return rc;
3186 }
regards,
dan carpenter
Powered by blists - more mailing lists