diff options
author | Paulo Alcantara <pc@manguebit.com> | 2023-04-21 21:52:32 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-05-11 17:03:41 +0300 |
commit | 64d62ac6d6514cba1305bd08e271ec1843bdd612 (patch) | |
tree | 864df9015430f429683214399c5726f9e6a8cce4 /fs/cifs/connect.c | |
parent | a744060574889927f2c22a0562d69aa820e3c9e1 (diff) | |
download | linux-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.c | 10 |
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; |