aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2009-07-23 15:22:30 -0400
committerSteve French <sfrench@us.ibm.com>2009-07-27 20:51:59 -0400
commit7b91e2661addd8e2419cb45f6a322aa5dab9bcee (patch)
treecf17b0ca2bffa52c7e450cd75d5277c35cc9eda4 /fs/cifs
parentfc013a58859b7cf85e53a05804a74952fe0a4117 (diff)
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: Sandro Mathys <sm@sandro-mathys.ch> Acked-by: Igor Mammedov <niallain@gmail.com> CC: Stable <stable@kernel.org> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifs_dfs_ref.c12
-rw-r--r--fs/cifs/connect.c13
2 files changed, 19 insertions, 6 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 3bb11be8b6a8..606912d8f2a8 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(void)
55 * i.e. strips from UNC trailing path that is not part of share 55 * i.e. strips from UNC trailing path that is not part of share
56 * name and fixup missing '\' in the begining of DFS node refferal 56 * name and fixup missing '\' in the begining of DFS node refferal
57 * if neccessary. 57 * if neccessary.
58 * Returns pointer to share name on success or NULL on error. 58 * Returns pointer to share name on success or ERR_PTR on error.
59 * Caller is responsible for freeing returned string. 59 * Caller is responsible for freeing returned string.
60 */ 60 */
61static char *cifs_get_share_name(const char *node_name) 61static char *cifs_get_share_name(const char *node_name)
@@ -68,7 +68,7 @@ static char *cifs_get_share_name(const char *node_name)
68 UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, 68 UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */,
69 GFP_KERNEL); 69 GFP_KERNEL);
70 if (!UNC) 70 if (!UNC)
71 return NULL; 71 return ERR_PTR(-ENOMEM);
72 72
73 /* get share name and server name */ 73 /* get share name and server name */
74 if (node_name[1] != '\\') { 74 if (node_name[1] != '\\') {
@@ -87,7 +87,7 @@ static char *cifs_get_share_name(const char *node_name)
87 cERROR(1, ("%s: no server name end in node name: %s", 87 cERROR(1, ("%s: no server name end in node name: %s",
88 __func__, node_name)); 88 __func__, node_name));
89 kfree(UNC); 89 kfree(UNC);
90 return NULL; 90 return ERR_PTR(-EINVAL);
91 } 91 }
92 92
93 /* find sharename end */ 93 /* find sharename end */
@@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
133 return ERR_PTR(-EINVAL); 133 return ERR_PTR(-EINVAL);
134 134
135 *devname = cifs_get_share_name(ref->node_name); 135 *devname = cifs_get_share_name(ref->node_name);
136 if (IS_ERR(*devname)) {
137 rc = PTR_ERR(*devname);
138 *devname = NULL;
139 goto compose_mount_options_err;
140 }
141
136 rc = dns_resolve_server_name_to_ip(*devname, &srvIP); 142 rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
137 if (rc != 0) { 143 if (rc != 0) {
138 cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", 144 cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d",
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index fc44d316d0bb..f2486889b7bb 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2544,11 +2544,20 @@ remote_path_check:
2544 2544
2545 if (mount_data != mount_data_global) 2545 if (mount_data != mount_data_global)
2546 kfree(mount_data); 2546 kfree(mount_data);
2547
2547 mount_data = cifs_compose_mount_options( 2548 mount_data = cifs_compose_mount_options(
2548 cifs_sb->mountdata, full_path + 1, 2549 cifs_sb->mountdata, full_path + 1,
2549 referrals, &fake_devname); 2550 referrals, &fake_devname);
2550 kfree(fake_devname); 2551
2551 free_dfs_info_array(referrals, num_referrals); 2552 free_dfs_info_array(referrals, num_referrals);
2553 kfree(fake_devname);
2554 kfree(full_path);
2555
2556 if (IS_ERR(mount_data)) {
2557 rc = PTR_ERR(mount_data);
2558 mount_data = NULL;
2559 goto mount_fail_check;
2560 }
2552 2561
2553 if (tcon) 2562 if (tcon)
2554 cifs_put_tcon(tcon); 2563 cifs_put_tcon(tcon);
@@ -2556,8 +2565,6 @@ remote_path_check:
2556 cifs_put_smb_ses(pSesInfo); 2565 cifs_put_smb_ses(pSesInfo);
2557 2566
2558 cleanup_volume_info(&volume_info); 2567 cleanup_volume_info(&volume_info);
2559 FreeXid(xid);
2560 kfree(full_path);
2561 referral_walks_count++; 2568 referral_walks_count++;
2562 goto try_mount_again; 2569 goto try_mount_again;
2563 } 2570 }