Skip to content

Commit 8560697

Browse files
committed
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
2 parents 3088d26 + 95d2b9f commit 8560697

File tree

3 files changed

+39
-25
lines changed

3 files changed

+39
-25
lines changed

fs/smb/client/cifsproto.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
163163
extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
164164
extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
165165
struct cifsFileInfo **ret_file);
166+
extern int cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode,
167+
struct file *file);
166168
extern unsigned int smbCalcSize(void *buf);
167169
extern int decode_negTokenInit(unsigned char *security_blob, int length,
168170
struct TCP_Server_Info *server);

fs/smb/client/connect.c

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ cifs_abort_connection(struct TCP_Server_Info *server)
300300
server->ssocket->flags);
301301
sock_release(server->ssocket);
302302
server->ssocket = NULL;
303-
put_net(cifs_net_ns(server));
304303
}
305304
server->sequence_number = 0;
306305
server->session_estab = false;
@@ -1074,13 +1073,9 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
10741073
msleep(125);
10751074
if (cifs_rdma_enabled(server))
10761075
smbd_destroy(server);
1077-
10781076
if (server->ssocket) {
10791077
sock_release(server->ssocket);
10801078
server->ssocket = NULL;
1081-
1082-
/* Release netns reference for the socket. */
1083-
put_net(cifs_net_ns(server));
10841079
}
10851080

10861081
if (!list_empty(&server->pending_mid_q)) {
@@ -1128,7 +1123,6 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
11281123
*/
11291124
}
11301125

1131-
/* Release netns reference for this server. */
11321126
put_net(cifs_net_ns(server));
11331127
kfree(server->leaf_fullpath);
11341128
kfree(server->hostname);
@@ -1774,8 +1768,6 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
17741768

17751769
tcp_ses->ops = ctx->ops;
17761770
tcp_ses->vals = ctx->vals;
1777-
1778-
/* Grab netns reference for this server. */
17791771
cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
17801772

17811773
tcp_ses->sign = ctx->sign;
@@ -1903,7 +1895,6 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
19031895
out_err_crypto_release:
19041896
cifs_crypto_secmech_release(tcp_ses);
19051897

1906-
/* Release netns reference for this server. */
19071898
put_net(cifs_net_ns(tcp_ses));
19081899

19091900
out_err:
@@ -1912,10 +1903,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
19121903
cifs_put_tcp_session(tcp_ses->primary_server, false);
19131904
kfree(tcp_ses->hostname);
19141905
kfree(tcp_ses->leaf_fullpath);
1915-
if (tcp_ses->ssocket) {
1906+
if (tcp_ses->ssocket)
19161907
sock_release(tcp_ses->ssocket);
1917-
put_net(cifs_net_ns(tcp_ses));
1918-
}
19191908
kfree(tcp_ses);
19201909
}
19211910
return ERR_PTR(rc);
@@ -3359,24 +3348,20 @@ generic_ip_connect(struct TCP_Server_Info *server)
33593348
socket = server->ssocket;
33603349
} else {
33613350
struct net *net = cifs_net_ns(server);
3351+
struct sock *sk;
33623352

3363-
rc = sock_create_kern(net, sfamily, SOCK_STREAM, IPPROTO_TCP, &server->ssocket);
3353+
rc = __sock_create(net, sfamily, SOCK_STREAM,
3354+
IPPROTO_TCP, &server->ssocket, 1);
33643355
if (rc < 0) {
33653356
cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
33663357
return rc;
33673358
}
33683359

3369-
/*
3370-
* Grab netns reference for the socket.
3371-
*
3372-
* This reference will be released in several situations:
3373-
* - In the failure path before the cifsd thread is started.
3374-
* - In the all place where server->socket is released, it is
3375-
* also set to NULL.
3376-
* - Ultimately in clean_demultiplex_info(), during the final
3377-
* teardown.
3378-
*/
3379-
get_net(net);
3360+
sk = server->ssocket->sk;
3361+
__netns_tracker_free(net, &sk->ns_tracker, false);
3362+
sk->sk_net_refcnt = 1;
3363+
get_net_track(net, &sk->ns_tracker, GFP_KERNEL);
3364+
sock_inuse_add(net, 1);
33803365

33813366
/* BB other socket options to set KEEPALIVE, NODELAY? */
33823367
cifs_dbg(FYI, "Socket created\n");
@@ -3428,7 +3413,6 @@ generic_ip_connect(struct TCP_Server_Info *server)
34283413
if (rc < 0) {
34293414
cifs_dbg(FYI, "Error %d connecting to server\n", rc);
34303415
trace_smb3_connect_err(server->hostname, server->conn_id, &server->dstaddr, rc);
3431-
put_net(cifs_net_ns(server));
34323416
sock_release(socket);
34333417
server->ssocket = NULL;
34343418
return rc;

fs/smb/client/file.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,11 @@ int cifs_open(struct inode *inode, struct file *file)
10071007
} else {
10081008
_cifsFileInfo_put(cfile, true, false);
10091009
}
1010+
} else {
1011+
/* hard link on the defeered close file */
1012+
rc = cifs_get_hardlink_path(tcon, inode, file);
1013+
if (rc)
1014+
cifs_close_deferred_file(CIFS_I(inode));
10101015
}
10111016

10121017
if (server->oplocks)
@@ -2071,6 +2076,29 @@ cifs_move_llist(struct list_head *source, struct list_head *dest)
20712076
list_move(li, dest);
20722077
}
20732078

2079+
int
2080+
cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode,
2081+
struct file *file)
2082+
{
2083+
struct cifsFileInfo *open_file = NULL;
2084+
struct cifsInodeInfo *cinode = CIFS_I(inode);
2085+
int rc = 0;
2086+
2087+
spin_lock(&tcon->open_file_lock);
2088+
spin_lock(&cinode->open_file_lock);
2089+
2090+
list_for_each_entry(open_file, &cinode->openFileList, flist) {
2091+
if (file->f_flags == open_file->f_flags) {
2092+
rc = -EINVAL;
2093+
break;
2094+
}
2095+
}
2096+
2097+
spin_unlock(&cinode->open_file_lock);
2098+
spin_unlock(&tcon->open_file_lock);
2099+
return rc;
2100+
}
2101+
20742102
void
20752103
cifs_free_llist(struct list_head *llist)
20762104
{

0 commit comments

Comments
 (0)