diff mbox series

[3/3] cifs: To match file servers, make sure the server hostname matches

Message ID 20211215143527.7088-4-tim.gardner@canonical.com
State New
Headers show
Series CIFS stable updates | expand

Commit Message

Tim Gardner Dec. 15, 2021, 2:35 p.m. UTC
From: Shyam Prasad N <sprasad@microsoft.com>

BugLink: https://bugs.launchpad.net/bugs/1954926

commit 7be3248f313930ff3d3436d4e9ddbe9fccc1f541 upstream.

We generally rely on a bunch of factors to differentiate between servers.
For example, IP address, port etc.

For certain server types (like Azure), it is important to make sure
that the server hostname matches too, even if the both hostnames currently
resolve to the same IP address.

Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
Cc: stable@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
[rtg - backported by the Microsoft team. They dropped changes to
fs/cifs/fs_connect.[ch], added a structure tag to fs/cifs/cifsglob.h: struct smb_vol,
misc changes to fs/cifs/connect.c to reflect the intent of the original upstream patch]
---
 fs/cifs/cifsglob.h |  1 +
 fs/cifs/connect.c  | 38 ++++++++++++++++++++++++++++++--------
 2 files changed, 31 insertions(+), 8 deletions(-)

Comments

Kleber Sacilotto de Souza Dec. 15, 2021, 3:37 p.m. UTC | #1
On 15.12.21 15:35, Tim Gardner wrote:
> From: Shyam Prasad N <sprasad@microsoft.com>
>
> BugLink: https://bugs.launchpad.net/bugs/1954926
>
> commit 7be3248f313930ff3d3436d4e9ddbe9fccc1f541 upstream.
>
> We generally rely on a bunch of factors to differentiate between servers.
> For example, IP address, port etc.
>
> For certain server types (like Azure), it is important to make sure
> that the server hostname matches too, even if the both hostnames currently
> resolve to the same IP address.
>
> Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Steve French <stfrench@microsoft.com>
> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
The "(cherry picked|backported from commit ...)" is missing here. This seems
to have been picked up from a stable tree as a base, so a reference to that
commit would be good.

Kleber

> [rtg - backported by the Microsoft team. They dropped changes to
> fs/cifs/fs_connect.[ch], added a structure tag to fs/cifs/cifsglob.h: struct smb_vol,
> misc changes to fs/cifs/connect.c to reflect the intent of the original upstream patch]
> ---
>   fs/cifs/cifsglob.h |  1 +
>   fs/cifs/connect.c  | 38 ++++++++++++++++++++++++++++++--------
>   2 files changed, 31 insertions(+), 8 deletions(-)
>
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 10934d4d5ce33..9607f623c1357 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -538,6 +538,7 @@ struct smb_vol {
>   	char *username;
>   	char *password;
>   	char *domainname;
> +	char *server_hostname;
>   	char *UNC;
>   	char *iocharset;  /* local code page for mapping to and from Unicode */
>   	char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index de188a8b282a5..dfcac2489b46b 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -1101,7 +1101,6 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
>   		 */
>   	}
>   
> -	kfree(server->hostname);
>   	kfree(server);
>   
>   	length = atomic_dec_return(&tcpSesAllocCount);
> @@ -1653,6 +1652,11 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol)
>   	if (!pos)
>   		return -EINVAL;
>   
> +	/* record the server hostname */
> +	vol->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL);
> +	if (!vol->server_hostname)
> +		return -ENOMEM;
> +
>   	/* skip past delimiter */
>   	++pos;
>   
> @@ -2510,6 +2514,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
>   		goto cifs_parse_mount_err;
>   	}
>   #endif
> +
> +	if (!vol->server_hostname) {
> +		cifs_dbg(VFS, "CIFS mount error: Unable to parse server name in device string!\n");
> +		goto cifs_parse_mount_err;
> +	}
> +
>   	if (!vol->UNC) {
>   		cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
>   		goto cifs_parse_mount_err;
> @@ -2712,6 +2722,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
>   	if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
>   		return 0;
>   
> +	if (strcasecmp(server->hostname, vol->server_hostname))
> +		return 0;
> +
>   	if (!match_address(server, addr,
>   			   (struct sockaddr *)&vol->srcaddr))
>   		return 0;
> @@ -2796,6 +2809,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
>   	kfree(server->session_key.response);
>   	server->session_key.response = NULL;
>   	server->session_key.len = 0;
> +	kfree(server->hostname);
>   
>   	task = xchg(&server->tsk, NULL);
>   	if (task)
> @@ -2821,14 +2835,15 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
>   		goto out_err;
>   	}
>   
> +	tcp_ses->hostname = kstrdup(volume_info->server_hostname, GFP_KERNEL);
> +	if (!tcp_ses->hostname) {
> +		rc = -ENOMEM;
> +		goto out_err;
> +	}
> +
>   	tcp_ses->ops = volume_info->ops;
>   	tcp_ses->vals = volume_info->vals;
>   	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
> -	tcp_ses->hostname = extract_hostname(volume_info->UNC);
> -	if (IS_ERR(tcp_ses->hostname)) {
> -		rc = PTR_ERR(tcp_ses->hostname);
> -		goto out_err_crypto_release;
> -	}
>   
>   	tcp_ses->noblockcnt = volume_info->rootfs;
>   	tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
> @@ -2942,8 +2957,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
>   
>   out_err:
>   	if (tcp_ses) {
> -		if (!IS_ERR(tcp_ses->hostname))
> -			kfree(tcp_ses->hostname);
> +		kfree(tcp_ses->hostname);
>   		if (tcp_ses->ssocket)
>   			sock_release(tcp_ses->ssocket);
>   		kfree(tcp_ses);
> @@ -4272,6 +4286,7 @@ cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
>   	kfree(volume_info->username);
>   	kzfree(volume_info->password);
>   	kfree(volume_info->UNC);
> +	kfree(volume_info->server_hostname);
>   	kfree(volume_info->domainname);
>   	kfree(volume_info->iocharset);
>   	kfree(volume_info->prepath);
> @@ -4541,6 +4556,12 @@ static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
>   	kfree(vol->UNC);
>   	vol->UNC = new_unc;
>   
> +	if (fake_vol->server_hostname) {
> +		kfree(vol->server_hostname);
> +		vol->server_hostname = fake_vol->server_hostname;
> +		fake_vol->server_hostname = NULL;
> +	}
> +
>   	if (fake_vol->prepath) {
>   		kfree(vol->prepath);
>   		vol->prepath = fake_vol->prepath;
> @@ -5342,6 +5363,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
>   	vol_info->linux_uid = fsuid;
>   	vol_info->cred_uid = fsuid;
>   	vol_info->UNC = master_tcon->treeName;
> +	vol_info->server_hostname = master_tcon->ses->server->hostname;
>   	vol_info->retry = master_tcon->retry;
>   	vol_info->nocase = master_tcon->nocase;
>   	vol_info->nohandlecache = master_tcon->nohandlecache;
Tim Gardner Dec. 15, 2021, 3:42 p.m. UTC | #2
On 12/15/21 8:37 AM, Kleber Souza wrote:
> On 15.12.21 15:35, Tim Gardner wrote:
>> From: Shyam Prasad N <sprasad@microsoft.com>
>>
>> BugLink: https://bugs.launchpad.net/bugs/1954926
>>
>> commit 7be3248f313930ff3d3436d4e9ddbe9fccc1f541 upstream.
>>
>> We generally rely on a bunch of factors to differentiate between servers.
>> For example, IP address, port etc.
>>
>> For certain server types (like Azure), it is important to make sure
>> that the server hostname matches too, even if the both hostnames 
>> currently
>> resolve to the same IP address.
>>
>> Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Steve French <stfrench@microsoft.com>
>> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
> The "(cherry picked|backported from commit ...)" is missing here. This 
> seems
> to have been picked up from a stable tree as a base, so a reference to that
> commit would be good.
> 

It really wasn't picked up from a stable tree as far as I could tell, 
which is why I didn't put the 'backported from' line in here. I guess I 
considered it sufficient that we know from what upstream commit it does 
descend from, i.e., 'commit 7be3248f313930ff3d3436d4e9ddbe9fccc1f541 
upstream'. As noted in the commit log, I received this from the 
Microsoft team (probably done by Steve French the CIFS maintainer).

rtg

-----------
Tim Gardner
Canonical, Inc
diff mbox series

Patch

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 10934d4d5ce33..9607f623c1357 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -538,6 +538,7 @@  struct smb_vol {
 	char *username;
 	char *password;
 	char *domainname;
+	char *server_hostname;
 	char *UNC;
 	char *iocharset;  /* local code page for mapping to and from Unicode */
 	char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index de188a8b282a5..dfcac2489b46b 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1101,7 +1101,6 @@  static void clean_demultiplex_info(struct TCP_Server_Info *server)
 		 */
 	}
 
-	kfree(server->hostname);
 	kfree(server);
 
 	length = atomic_dec_return(&tcpSesAllocCount);
@@ -1653,6 +1652,11 @@  cifs_parse_devname(const char *devname, struct smb_vol *vol)
 	if (!pos)
 		return -EINVAL;
 
+	/* record the server hostname */
+	vol->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL);
+	if (!vol->server_hostname)
+		return -ENOMEM;
+
 	/* skip past delimiter */
 	++pos;
 
@@ -2510,6 +2514,12 @@  cifs_parse_mount_options(const char *mountdata, const char *devname,
 		goto cifs_parse_mount_err;
 	}
 #endif
+
+	if (!vol->server_hostname) {
+		cifs_dbg(VFS, "CIFS mount error: Unable to parse server name in device string!\n");
+		goto cifs_parse_mount_err;
+	}
+
 	if (!vol->UNC) {
 		cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
 		goto cifs_parse_mount_err;
@@ -2712,6 +2722,9 @@  static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
 	if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
 		return 0;
 
+	if (strcasecmp(server->hostname, vol->server_hostname))
+		return 0;
+
 	if (!match_address(server, addr,
 			   (struct sockaddr *)&vol->srcaddr))
 		return 0;
@@ -2796,6 +2809,7 @@  cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
 	kfree(server->session_key.response);
 	server->session_key.response = NULL;
 	server->session_key.len = 0;
+	kfree(server->hostname);
 
 	task = xchg(&server->tsk, NULL);
 	if (task)
@@ -2821,14 +2835,15 @@  cifs_get_tcp_session(struct smb_vol *volume_info)
 		goto out_err;
 	}
 
+	tcp_ses->hostname = kstrdup(volume_info->server_hostname, GFP_KERNEL);
+	if (!tcp_ses->hostname) {
+		rc = -ENOMEM;
+		goto out_err;
+	}
+
 	tcp_ses->ops = volume_info->ops;
 	tcp_ses->vals = volume_info->vals;
 	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
-	tcp_ses->hostname = extract_hostname(volume_info->UNC);
-	if (IS_ERR(tcp_ses->hostname)) {
-		rc = PTR_ERR(tcp_ses->hostname);
-		goto out_err_crypto_release;
-	}
 
 	tcp_ses->noblockcnt = volume_info->rootfs;
 	tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
@@ -2942,8 +2957,7 @@  cifs_get_tcp_session(struct smb_vol *volume_info)
 
 out_err:
 	if (tcp_ses) {
-		if (!IS_ERR(tcp_ses->hostname))
-			kfree(tcp_ses->hostname);
+		kfree(tcp_ses->hostname);
 		if (tcp_ses->ssocket)
 			sock_release(tcp_ses->ssocket);
 		kfree(tcp_ses);
@@ -4272,6 +4286,7 @@  cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
 	kfree(volume_info->username);
 	kzfree(volume_info->password);
 	kfree(volume_info->UNC);
+	kfree(volume_info->server_hostname);
 	kfree(volume_info->domainname);
 	kfree(volume_info->iocharset);
 	kfree(volume_info->prepath);
@@ -4541,6 +4556,12 @@  static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
 	kfree(vol->UNC);
 	vol->UNC = new_unc;
 
+	if (fake_vol->server_hostname) {
+		kfree(vol->server_hostname);
+		vol->server_hostname = fake_vol->server_hostname;
+		fake_vol->server_hostname = NULL;
+	}
+
 	if (fake_vol->prepath) {
 		kfree(vol->prepath);
 		vol->prepath = fake_vol->prepath;
@@ -5342,6 +5363,7 @@  cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
 	vol_info->linux_uid = fsuid;
 	vol_info->cred_uid = fsuid;
 	vol_info->UNC = master_tcon->treeName;
+	vol_info->server_hostname = master_tcon->ses->server->hostname;
 	vol_info->retry = master_tcon->retry;
 	vol_info->nocase = master_tcon->nocase;
 	vol_info->nohandlecache = master_tcon->nohandlecache;