diff options
author | Jeff Layton <jlayton@redhat.com> | 2009-07-23 15:22:30 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2009-07-27 20:51:59 -0400 |
commit | 7b91e2661addd8e2419cb45f6a322aa5dab9bcee (patch) | |
tree | cf17b0ca2bffa52c7e450cd75d5277c35cc9eda4 /fs/cifs | |
parent | fc013a58859b7cf85e53a05804a74952fe0a4117 (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.c | 12 | ||||
-rw-r--r-- | fs/cifs/connect.c | 13 |
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 | */ |
61 | static char *cifs_get_share_name(const char *node_name) | 61 | static 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 | } |