cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS referrals

Submitted by Jeff Layton on Dec. 3, 2009, 1:09 p.m.

Details

Message ID 1259845781-18830-1-git-send-email-jlayton@redhat.com
State New
Headers show

Commit Message

Jeff Layton Dec. 3, 2009, 1:09 p.m.
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.

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>
---
 fs/cifs/connect.c |   13 +++++++++----
 1 files changed, 9 insertions(+), 4 deletions(-)

Comments

Steve French Dec. 3, 2009, 4:18 p.m.
Added cc: stable and Reported-by: line, and merged

On Thu, Dec 3, 2009 at 7:09 AM, Jeff Layton <jlayton@redhat.com> wrote:

> 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.
>
> 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>
> ---
>  fs/cifs/connect.c |   13 +++++++++----
>  1 files changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 63ea83f..3bbcaa7 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -2287,12 +2287,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
> @@ -2301,6 +2301,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();
> @@ -2597,6 +2601,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 */
> --
> 1.6.5.2
>
>

Patch hide | download patch | download mbox

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 63ea83f..3bbcaa7 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2287,12 +2287,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
@@ -2301,6 +2301,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();
@@ -2597,6 +2601,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 */