]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS referrals
authorJeff Layton <jlayton@redhat.com>
Thu, 3 Dec 2009 13:09:41 +0000 (08:09 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 6 Jan 2010 22:26:20 +0000 (14:26 -0800)
commit a2934c7b363ddcc001964f2444649f909e583bef upstream.

The scenario is this:

The kernel gets EREMOTE and starts chasing a DFS referral at mount time.
The tcon reference is put, which puts the session reference too, but
neither pointer is zeroed out.

The mount gets retried (goto try_mount_again) with new mount info.
Session setup fails fails and rc ends up being non-zero. The code then
falls through to the end and tries to put the previously freed tcon
pointer again.  Oops at: cifs_put_smb_ses+0x14/0xd0

Fix this by moving the initialization of the rc variable and the tcon,
pSesInfo and srvTcp pointers below the try_mount_again label. Also, add
a FreeXid() before the goto to prevent xid "leaks".

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reported-by: Gustavo Carvalho Homem <gustavo@angulosolido.pt>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/cifs/connect.c

index 5c084e517d63a48ae95c1187c5910cd6cf92743f..08a44ca2a8db8f1f5acc9ee128d48e15c9585402 100644 (file)
@@ -2267,12 +2267,12 @@ int
 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                char *mount_data_global, const char *devname)
 {
-       int rc = 0;
+       int rc;
        int xid;
        struct smb_vol *volume_info;
-       struct cifsSesInfo *pSesInfo = NULL;
-       struct cifsTconInfo *tcon = NULL;
-       struct TCP_Server_Info *srvTcp = NULL;
+       struct cifsSesInfo *pSesInfo;
+       struct cifsTconInfo *tcon;
+       struct TCP_Server_Info *srvTcp;
        char   *full_path;
        char *mount_data = mount_data_global;
 #ifdef CONFIG_CIFS_DFS_UPCALL
@@ -2281,6 +2281,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        int referral_walks_count = 0;
 try_mount_again:
 #endif
+       rc = 0;
+       tcon = NULL;
+       pSesInfo = NULL;
+       srvTcp = NULL;
        full_path = NULL;
 
        xid = GetXid();
@@ -2577,6 +2581,7 @@ remote_path_check:
 
                        cleanup_volume_info(&volume_info);
                        referral_walks_count++;
+                       FreeXid(xid);
                        goto try_mount_again;
                }
 #else /* No DFS support, return error on mount */