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

login
register
mail settings
Submitter Jeff Layton
Date Dec. 3, 2009, 1:09 p.m.
Message ID <1259845781-18830-1-git-send-email-jlayton@redhat.com>
Download mbox | patch
Permalink /patch/40171/
State New
Headers show

Comments

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(-)
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

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 */