summaryrefslogtreecommitdiff
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2023-04-21 21:52:32 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-05-11 17:03:41 +0300
commit64d62ac6d6514cba1305bd08e271ec1843bdd612 (patch)
tree864df9015430f429683214399c5726f9e6a8cce4 /fs/cifs/connect.c
parenta744060574889927f2c22a0562d69aa820e3c9e1 (diff)
downloadlinux-64d62ac6d6514cba1305bd08e271ec1843bdd612.tar.xz
cifs: fix potential use-after-free bugs in TCP_Server_Info::hostname
commit 90c49fce1c43e1cc152695e20363ff5087897c09 upstream. TCP_Server_Info::hostname may be updated once or many times during reconnect, so protect its access outside reconnect path as well and then prevent any potential use-after-free bugs. Cc: stable@vger.kernel.org Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 077c88c49dfd..21b31d1640e5 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -452,8 +452,10 @@ static int __reconnect_target_unlocked(struct TCP_Server_Info *server, const cha
if (server->hostname != target) {
hostname = extract_hostname(target);
if (!IS_ERR(hostname)) {
+ spin_lock(&server->srv_lock);
kfree(server->hostname);
server->hostname = hostname;
+ spin_unlock(&server->srv_lock);
} else {
cifs_dbg(FYI, "%s: couldn't extract hostname or address from dfs target: %ld\n",
__func__, PTR_ERR(hostname));
@@ -620,9 +622,7 @@ cifs_echo_request(struct work_struct *work)
goto requeue_echo;
rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
- if (rc)
- cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
- server->hostname);
+ cifs_server_dbg(FYI, "send echo request: rc = %d\n", rc);
/* Check witness registrations */
cifs_swn_check();
@@ -1462,6 +1462,8 @@ static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *
{
struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
+ lockdep_assert_held(&server->srv_lock);
+
if (ctx->nosharesock)
return 0;
@@ -1863,7 +1865,9 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
if (tcon == NULL)
return -ENOMEM;
+ spin_lock(&server->srv_lock);
scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
+ spin_unlock(&server->srv_lock);
xid = get_xid();
tcon->ses = ses;