Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b91e266 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French
Browse files

cifs: fix error handling in mount-time DFS referral chasing code



If the referral is malformed or the hostname can't be resolved, then
the current code generates an oops. Fix it to handle these errors
gracefully.

Reported-by: default avatarSandro Mathys <sm@sandro-mathys.ch>
Acked-by: default avatarIgor Mammedov <niallain@gmail.com>
CC: Stable <stable@kernel.org>
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent fc013a58
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(void)
 * i.e. strips from UNC trailing path that is not part of share
 * name and fixup missing '\' in the begining of DFS node refferal
 * if neccessary.
 * Returns pointer to share name on success or NULL on error.
 * Returns pointer to share name on success or ERR_PTR on error.
 * Caller is responsible for freeing returned string.
 */
static char *cifs_get_share_name(const char *node_name)
@@ -68,7 +68,7 @@ static char *cifs_get_share_name(const char *node_name)
	UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */,
			 GFP_KERNEL);
	if (!UNC)
		return NULL;
		return ERR_PTR(-ENOMEM);

	/* get share name and server name */
	if (node_name[1] != '\\') {
@@ -87,7 +87,7 @@ static char *cifs_get_share_name(const char *node_name)
		cERROR(1, ("%s: no server name end in node name: %s",
			__func__, node_name));
		kfree(UNC);
		return NULL;
		return ERR_PTR(-EINVAL);
	}

	/* find sharename end */
@@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
		return ERR_PTR(-EINVAL);

	*devname = cifs_get_share_name(ref->node_name);
	if (IS_ERR(*devname)) {
		rc = PTR_ERR(*devname);
		*devname = NULL;
		goto compose_mount_options_err;
	}

	rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
	if (rc != 0) {
		cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d",
+10 −3
Original line number Diff line number Diff line
@@ -2544,11 +2544,20 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,

			if (mount_data != mount_data_global)
				kfree(mount_data);

			mount_data = cifs_compose_mount_options(
					cifs_sb->mountdata, full_path + 1,
					referrals, &fake_devname);
			kfree(fake_devname);

			free_dfs_info_array(referrals, num_referrals);
			kfree(fake_devname);
			kfree(full_path);

			if (IS_ERR(mount_data)) {
				rc = PTR_ERR(mount_data);
				mount_data = NULL;
				goto mount_fail_check;
			}

			if (tcon)
				cifs_put_tcon(tcon);
@@ -2556,8 +2565,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
				cifs_put_smb_ses(pSesInfo);

			cleanup_volume_info(&volume_info);
			FreeXid(xid);
			kfree(full_path);
			referral_walks_count++;
			goto try_mount_again;
		}