cifs: fix error handling in mount-time DFS referral chasing code
authorJeff Layton <jlayton@redhat.com>
Thu, 23 Jul 2009 19:22:30 +0000 (15:22 -0400)
committerSteve French <sfrench@us.ibm.com>
Tue, 28 Jul 2009 00:51:59 +0000 (00:51 +0000)
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>
fs/cifs/cifs_dfs_ref.c
fs/cifs/connect.c

index 3bb11be8b6a8210271368fc8b6c44942c77a02a7..606912d8f2a885d9272a843e34542adc1cc9c3d0 100644 (file)
@@ -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",
index fc44d316d0bb4702eaa8d083cf9ed0eb746304ca..f2486889b7bb7634caf9872df3fa966f25e5b2a6 100644 (file)
@@ -2544,11 +2544,20 @@ remote_path_check:
 
                        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 @@ remote_path_check:
                                cifs_put_smb_ses(pSesInfo);
 
                        cleanup_volume_info(&volume_info);
-                       FreeXid(xid);
-                       kfree(full_path);
                        referral_walks_count++;
                        goto try_mount_again;
                }