Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '6.18-rc3-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

- fix potential UAF in statfs

- DFS fix for expired referrals

- fix minor modinfo typo

- small improvement to reconnect for smbdirect

* tag '6.18-rc3-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
smb: client: call smbd_destroy() in the same splace as kernel_sock_shutdown()/sock_release()
smb: client: handle lack of IPC in dfs_cache_refresh()
smb: client: fix potential cfid UAF in smb2_query_info_compound
cifs: fix typo in enable_gcm_256 module parameter

+71 -37
+1 -1
fs/smb/client/cifsfs.c
··· 173 173 MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1"); 174 174 175 175 module_param(enable_gcm_256, bool, 0644); 176 - MODULE_PARM_DESC(enable_gcm_256, "Enable requesting strongest (256 bit) GCM encryption. Default: y/Y/0"); 176 + MODULE_PARM_DESC(enable_gcm_256, "Enable requesting strongest (256 bit) GCM encryption. Default: y/Y/1"); 177 177 178 178 module_param(require_gcm_256, bool, 0644); 179 179 MODULE_PARM_DESC(require_gcm_256, "Require strongest (256 bit) GCM encryption. Default: n/N/0");
+2
fs/smb/client/cifsproto.h
··· 616 616 extern struct TCP_Server_Info * 617 617 cifs_find_tcp_session(struct smb3_fs_context *ctx); 618 618 619 + struct cifs_tcon *cifs_setup_ipc(struct cifs_ses *ses, bool seal); 620 + 619 621 void __cifs_put_smb_ses(struct cifs_ses *ses); 620 622 621 623 extern struct cifs_ses *
+19 -27
fs/smb/client/connect.c
··· 310 310 server->ssocket->flags); 311 311 sock_release(server->ssocket); 312 312 server->ssocket = NULL; 313 + } else if (cifs_rdma_enabled(server)) { 314 + smbd_destroy(server); 313 315 } 314 316 server->sequence_number = 0; 315 317 server->session_estab = false; ··· 339 337 list_del_init(&mid->qhead); 340 338 mid_execute_callback(mid); 341 339 release_mid(mid); 342 - } 343 - 344 - if (cifs_rdma_enabled(server)) { 345 - cifs_server_lock(server); 346 - smbd_destroy(server); 347 - cifs_server_unlock(server); 348 340 } 349 341 } 350 342 ··· 2011 2015 /** 2012 2016 * cifs_setup_ipc - helper to setup the IPC tcon for the session 2013 2017 * @ses: smb session to issue the request on 2014 - * @ctx: the superblock configuration context to use for building the 2015 - * new tree connection for the IPC (interprocess communication RPC) 2018 + * @seal: if encryption is requested 2016 2019 * 2017 2020 * A new IPC connection is made and stored in the session 2018 2021 * tcon_ipc. The IPC tcon has the same lifetime as the session. 2019 2022 */ 2020 - static int 2021 - cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx) 2023 + struct cifs_tcon *cifs_setup_ipc(struct cifs_ses *ses, bool seal) 2022 2024 { 2023 2025 int rc = 0, xid; 2024 2026 struct cifs_tcon *tcon; 2025 2027 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0}; 2026 - bool seal = false; 2027 2028 struct TCP_Server_Info *server = ses->server; 2028 2029 2029 2030 /* 2030 2031 * If the mount request that resulted in the creation of the 2031 2032 * session requires encryption, force IPC to be encrypted too. 2032 2033 */ 2033 - if (ctx->seal) { 2034 - if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) 2035 - seal = true; 2036 - else { 2037 - cifs_server_dbg(VFS, 2038 - "IPC: server doesn't support encryption\n"); 2039 - return -EOPNOTSUPP; 2040 - } 2034 + if (seal && !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) { 2035 + cifs_server_dbg(VFS, "IPC: server doesn't support encryption\n"); 2036 + return ERR_PTR(-EOPNOTSUPP); 2041 2037 } 2042 2038 2043 2039 /* no need to setup directory caching on IPC share, so pass in false */ 2044 2040 tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc); 2045 2041 if (tcon == NULL) 2046 - return -ENOMEM; 2042 + return ERR_PTR(-ENOMEM); 2047 2043 2048 2044 spin_lock(&server->srv_lock); 2049 2045 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname); ··· 2045 2057 tcon->ses = ses; 2046 2058 tcon->ipc = true; 2047 2059 tcon->seal = seal; 2048 - rc = server->ops->tree_connect(xid, ses, unc, tcon, ctx->local_nls); 2060 + rc = server->ops->tree_connect(xid, ses, unc, tcon, ses->local_nls); 2049 2061 free_xid(xid); 2050 2062 2051 2063 if (rc) { 2052 - cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc); 2064 + cifs_server_dbg(VFS | ONCE, "failed to connect to IPC (rc=%d)\n", rc); 2053 2065 tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail); 2054 - goto out; 2066 + return ERR_PTR(rc); 2055 2067 } 2056 2068 2057 2069 cifs_dbg(FYI, "IPC tcon rc=%d ipc tid=0x%x\n", rc, tcon->tid); ··· 2059 2071 spin_lock(&tcon->tc_lock); 2060 2072 tcon->status = TID_GOOD; 2061 2073 spin_unlock(&tcon->tc_lock); 2062 - ses->tcon_ipc = tcon; 2063 - out: 2064 - return rc; 2074 + return tcon; 2065 2075 } 2066 2076 2067 2077 static struct cifs_ses * ··· 2333 2347 { 2334 2348 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; 2335 2349 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; 2350 + struct cifs_tcon *ipc; 2336 2351 struct cifs_ses *ses; 2337 2352 unsigned int xid; 2338 2353 int retries = 0; ··· 2512 2525 list_add(&ses->smb_ses_list, &server->smb_ses_list); 2513 2526 spin_unlock(&cifs_tcp_ses_lock); 2514 2527 2515 - cifs_setup_ipc(ses, ctx); 2528 + ipc = cifs_setup_ipc(ses, ctx->seal); 2529 + spin_lock(&cifs_tcp_ses_lock); 2530 + spin_lock(&ses->ses_lock); 2531 + ses->tcon_ipc = !IS_ERR(ipc) ? ipc : NULL; 2532 + spin_unlock(&ses->ses_lock); 2533 + spin_unlock(&cifs_tcp_ses_lock); 2516 2534 2517 2535 free_xid(xid); 2518 2536
+47 -8
fs/smb/client/dfs_cache.c
··· 1120 1120 return match; 1121 1121 } 1122 1122 1123 - static bool is_ses_good(struct cifs_ses *ses) 1123 + static bool is_ses_good(struct cifs_tcon *tcon, struct cifs_ses *ses) 1124 1124 { 1125 1125 struct TCP_Server_Info *server = ses->server; 1126 - struct cifs_tcon *tcon = ses->tcon_ipc; 1126 + struct cifs_tcon *ipc = NULL; 1127 1127 bool ret; 1128 1128 1129 + spin_lock(&cifs_tcp_ses_lock); 1129 1130 spin_lock(&ses->ses_lock); 1130 1131 spin_lock(&ses->chan_lock); 1132 + 1131 1133 ret = !cifs_chan_needs_reconnect(ses, server) && 1132 - ses->ses_status == SES_GOOD && 1133 - !tcon->need_reconnect; 1134 + ses->ses_status == SES_GOOD; 1135 + 1134 1136 spin_unlock(&ses->chan_lock); 1137 + 1138 + if (!ret) 1139 + goto out; 1140 + 1141 + if (likely(ses->tcon_ipc)) { 1142 + if (ses->tcon_ipc->need_reconnect) { 1143 + ret = false; 1144 + goto out; 1145 + } 1146 + } else { 1147 + spin_unlock(&ses->ses_lock); 1148 + spin_unlock(&cifs_tcp_ses_lock); 1149 + 1150 + ipc = cifs_setup_ipc(ses, tcon->seal); 1151 + 1152 + spin_lock(&cifs_tcp_ses_lock); 1153 + spin_lock(&ses->ses_lock); 1154 + if (!IS_ERR(ipc)) { 1155 + if (!ses->tcon_ipc) { 1156 + ses->tcon_ipc = ipc; 1157 + ipc = NULL; 1158 + } 1159 + } else { 1160 + ret = false; 1161 + ipc = NULL; 1162 + } 1163 + } 1164 + 1165 + out: 1135 1166 spin_unlock(&ses->ses_lock); 1167 + spin_unlock(&cifs_tcp_ses_lock); 1168 + if (ipc && server->ops->tree_disconnect) { 1169 + unsigned int xid = get_xid(); 1170 + 1171 + (void)server->ops->tree_disconnect(xid, ipc); 1172 + _free_xid(xid); 1173 + } 1174 + tconInfoFree(ipc, netfs_trace_tcon_ref_free_ipc); 1136 1175 return ret; 1137 1176 } 1138 1177 1139 1178 /* Refresh dfs referral of @ses */ 1140 - static void refresh_ses_referral(struct cifs_ses *ses) 1179 + static void refresh_ses_referral(struct cifs_tcon *tcon, struct cifs_ses *ses) 1141 1180 { 1142 1181 struct cache_entry *ce; 1143 1182 unsigned int xid; ··· 1192 1153 } 1193 1154 1194 1155 ses = CIFS_DFS_ROOT_SES(ses); 1195 - if (!is_ses_good(ses)) { 1156 + if (!is_ses_good(tcon, ses)) { 1196 1157 cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n", 1197 1158 __func__); 1198 1159 goto out; ··· 1280 1241 up_read(&htable_rw_lock); 1281 1242 1282 1243 ses = CIFS_DFS_ROOT_SES(ses); 1283 - if (!is_ses_good(ses)) { 1244 + if (!is_ses_good(tcon, ses)) { 1284 1245 cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n", 1285 1246 __func__); 1286 1247 goto out; ··· 1348 1309 tcon = container_of(work, struct cifs_tcon, dfs_cache_work.work); 1349 1310 1350 1311 list_for_each_entry(ses, &tcon->dfs_ses_list, dlist) 1351 - refresh_ses_referral(ses); 1312 + refresh_ses_referral(tcon, ses); 1352 1313 refresh_tcon_referral(tcon, false); 1353 1314 1354 1315 queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work,
+2 -1
fs/smb/client/smb2ops.c
··· 2799 2799 struct cifs_fid fid; 2800 2800 int rc; 2801 2801 __le16 *utf16_path; 2802 - struct cached_fid *cfid = NULL; 2802 + struct cached_fid *cfid; 2803 2803 int retries = 0, cur_sleep = 1; 2804 2804 2805 2805 replay_again: 2806 2806 /* reinitialize for possible replay */ 2807 + cfid = NULL; 2807 2808 flags = CIFS_CP_CREATE_CLOSE_OP; 2808 2809 oplock = SMB2_OPLOCK_LEVEL_NONE; 2809 2810 server = cifs_pick_channel(ses);