]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
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)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sun, 16 Aug 2009 21:18:32 +0000 (14:18 -0700)
commit 7b91e2661addd8e2419cb45f6a322aa5dab9bcee upstream.

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>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/cifs/cifs_dfs_ref.c
fs/cifs/connect.c

index 83d62759c7c7a42537674faa4b05958292076c08..3236d1acef2e062e2cffd0b84ccf5393c079c63c 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 1dc14f219adaaccd537cc4ef1bac652df01574cb..0b0b9df2350a5d7e68fd7288559a327c4952ae5a 100644 (file)
@@ -2563,11 +2563,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);
@@ -2575,8 +2584,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;
                }