Message ID | 1259845781-18830-1-git-send-email-jlayton@redhat.com |
---|---|
State | New |
Headers | show |
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 > >
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 */
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(-)