smb client fixes

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmgC/bEACgkQiiy9cAdy
 T1Fhtwv/THJBLHY7HVZAdhVGbWOi/zQ+hKpIyglDJ8bcoxU+UA0qRMFcrrL/2qMd
 4dGwtlQBgWEV2Ixb2q1j9gAcg0Q7n2jtp6+1iBB3re/SA5ykyLzC+REcBSo7GnXQ
 OL+FPEfo1/JS8W955ZTgzpA/k18btI0b1IIgx5409SiPt5pcmxwodar7CQUrT3gU
 LWDApQbRG+/HR24MPSBY4q5Xx5CWGEYlpy2Sra44VFtig31YrPaGO372qPwzu3k+
 NBeQ5IWe64ema6fhmHK70oSz+ZUih0llr5oVlGFn8IGrhG3HryY0KD4ORRzVubmq
 XXwFI2+sDNTlTwu7kwXLw/GKKV2UBPCDemsEBm3MPFiKi/TKOObgE0HK4y4mXySI
 Lv1iIUcCkxD/MYuMPED3ntI6akV60KdFMZWxaBiV29FjJPT9pxryViMsDwMhgTaS
 xOKV0IbrnmldrRo7GGTTOn+54QuRijyFgxxF1rs2lANAoC2hi4AtlgFeg6912Haa
 mDofaZL4
 =92E5
 -----END PGP SIGNATURE-----

Merge tag '6.15-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - Fix hard link lease key problem when close is deferred

 - Revert the socket lockdep/refcount workarounds done in cifs.ko now
   that it is fixed at the socket layer

* tag '6.15-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  Revert "smb: client: fix TCP timers deadlock after rmmod"
  Revert "smb: client: Fix netns refcount imbalance causing leaks and use-after-free"
  smb3 client: fix open hardlink on deferred close file error
This commit is contained in:
Linus Torvalds 2025-04-18 20:10:42 -07:00
commit 8560697b23
3 changed files with 39 additions and 25 deletions

View File

@ -163,6 +163,8 @@ extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
struct cifsFileInfo **ret_file);
extern int cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode,
struct file *file);
extern unsigned int smbCalcSize(void *buf);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
struct TCP_Server_Info *server);

View File

@ -300,7 +300,6 @@ cifs_abort_connection(struct TCP_Server_Info *server)
server->ssocket->flags);
sock_release(server->ssocket);
server->ssocket = NULL;
put_net(cifs_net_ns(server));
}
server->sequence_number = 0;
server->session_estab = false;
@ -1074,13 +1073,9 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
msleep(125);
if (cifs_rdma_enabled(server))
smbd_destroy(server);
if (server->ssocket) {
sock_release(server->ssocket);
server->ssocket = NULL;
/* Release netns reference for the socket. */
put_net(cifs_net_ns(server));
}
if (!list_empty(&server->pending_mid_q)) {
@ -1128,7 +1123,6 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
*/
}
/* Release netns reference for this server. */
put_net(cifs_net_ns(server));
kfree(server->leaf_fullpath);
kfree(server->hostname);
@ -1774,8 +1768,6 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
tcp_ses->ops = ctx->ops;
tcp_ses->vals = ctx->vals;
/* Grab netns reference for this server. */
cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
tcp_ses->sign = ctx->sign;
@ -1903,7 +1895,6 @@ smbd_connected:
out_err_crypto_release:
cifs_crypto_secmech_release(tcp_ses);
/* Release netns reference for this server. */
put_net(cifs_net_ns(tcp_ses));
out_err:
@ -1912,10 +1903,8 @@ out_err:
cifs_put_tcp_session(tcp_ses->primary_server, false);
kfree(tcp_ses->hostname);
kfree(tcp_ses->leaf_fullpath);
if (tcp_ses->ssocket) {
if (tcp_ses->ssocket)
sock_release(tcp_ses->ssocket);
put_net(cifs_net_ns(tcp_ses));
}
kfree(tcp_ses);
}
return ERR_PTR(rc);
@ -3359,24 +3348,20 @@ generic_ip_connect(struct TCP_Server_Info *server)
socket = server->ssocket;
} else {
struct net *net = cifs_net_ns(server);
struct sock *sk;
rc = sock_create_kern(net, sfamily, SOCK_STREAM, IPPROTO_TCP, &server->ssocket);
rc = __sock_create(net, sfamily, SOCK_STREAM,
IPPROTO_TCP, &server->ssocket, 1);
if (rc < 0) {
cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
return rc;
}
/*
* Grab netns reference for the socket.
*
* This reference will be released in several situations:
* - In the failure path before the cifsd thread is started.
* - In the all place where server->socket is released, it is
* also set to NULL.
* - Ultimately in clean_demultiplex_info(), during the final
* teardown.
*/
get_net(net);
sk = server->ssocket->sk;
__netns_tracker_free(net, &sk->ns_tracker, false);
sk->sk_net_refcnt = 1;
get_net_track(net, &sk->ns_tracker, GFP_KERNEL);
sock_inuse_add(net, 1);
/* BB other socket options to set KEEPALIVE, NODELAY? */
cifs_dbg(FYI, "Socket created\n");
@ -3428,7 +3413,6 @@ generic_ip_connect(struct TCP_Server_Info *server)
if (rc < 0) {
cifs_dbg(FYI, "Error %d connecting to server\n", rc);
trace_smb3_connect_err(server->hostname, server->conn_id, &server->dstaddr, rc);
put_net(cifs_net_ns(server));
sock_release(socket);
server->ssocket = NULL;
return rc;

View File

@ -1007,6 +1007,11 @@ int cifs_open(struct inode *inode, struct file *file)
} else {
_cifsFileInfo_put(cfile, true, false);
}
} else {
/* hard link on the defeered close file */
rc = cifs_get_hardlink_path(tcon, inode, file);
if (rc)
cifs_close_deferred_file(CIFS_I(inode));
}
if (server->oplocks)
@ -2071,6 +2076,29 @@ cifs_move_llist(struct list_head *source, struct list_head *dest)
list_move(li, dest);
}
int
cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode,
struct file *file)
{
struct cifsFileInfo *open_file = NULL;
struct cifsInodeInfo *cinode = CIFS_I(inode);
int rc = 0;
spin_lock(&tcon->open_file_lock);
spin_lock(&cinode->open_file_lock);
list_for_each_entry(open_file, &cinode->openFileList, flist) {
if (file->f_flags == open_file->f_flags) {
rc = -EINVAL;
break;
}
}
spin_unlock(&cinode->open_file_lock);
spin_unlock(&tcon->open_file_lock);
return rc;
}
void
cifs_free_llist(struct list_head *llist)
{