[linux-cifs-client,CIFS] Prevent OOPs when mounting with remote prefixpath
diff mbox

Message ID 49881AE6.4030109@gmail.com
State New, archived
Headers show

Commit Message

Igor Mammedov Feb. 3, 2009, 10:22 a.m. UTC
Managed to single out the part of  DFS root support from a big patch
with a little modification.
It will report error and fail to mount if perfixpath is on remote server.
As well it will not scare people off with a error 
'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.


---------
Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
Check if prefixpath in accessible while we are still in cifs_mount
and fail with reporting a error if we can't access prefixpath
(i.e. if prefixpath is located on another server)


Best regards,

-------------------------
Igor Mammedov,
niallain "at" gmail.com

Comments

Jeff Layton Feb. 4, 2009, 2:13 a.m. UTC | #1
On Tue, 03 Feb 2009 13:22:30 +0300
Igor Mammedov <niallain@gmail.com> wrote:

> From: Igor Mammedov <niallain@gmail.com>
> To: Steve French <smfrench@gmail.com>
> Cc: "linux-cifs-client@lists.samba.org" <linux-cifs-client@lists.samba.org>
> Subject: [linux-cifs-client] [PATCH] [CIFS] Prevent OOPs when mounting with remote prefixpath
> Date: Tue, 03 Feb 2009 13:22:30 +0300
> Sender: linux-cifs-client-bounces+jlayton=poochiereds.net@lists.samba.org
> User-Agent: Thunderbird 2.0.0.19 (X11/20081209)
> 
> Managed to single out the part of  DFS root support from a big patch
> with a little modification.
> It will report error and fail to mount if perfixpath is on remote server.
> As well it will not scare people off with a error 
> 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> 
> 
> ---------
> Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> Check if prefixpath in accessible while we are still in cifs_mount
> and fail with reporting a error if we can't access prefixpath
> (i.e. if prefixpath is located on another server)
> 
> 
> Best regards,
> 
> -------------------------
> Igor Mammedov,
> niallain "at" gmail.com
> 
> 
> 
> 
> 
> >From c61a715cbeee404a1bcc2788090b4d453eb43b8e Mon Sep 17 00:00:00 2001  
> From: Igor Mammedov <niallain@gmail.com>
> Date: Tue, 3 Feb 2009 12:43:56 +0300
> Subject: [PATCH] [CIFS] Prevent OOPs when mounting with remote prefixpath.
>  	Fix OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>  	Check if prefixpath in accesible while we are still in cifs_mount
>  	and fail with reporting a error if we can't access prefixpath
>          (i.e. if prefixpath is located on another server)
> 
> Signed-off-by: Igor Mammedov <niallain@gmail.com>
> ---
>  fs/cifs/cifsproto.h |    1 +
>  fs/cifs/connect.c   |   30 ++++++++++++++++++++++++++++++
>  fs/cifs/inode.c     |    2 +-
>  3 files changed, 32 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 382ba62..22ff09c 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -42,6 +42,7 @@ extern void _FreeXid(unsigned int);
>  #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
>  #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
>  extern char *build_path_from_dentry(struct dentry *);
> +extern char *build_path_to_root(struct cifs_sb_info *cifs_sb);
>  extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
>  /* extern void renew_parental_timestamps(struct dentry *direntry);*/
>  extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 2209be9..dcffaa9 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -2181,6 +2181,24 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
>  }
>  
>  int
> +is_path_accessible(int xid, struct cifsTconInfo *tcon,
> +		struct cifs_sb_info *cifs_sb,  const char *full_path)
> +{
> +	int rc;
> +	FILE_ALL_INFO *pfindData;
> +	pfindData = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
> +	if (pfindData == NULL)
> +		return -ENOMEM;
> +
> +	rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfindData,
> +			0 /* not legacy */,
> +			cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
> +			CIFS_MOUNT_MAP_SPECIAL_CHR);
> +	kfree(pfindData);
> +	return rc;
> +}
> +
> +int
>  cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
>  	   char *mount_data, const char *devname)
>  {
> @@ -2190,6 +2208,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
>  	struct cifsSesInfo *pSesInfo = NULL;
>  	struct cifsTconInfo *tcon = NULL;
>  	struct TCP_Server_Info *srvTcp = NULL;
> +	char *full_path;
>  
>  	xid = GetXid();
>  
> @@ -2426,6 +2445,17 @@ mount_fail_check:
>  		cifs_sb->rsize = min(cifs_sb->rsize,
>  			       (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
>  
> +
> +	full_path = build_path_to_root(cifs_sb);
> +	if (full_path != NULL) {
> +		rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
> +		kfree(full_path);
> +		if (rc) {
> +			cERROR(1, ("Remote DFS root not supported"));

                        ^^^ aren't you making an assumption about the error here? What if the allocation in is_path_accessable failed? A more helpful error message would be nice.

> +			goto mount_fail_check;
> +		}
> +	}
> +
>  	/* volume_info->password is freed above when existing session found
>  	(in which case it is not needed anymore) but when new sesion is created
>  	the password ptr is put in the new session structure (in which case the
> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> index bcf7b51..00c6a3f 100644
> --- a/fs/cifs/inode.c
> +++ b/fs/cifs/inode.c
> @@ -621,7 +621,7 @@ static const struct inode_operations cifs_ipc_inode_ops = {
>  	.lookup = cifs_lookup,
>  };
>  
> -static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
> +char *build_path_to_root(struct cifs_sb_info *cifs_sb)
>  {
>  	int pplen = cifs_sb->prepathlen;
>  	int dfsplen;
> -- 
> 1.6.0.2
> 

Other than the error message this seems reasonable. I assume that it's
been tested?
Igor Mammedov Feb. 4, 2009, 10:35 a.m. UTC | #2
Jeff Layton wrote:
> On Tue, 03 Feb 2009 13:22:30 +0300
> Igor Mammedov <niallain@gmail.com> wrote:
> 
>> From: Igor Mammedov <niallain@gmail.com>
>> To: Steve French <smfrench@gmail.com>
>> Cc: "linux-cifs-client@lists.samba.org" <linux-cifs-client@lists.samba.org>
>> Subject: [linux-cifs-client] [PATCH] [CIFS] Prevent OOPs when mounting with remote prefixpath
>> Date: Tue, 03 Feb 2009 13:22:30 +0300
>> Sender: linux-cifs-client-bounces+jlayton=poochiereds.net@lists.samba.org
>> User-Agent: Thunderbird 2.0.0.19 (X11/20081209)
>>
>> Managed to single out the part of  DFS root support from a big patch
>> with a little modification.
>> It will report error and fail to mount if perfixpath is on remote server.
>> As well it will not scare people off with a error 
>> 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>>
>>
>> ---------
>> Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>> Check if prefixpath in accessible while we are still in cifs_mount
>> and fail with reporting a error if we can't access prefixpath
>> (i.e. if prefixpath is located on another server)
>>
>>
>> Best regards,
>>
>> -------------------------
>> Igor Mammedov,
>> niallain "at" gmail.com
>>
>>
>>
>>
>>
>> >From c61a715cbeee404a1bcc2788090b4d453eb43b8e Mon Sep 17 00:00:00 2001  
>> From: Igor Mammedov <niallain@gmail.com>
>> Date: Tue, 3 Feb 2009 12:43:56 +0300
>> Subject: [PATCH] [CIFS] Prevent OOPs when mounting with remote prefixpath.
>>  	Fix OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>>  	Check if prefixpath in accesible while we are still in cifs_mount
>>  	and fail with reporting a error if we can't access prefixpath
>>          (i.e. if prefixpath is located on another server)
>>
>> Signed-off-by: Igor Mammedov <niallain@gmail.com>
>> ---
>>  fs/cifs/cifsproto.h |    1 +
>>  fs/cifs/connect.c   |   30 ++++++++++++++++++++++++++++++
>>  fs/cifs/inode.c     |    2 +-
>>  3 files changed, 32 insertions(+), 1 deletions(-)
>>
>> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
>> index 382ba62..22ff09c 100644
>> --- a/fs/cifs/cifsproto.h
>> +++ b/fs/cifs/cifsproto.h
>> @@ -42,6 +42,7 @@ extern void _FreeXid(unsigned int);
>>  #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
>>  #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
>>  extern char *build_path_from_dentry(struct dentry *);
>> +extern char *build_path_to_root(struct cifs_sb_info *cifs_sb);
>>  extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
>>  /* extern void renew_parental_timestamps(struct dentry *direntry);*/
>>  extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
>> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
>> index 2209be9..dcffaa9 100644
>> --- a/fs/cifs/connect.c
>> +++ b/fs/cifs/connect.c
>> @@ -2181,6 +2181,24 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
>>  }
>>  
>>  int
>> +is_path_accessible(int xid, struct cifsTconInfo *tcon,
>> +		struct cifs_sb_info *cifs_sb,  const char *full_path)
>> +{
>> +	int rc;
>> +	FILE_ALL_INFO *pfindData;
>> +	pfindData = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
>> +	if (pfindData == NULL)
>> +		return -ENOMEM;
>> +
>> +	rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfindData,
>> +			0 /* not legacy */,
>> +			cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
>> +			CIFS_MOUNT_MAP_SPECIAL_CHR);
>> +	kfree(pfindData);
>> +	return rc;
>> +}
>> +
>> +int
>>  cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
>>  	   char *mount_data, const char *devname)
>>  {
>> @@ -2190,6 +2208,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
>>  	struct cifsSesInfo *pSesInfo = NULL;
>>  	struct cifsTconInfo *tcon = NULL;
>>  	struct TCP_Server_Info *srvTcp = NULL;
>> +	char *full_path;
>>  
>>  	xid = GetXid();
>>  
>> @@ -2426,6 +2445,17 @@ mount_fail_check:
>>  		cifs_sb->rsize = min(cifs_sb->rsize,
>>  			       (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
>>  
>> +
>> +	full_path = build_path_to_root(cifs_sb);
>> +	if (full_path != NULL) {
>> +		rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
>> +		kfree(full_path);
>> +		if (rc) {
>> +			cERROR(1, ("Remote DFS root not supported"));
> 
>                         ^^^ aren't you making an assumption about the error here? What if the allocation in is_path_accessable failed? A more helpful error message would be nice.
> 
>> +			goto mount_fail_check;
>> +		}
>> +	}
>> +
>>  	/* volume_info->password is freed above when existing session found
>>  	(in which case it is not needed anymore) but when new sesion is created
>>  	the password ptr is put in the new session structure (in which case the
>> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
>> index bcf7b51..00c6a3f 100644
>> --- a/fs/cifs/inode.c
>> +++ b/fs/cifs/inode.c
>> @@ -621,7 +621,7 @@ static const struct inode_operations cifs_ipc_inode_ops = {
>>  	.lookup = cifs_lookup,
>>  };
>>  
>> -static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
>> +char *build_path_to_root(struct cifs_sb_info *cifs_sb)
>>  {
>>  	int pplen = cifs_sb->prepathlen;
>>  	int dfsplen;
>> -- 
>> 1.6.0.2
>>
> 
> Other than the error message this seems reasonable. I assume that it's
> been tested?
> 

I've tested it in mine test env.
About 'error message', Any suggestions on what should be there?
Jeff Layton Feb. 4, 2009, 12:13 p.m. UTC | #3
On Wed, 04 Feb 2009 13:35:16 +0300
Igor Mammedov <niallain@gmail.com> wrote:

> Jeff Layton wrote:
> > On Tue, 03 Feb 2009 13:22:30 +0300
> > Igor Mammedov <niallain@gmail.com> wrote:
> > 
> >> From: Igor Mammedov <niallain@gmail.com>
> >> To: Steve French <smfrench@gmail.com>
> >> Cc: "linux-cifs-client@lists.samba.org" <linux-cifs-client@lists.samba.org>
> >> Subject: [linux-cifs-client] [PATCH] [CIFS] Prevent OOPs when mounting with remote prefixpath
> >> Date: Tue, 03 Feb 2009 13:22:30 +0300
> >> Sender: linux-cifs-client-bounces+jlayton=poochiereds.net@lists.samba.org
> >> User-Agent: Thunderbird 2.0.0.19 (X11/20081209)
> >>
> >> Managed to single out the part of  DFS root support from a big patch
> >> with a little modification.
> >> It will report error and fail to mount if perfixpath is on remote server.
> >> As well it will not scare people off with a error 
> >> 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> >>
> >>
> >> ---------
> >> Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> >> Check if prefixpath in accessible while we are still in cifs_mount
> >> and fail with reporting a error if we can't access prefixpath
> >> (i.e. if prefixpath is located on another server)
> >>
> >>
> >> Best regards,
> >>
> >> -------------------------
> >> Igor Mammedov,
> >> niallain "at" gmail.com
> >>
> >>
> >>
> >>
> >>
> >> >From c61a715cbeee404a1bcc2788090b4d453eb43b8e Mon Sep 17 00:00:00 2001  
> >> From: Igor Mammedov <niallain@gmail.com>
> >> Date: Tue, 3 Feb 2009 12:43:56 +0300
> >> Subject: [PATCH] [CIFS] Prevent OOPs when mounting with remote prefixpath.
> >>  	Fix OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> >>  	Check if prefixpath in accesible while we are still in cifs_mount
> >>  	and fail with reporting a error if we can't access prefixpath
> >>          (i.e. if prefixpath is located on another server)
> >>
> >> Signed-off-by: Igor Mammedov <niallain@gmail.com>
> >> ---
> >>  fs/cifs/cifsproto.h |    1 +
> >>  fs/cifs/connect.c   |   30 ++++++++++++++++++++++++++++++
> >>  fs/cifs/inode.c     |    2 +-
> >>  3 files changed, 32 insertions(+), 1 deletions(-)
> >>
> >> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> >> index 382ba62..22ff09c 100644
> >> --- a/fs/cifs/cifsproto.h
> >> +++ b/fs/cifs/cifsproto.h
> >> @@ -42,6 +42,7 @@ extern void _FreeXid(unsigned int);
> >>  #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
> >>  #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
> >>  extern char *build_path_from_dentry(struct dentry *);
> >> +extern char *build_path_to_root(struct cifs_sb_info *cifs_sb);
> >>  extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
> >>  /* extern void renew_parental_timestamps(struct dentry *direntry);*/
> >>  extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
> >> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> >> index 2209be9..dcffaa9 100644
> >> --- a/fs/cifs/connect.c
> >> +++ b/fs/cifs/connect.c
> >> @@ -2181,6 +2181,24 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
> >>  }
> >>  
> >>  int
> >> +is_path_accessible(int xid, struct cifsTconInfo *tcon,
> >> +		struct cifs_sb_info *cifs_sb,  const char *full_path)
> >> +{
> >> +	int rc;
> >> +	FILE_ALL_INFO *pfindData;
> >> +	pfindData = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
> >> +	if (pfindData == NULL)
> >> +		return -ENOMEM;
> >> +
> >> +	rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfindData,
> >> +			0 /* not legacy */,
> >> +			cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
> >> +			CIFS_MOUNT_MAP_SPECIAL_CHR);
> >> +	kfree(pfindData);
> >> +	return rc;
> >> +}
> >> +
> >> +int
> >>  cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
> >>  	   char *mount_data, const char *devname)
> >>  {
> >> @@ -2190,6 +2208,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
> >>  	struct cifsSesInfo *pSesInfo = NULL;
> >>  	struct cifsTconInfo *tcon = NULL;
> >>  	struct TCP_Server_Info *srvTcp = NULL;
> >> +	char *full_path;
> >>  
> >>  	xid = GetXid();
> >>  
> >> @@ -2426,6 +2445,17 @@ mount_fail_check:
> >>  		cifs_sb->rsize = min(cifs_sb->rsize,
> >>  			       (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
> >>  
> >> +
> >> +	full_path = build_path_to_root(cifs_sb);
> >> +	if (full_path != NULL) {
> >> +		rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
> >> +		kfree(full_path);
> >> +		if (rc) {
> >> +			cERROR(1, ("Remote DFS root not supported"));
> > 
> >                         ^^^ aren't you making an assumption about the error here? What if the allocation in is_path_accessable failed? A more helpful error message would be nice.
> > 
> >> +			goto mount_fail_check;
> >> +		}
> >> +	}
> >> +
> >>  	/* volume_info->password is freed above when existing session found
> >>  	(in which case it is not needed anymore) but when new sesion is created
> >>  	the password ptr is put in the new session structure (in which case the
> >> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> >> index bcf7b51..00c6a3f 100644
> >> --- a/fs/cifs/inode.c
> >> +++ b/fs/cifs/inode.c
> >> @@ -621,7 +621,7 @@ static const struct inode_operations cifs_ipc_inode_ops = {
> >>  	.lookup = cifs_lookup,
> >>  };
> >>  
> >> -static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
> >> +char *build_path_to_root(struct cifs_sb_info *cifs_sb)
> >>  {
> >>  	int pplen = cifs_sb->prepathlen;
> >>  	int dfsplen;
> >> -- 
> >> 1.6.0.2
> >>
> > 
> > Other than the error message this seems reasonable. I assume that it's
> > been tested?
> > 
> 
> I've tested it in mine test env.
> About 'error message', Any suggestions on what should be there?
> 

Maybe something like:

    cERROR(1, ("Path %s not accessable: %d", full_path, rc));

...of course, you'd need to not kfree full_path until after this is
printed but that's not too tough.

Won't this error also fire when trying to mount with an inaccessable
prefixpath, even if DFS is involved? If so, then mentioning DFS in
the error is probably going to be confusing for users/admins.

Actually, there's another problem too. If build_path_to_root ends up
returning NULL, then we'll just skip this check. Shouldn't we return
-ENOMEM or something at that point? It's probably better to fail the
mount than to leave the client subject to a later oops...
Shirish Pargaonkar Feb. 10, 2009, 7:32 p.m. UTC | #4
On Tue, Feb 3, 2009 at 4:22 AM, Igor Mammedov <niallain@gmail.com> wrote:
> Managed to single out the part of  DFS root support from a big patch
> with a little modification.
> It will report error and fail to mount if perfixpath is on remote server.
> As well it will not scare people off with a error
> 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>
>
> ---------
> Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> Check if prefixpath in accessible while we are still in cifs_mount
> and fail with reporting a error if we can't access prefixpath
> (i.e. if prefixpath is located on another server)
>
>
> Best regards,
>
> -------------------------
> Igor Mammedov,
> niallain "at" gmail.com
>
>
>
>
>


Even before I can apply this patch and test, I do run into this system
crash on a 2.6.29-rc3

keyutils-1.2-108.6
keyutils-libs-1.2-108.6


 #0 [ffff88012c891640] crash_kexec at ffffffff80272cb6
 #1 [ffff88012c891720] oops_end at ffffffff804b1c25
 #2 [ffff88012c891750] do_page_fault at ffffffff804b3ac6
 #3 [ffff88012c891a60] page_fault at ffffffff804b1145
 #4 [ffff88012c891ae8] __ticket_spin_lock at ffffffff80225215
 #5 [ffff88012c891b20] _spin_lock_irq at ffffffff804b0ca8
 #6 [ffff88012c891b30] __down_write_nested at ffffffff804b0a1f
 #7 [ffff88012c891b70] __down_write at ffffffff804b0af1
 #8 [ffff88012c891b80] down_write at ffffffff804afc04
 #9 [ffff88012c891b90] request_key_and_link at ffffffff80338565
#10 [ffff88012c891c00] request_key at ffffffff803387cf
#11 [ffff88012c891c30] dns_resolve_server_name_to_ip at ffffffffa031dd4b
#12 [ffff88012c891c80] cifs_dfs_follow_mountpoint at ffffffffa031e1ce
#13 [ffff88012c891d50] __link_path_walk at ffffffff802d8513
#14 [ffff88012c891de0] path_walk at ffffffff802d8a43
#15 [ffff88012c891e20] do_path_lookup at ffffffff802d8cd2
#16 [ffff88012c891e60] user_path_at at ffffffff802d979f
#17 [ffff88012c891f30] sys_getxattr at ffffffff802e7b1d
#18 [ffff88012c891f80] system_call_fastpath at ffffffff8020c42a
David Howells Feb. 10, 2009, 8:47 p.m. UTC | #5
Shirish Pargaonkar <shirishpargaonkar@gmail.com> wrote:

> Even before I can apply this patch and test, I do run into this system
> crash on a 2.6.29-rc3

Do you have any more of the text of the crash?  The register dump or the crash
message, for example?

There's only one down_write() in request_key.c, so I suspect the destination
keyring pointer is corrupt in some way.

David
Shirish Pargaonkar Feb. 13, 2009, 5:18 a.m. UTC | #6
On Tue, Feb 3, 2009 at 4:22 AM, Igor Mammedov <niallain@gmail.com> wrote:
> Managed to single out the part of  DFS root support from a big patch
> with a little modification.
> It will report error and fail to mount if perfixpath is on remote server.
> As well it will not scare people off with a error
> 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>
>
> ---------
> Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> Check if prefixpath in accessible while we are still in cifs_mount
> and fail with reporting a error if we can't access prefixpath
> (i.e. if prefixpath is located on another server)
>
>
> Best regards,
>
> -------------------------
> Igor Mammedov,
> niallain "at" gmail.com
>
>
>
>
>

We need to bring back NIPQUAD and NIPQUAD_FMT back in cifs_mount
instead of %pI4 i..e.
sprintf(pSesInfo->serverName, NIPQUAD_FMT,
                                NIPQUAD(srvTcp->addr.sockAddr.sin_addr.s_addr));
If we sprintf hex address in serverName instead of dotted-decimal
notation, the Path parameter in Tree Connect
to IPC$ share on the server to get dfs referral fails,
\\hex_address\IPC$ is not a valid UNC path name.

I have not tried on a IPv6 setup, but I suspect the same applies to
IPv6 formatting.

Regards,

Shirish
Jeff Layton Feb. 13, 2009, 2:36 p.m. UTC | #7
On Thu, 12 Feb 2009 23:18:16 -0600
Shirish Pargaonkar <shirishpargaonkar@gmail.com> wrote:

> On Tue, Feb 3, 2009 at 4:22 AM, Igor Mammedov <niallain@gmail.com> wrote:
> > Managed to single out the part of  DFS root support from a big patch
> > with a little modification.
> > It will report error and fail to mount if perfixpath is on remote server.
> > As well it will not scare people off with a error
> > 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> >
> >
> > ---------
> > Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> > Check if prefixpath in accessible while we are still in cifs_mount
> > and fail with reporting a error if we can't access prefixpath
> > (i.e. if prefixpath is located on another server)
> >
> >
> > Best regards,
> >
> > -------------------------
> > Igor Mammedov,
> > niallain "at" gmail.com
> >
> >
> >
> >
> >
> 
> We need to bring back NIPQUAD and NIPQUAD_FMT back in cifs_mount
> instead of %pI4 i..e.
> sprintf(pSesInfo->serverName, NIPQUAD_FMT,
>                                 NIPQUAD(srvTcp->addr.sockAddr.sin_addr.s_addr));
> If we sprintf hex address in serverName instead of dotted-decimal
> notation, the Path parameter in Tree Connect
> to IPC$ share on the server to get dfs referral fails,
> \\hex_address\IPC$ is not a valid UNC path name.
> 
> I have not tried on a IPv6 setup, but I suspect the same applies to
> IPv6 formatting.
> 

I'm afraid I don't follow this. %pI4 formats the address in
dotted-decimal format, not as a hex address. %pI6 should format it the
same way that NIP6_FMT did.
Shirish Pargaonkar Feb. 13, 2009, 5:32 p.m. UTC | #8
On Fri, Feb 13, 2009 at 8:36 AM, Jeff Layton <jlayton@redhat.com> wrote:
> On Thu, 12 Feb 2009 23:18:16 -0600
> Shirish Pargaonkar <shirishpargaonkar@gmail.com> wrote:
>
>> On Tue, Feb 3, 2009 at 4:22 AM, Igor Mammedov <niallain@gmail.com> wrote:
>> > Managed to single out the part of  DFS root support from a big patch
>> > with a little modification.
>> > It will report error and fail to mount if perfixpath is on remote server.
>> > As well it will not scare people off with a error
>> > 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>> >
>> >
>> > ---------
>> > Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>> > Check if prefixpath in accessible while we are still in cifs_mount
>> > and fail with reporting a error if we can't access prefixpath
>> > (i.e. if prefixpath is located on another server)
>> >
>> >
>> > Best regards,
>> >
>> > -------------------------
>> > Igor Mammedov,
>> > niallain "at" gmail.com
>> >
>> >
>> >
>> >
>> >
>>
>> We need to bring back NIPQUAD and NIPQUAD_FMT back in cifs_mount
>> instead of %pI4 i..e.
>> sprintf(pSesInfo->serverName, NIPQUAD_FMT,
>>                                 NIPQUAD(srvTcp->addr.sockAddr.sin_addr.s_addr));
>> If we sprintf hex address in serverName instead of dotted-decimal
>> notation, the Path parameter in Tree Connect
>> to IPC$ share on the server to get dfs referral fails,
>> \\hex_address\IPC$ is not a valid UNC path name.
>>
>> I have not tried on a IPv6 setup, but I suspect the same applies to
>> IPv6 formatting.
>>
>
> I'm afraid I don't follow this. %pI4 formats the address in
> dotted-decimal format, not as a hex address. %pI6 should format it the
> same way that NIP6_FMT did.
>
> --
> Jeff Layton <jlayton@redhat.com>
>

Jeff,

You are right, it works. I was using 2.6.29-rc3 cifs code in 2.6.27
and  I think that is why.

Regards,

Shirish
Steve French Feb. 13, 2009, 6:15 p.m. UTC | #9
The DFS mount now works?

On Fri, Feb 13, 2009 at 11:32 AM, Shirish Pargaonkar <
shirishpargaonkar@gmail.com> wrote:

> On Fri, Feb 13, 2009 at 8:36 AM, Jeff Layton <jlayton@redhat.com> wrote:
> > On Thu, 12 Feb 2009 23:18:16 -0600
> > Shirish Pargaonkar <shirishpargaonkar@gmail.com> wrote:
> >
> >> On Tue, Feb 3, 2009 at 4:22 AM, Igor Mammedov <niallain@gmail.com>
> wrote:
> >> > Managed to single out the part of  DFS root support from a big patch
> >> > with a little modification.
> >> > It will report error and fail to mount if perfixpath is on remote
> server.
> >> > As well it will not scare people off with a error
> >> > 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> >> >
> >> >
> >> > ---------
> >> > Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
> >> > Check if prefixpath in accessible while we are still in cifs_mount
> >> > and fail with reporting a error if we can't access prefixpath
> >> > (i.e. if prefixpath is located on another server)
> >> >
> >> >
> >> > Best regards,
> >> >
> >> > -------------------------
> >> > Igor Mammedov,
> >> > niallain "at" gmail.com
> >> >
> >> >
> >> >
> >> >
> >> >
> >>
> >> We need to bring back NIPQUAD and NIPQUAD_FMT back in cifs_mount
> >> instead of %pI4 i..e.
> >> sprintf(pSesInfo->serverName, NIPQUAD_FMT,
> >>
> NIPQUAD(srvTcp->addr.sockAddr.sin_addr.s_addr));
> >> If we sprintf hex address in serverName instead of dotted-decimal
> >> notation, the Path parameter in Tree Connect
> >> to IPC$ share on the server to get dfs referral fails,
> >> \\hex_address\IPC$ is not a valid UNC path name.
> >>
> >> I have not tried on a IPv6 setup, but I suspect the same applies to
> >> IPv6 formatting.
> >>
> >
> > I'm afraid I don't follow this. %pI4 formats the address in
> > dotted-decimal format, not as a hex address. %pI6 should format it the
> > same way that NIP6_FMT did.
> >
> > --
> > Jeff Layton <jlayton@redhat.com>
> >
>
> Jeff,
>
> You are right, it works. I was using 2.6.29-rc3 cifs code in 2.6.27
> and  I think that is why.
>
> Regards,
>
> Shirish
>
Shirish Pargaonkar Feb. 13, 2009, 7:18 p.m. UTC | #10
On Fri, Feb 13, 2009 at 12:15 PM, Steve French <smfrench@gmail.com> wrote:
> The DFS mount now works?
>
> On Fri, Feb 13, 2009 at 11:32 AM, Shirish Pargaonkar
> <shirishpargaonkar@gmail.com> wrote:
>>
>> On Fri, Feb 13, 2009 at 8:36 AM, Jeff Layton <jlayton@redhat.com> wrote:
>> > On Thu, 12 Feb 2009 23:18:16 -0600
>> > Shirish Pargaonkar <shirishpargaonkar@gmail.com> wrote:
>> >
>> >> On Tue, Feb 3, 2009 at 4:22 AM, Igor Mammedov <niallain@gmail.com>
>> >> wrote:
>> >> > Managed to single out the part of  DFS root support from a big patch
>> >> > with a little modification.
>> >> > It will report error and fail to mount if perfixpath is on remote
>> >> > server.
>> >> > As well it will not scare people off with a error
>> >> > 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>> >> >
>> >> >
>> >> > ---------
>> >> > Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
>> >> > Check if prefixpath in accessible while we are still in cifs_mount
>> >> > and fail with reporting a error if we can't access prefixpath
>> >> > (i.e. if prefixpath is located on another server)
>> >> >
>> >> >
>> >> > Best regards,
>> >> >
>> >> > -------------------------
>> >> > Igor Mammedov,
>> >> > niallain "at" gmail.com
>> >> >
>> >> >
>> >> >
>> >> >
>> >> >
>> >>
>> >> We need to bring back NIPQUAD and NIPQUAD_FMT back in cifs_mount
>> >> instead of %pI4 i..e.
>> >> sprintf(pSesInfo->serverName, NIPQUAD_FMT,
>> >>
>> >> NIPQUAD(srvTcp->addr.sockAddr.sin_addr.s_addr));
>> >> If we sprintf hex address in serverName instead of dotted-decimal
>> >> notation, the Path parameter in Tree Connect
>> >> to IPC$ share on the server to get dfs referral fails,
>> >> \\hex_address\IPC$ is not a valid UNC path name.
>> >>
>> >> I have not tried on a IPv6 setup, but I suspect the same applies to
>> >> IPv6 formatting.
>> >>
>> >
>> > I'm afraid I don't follow this. %pI4 formats the address in
>> > dotted-decimal format, not as a hex address. %pI6 should format it the
>> > same way that NIP6_FMT did.
>> >
>> > --
>> > Jeff Layton <jlayton@redhat.com>
>> >
>>
>> Jeff,
>>
>> You are right, it works. I was using 2.6.29-rc3 cifs code in 2.6.27
>> and  I think that is why.
>>
>> Regards,
>>
>> Shirish
>
>
>
> --
> Thanks,
>
> Steve
>

DFS mount works on 2.6.29-rc3 with the current code (%pI6 and %pI4)
but the machine still
crashes when I try to list the mount (i.e. ls -l <mounted_filesystem),
no resolution there yet.

DFS mount works, because I am back to using this on 2.6.27.8-1-default

                if (srvTcp->addr.sockAddr6.sin6_family == AF_INET6)
                        sprintf(pSesInfo->serverName, "%pI6",
                                &srvTcp->addr.sockAddr6.sin6_addr);
                else {
                        sprintf(pSesInfo->serverName, NIPQUAD_FMT,
                                NIPQUAD(srvTcp->addr.sockAddr.sin_addr));
                }

But wiith this patch prefixpath does not seem to work for me, either
when prefix path is local on the dfslink or prefix path
is a mounted share on the dfslink (no crashes or oopses though)

This works

mount -t cifs //cifstest1/dfsroot /mnt/smb_a -o user=user,pass=password

ls -l /mnt/smb_a
total 0
drwxrwxrwx 1 root root 0 Feb 11 18:40 linktocifstest4

ls -l /mnt/smb_a/linktocifstest4
total 4
drwxr-xr-x  2 root root  0 Feb  6 03:35 dir1
drwxr-xr-x 14 root root  0 Jan 18  2006 dir2
-rw-r--r--  1 root root 18 Nov 10 09:32 file1


This fails (dir1 exists locally on cifstest4 share (the dfslink'ed machine),

mount -t cifs //cifstest1/dfsroot /mnt/smb_a -o
prefixpath=dir1,user=user,pass=password
mount error 2 = No such file or directory
Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)

fs/cifs.ssp/transport.c: For smb_command 117
 fs/cifs.ssp/transport.c: Sending smb:  total_len 124
 fs/cifs.ssp/connect.c: rfc1002 length 0x42
 fs/cifs.ssp/connect.c: disk share connection
 fs/cifs.ssp/connect.c: Tcon flags: 0x3
 fs/cifs.ssp/connect.c: CIFS Tcon rc = 0
 fs/cifs.ssp/cifssmb.c: In QFSDeviceInfo
 fs/cifs.ssp/transport.c: For smb_command 50
 fs/cifs.ssp/transport.c: Sending smb:  total_len 72
 fs/cifs.ssp/connect.c: rfc1002 length 0x44
 fs/cifs.ssp/cifssmb.c: In QFSAttributeInfo
 fs/cifs.ssp/transport.c: For smb_command 50
 fs/cifs.ssp/transport.c: Sending smb:  total_len 72
 fs/cifs.ssp/connect.c: rfc1002 length 0x50
 fs/cifs.ssp/transport.c: For smb_command 50
 fs/cifs.ssp/transport.c: Sending smb:  total_len 156
 fs/cifs.ssp/connect.c: rfc1002 length 0x27
 fs/cifs.ssp/connect.c: invalid transact2 word count
Status code returned 0xc0000034 NT_STATUS_OBJECT_NAME_NOT_FOUND
 fs/cifs.ssp/netmisc.c: Mapping smb error code 2 to POSIX err -2
 fs/cifs.ssp/cifssmb.c: Send error in QPathInfo = -2
 CIFS VFS: Path \\cifstest1\dfsroot\dir1 in not accessible: -2
 fs/cifs.ssp/connect.c: CIFS VFS: in cifs_put_tcon as Xid: 68 with uid: 0
 fs/cifs.ssp/cifssmb.c: In tree disconnect
 fs/cifs.ssp/transport.c: For smb_command 113
 fs/cifs.ssp/transport.c: Sending smb:  total_len 39
 fs/cifs.ssp/connect.c: rfc1002 length 0x27
 fs/cifs.ssp/connect.c: CIFS VFS: in cifs_put_smb_ses as Xid: 69 with uid: 0
 fs/cifs.ssp/cifssmb.c: In SMBLogoff for session disconnect
 fs/cifs.ssp/transport.c: For smb_command 116
 fs/cifs.ssp/transport.c: Sending smb:  total_len 43
 fs/cifs.ssp/connect.c: rfc1002 length 0x2b
 fs/cifs.ssp/connect.c: CIFS VFS: leaving cifs_mount (xid = 67) rc = -2
 CIFS VFS: cifs_mount failed w/return code = -2


This fails as well (dir2 is mounted share from cifstest5)

mount -t cifs //cifstest1/dfsroot /mnt/smb_a -o
prefixpath=dir2,user=user,pass=password
mount error 2 = No such file or directory
Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)



Then I tried this and the mount failed,

mount -t cifs //cifstest1/dfsroot /mnt/smb_a -o
prefixpath=linktocifstest4/dir1,user=user,pass=password
mount error 66 = Object is remote

 fs/cifs.ssp/cifsfs.c: Devname: //cifstest1/dfsroot flags: 64
 fs/cifs.ssp/connect.c: CIFS VFS: in cifs_mount as Xid: 79 with uid: 0
 fs/cifs.ssp/connect.c: prefix path /linktocifstest4/dir1
 fs/cifs.ssp/connect.c: Username: user
 fs/cifs.ssp/connect.c: UNC: \\cifstest1\dfsroot ip: 9.3.uvw.xyz
 fs/cifs.ssp/connect.c: Socket created
 fs/cifs.ssp/connect.c: sndbuf 16384 rcvbuf 87380 rcvtimeo 0x6d6
 fs/cifs.ssp/connect.c: Existing smb sess not found
 CIFS VFS: cifs_mount serverName: 9.3.uvw.xyz
 fs/cifs.ssp/connect.c: Demultiplex PID: 3996
 fs/cifs.ssp/cifssmb.c: secFlags 0x7
 fs/cifs.ssp/transport.c: For smb_command 114
 fs/cifs.ssp/transport.c: Sending smb:  total_len 82
 fs/cifs.ssp/connect.c: rfc1002 length 0x7d
 fs/cifs.ssp/cifssmb.c: Dialect: 2
 fs/cifs.ssp/cifssmb.c: negprot rc 0
 fs/cifs.ssp/connect.c: Security Mode: 0xf Capabilities: 0x1f3fd
TimeAdjust: 21600
 fs/cifs.ssp/sess.c: sess setup type 2
 fs/cifs.ssp/transport.c: For smb_command 115
 fs/cifs.ssp/transport.c: Sending smb:  total_len 262
 fs/cifs.ssp/connect.c: rfc1002 length 0xd1
 fs/cifs.ssp/misc.c: Null buffer passed to cifs_small_buf_release
 fs/cifs.ssp/sess.c: ssetup rc from sendrecv2 is 0
 fs/cifs.ssp/sess.c: UID = 16385
 fs/cifs.ssp/sess.c: bleft 164
 fs/cifs.ssp/sess.c: words left: -1
 fs/cifs.ssp/sess.c: ssetup freeing small buf ffff88013d499d40
 fs/cifs.ssp/connect.c: CIFS Session Established successfully
 fs/cifs.ssp/connect.c: file mode: 0x5f7  dir mode: 0x1ff
 fs/cifs.ssp/transport.c: For smb_command 117
 fs/cifs.ssp/transport.c: Sending smb:  total_len 124
 fs/cifs.ssp/connect.c: rfc1002 length 0x42
 fs/cifs.ssp/connect.c: disk share connection
 fs/cifs.ssp/connect.c: Tcon flags: 0x3
 fs/cifs.ssp/connect.c: CIFS Tcon rc = 0
 fs/cifs.ssp/cifssmb.c: In QFSDeviceInfo
 fs/cifs.ssp/transport.c: For smb_command 50
 fs/cifs.ssp/transport.c: Sending smb:  total_len 72
 fs/cifs.ssp/connect.c: rfc1002 length 0x44
 fs/cifs.ssp/cifssmb.c: In QFSAttributeInfo
 fs/cifs.ssp/transport.c: For smb_command 50
 fs/cifs.ssp/transport.c: Sending smb:  total_len 72
 fs/cifs.ssp/connect.c: rfc1002 length 0x50
 fs/cifs.ssp/transport.c: For smb_command 50
 fs/cifs.ssp/transport.c: Sending smb:  total_len 188
 fs/cifs.ssp/connect.c: rfc1002 length 0x27
 fs/cifs.ssp/connect.c: invalid transact2 word count
Status code returned 0xc0000257 NT_STATUS_PATH_NOT_COVERED
 fs/cifs.ssp/netmisc.c: Mapping smb error code 3 to POSIX err -66
 fs/cifs.ssp/cifssmb.c: Send error in QPathInfo = -66
 CIFS VFS: Path \\cifstest1\dfsroot\linktocifstest4\dir1 in not accessible: -66
 fs/cifs.ssp/connect.c: CIFS VFS: in cifs_put_tcon as Xid: 80 with uid: 0
 fs/cifs.ssp/cifssmb.c: In tree disconnect
 fs/cifs.ssp/transport.c: For smb_command 113
 fs/cifs.ssp/transport.c: Sending smb:  total_len 39
 fs/cifs.ssp/connect.c: rfc1002 length 0x27
 fs/cifs.ssp/connect.c: CIFS VFS: in cifs_put_smb_ses as Xid: 81 with uid: 0
 fs/cifs.ssp/cifssmb.c: In SMBLogoff for session disconnect
 fs/cifs.ssp/transport.c: For smb_command 116
 fs/cifs.ssp/transport.c: Sending smb:  total_len 43
 fs/cifs.ssp/connect.c: rfc1002 length 0x2b
 fs/cifs.ssp/connect.c: CIFS VFS: leaving cifs_mount (xid = 79) rc = -66
 CIFS VFS: cifs_mount failed w/return code = -66

mount -t cifs //cifstest1/dfsroot /mnt/smb_a -o
prefixpath=/linktocifstest4/dir2,user=user,pass=password
mount error 66 = Object is remote
Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)

 fs/cifs.ssp/cifsfs.c: Devname: //cifstest1/dfsroot flags: 64
 fs/cifs.ssp/connect.c: CIFS VFS: in cifs_mount as Xid: 82 with uid: 0
 fs/cifs.ssp/connect.c: prefix path /linktocifstest4/dir2
 fs/cifs.ssp/connect.c: Username: user
 fs/cifs.ssp/connect.c: UNC: \\cifstest1\dfsroot ip: 9.3.uvw.xyz
 fs/cifs.ssp/connect.c: Socket created
 fs/cifs.ssp/connect.c: sndbuf 16384 rcvbuf 87380 rcvtimeo 0x6d6
 fs/cifs.ssp/connect.c: Existing smb sess not found
 fs/cifs.ssp/connect.c: Demultiplex PID: 4047
 CIFS VFS: cifs_mount serverName: 9.3.uvw.xyz
 fs/cifs.ssp/cifssmb.c: secFlags 0x7
 fs/cifs.ssp/transport.c: For smb_command 114
 fs/cifs.ssp/transport.c: Sending smb:  total_len 82
 fs/cifs.ssp/connect.c: rfc1002 length 0x7d
 fs/cifs.ssp/cifssmb.c: Dialect: 2
 fs/cifs.ssp/cifssmb.c: negprot rc 0
 fs/cifs.ssp/connect.c: Security Mode: 0xf Capabilities: 0x1f3fd
TimeAdjust: 21600
 fs/cifs.ssp/sess.c: sess setup type 2
 fs/cifs.ssp/transport.c: For smb_command 115
 fs/cifs.ssp/transport.c: Sending smb:  total_len 262
 fs/cifs.ssp/connect.c: rfc1002 length 0xd1
 fs/cifs.ssp/misc.c: Null buffer passed to cifs_small_buf_release
 fs/cifs.ssp/sess.c: ssetup rc from sendrecv2 is 0
 fs/cifs.ssp/sess.c: UID = 40960
 fs/cifs.ssp/sess.c: bleft 164
 fs/cifs.ssp/sess.c: words left: -1
 fs/cifs.ssp/sess.c: ssetup freeing small buf ffff8801301fd300
 fs/cifs.ssp/connect.c: CIFS Session Established successfully
 fs/cifs.ssp/connect.c: file mode: 0x5f7  dir mode: 0x1ff
 fs/cifs.ssp/transport.c: For smb_command 117
 fs/cifs.ssp/transport.c: Sending smb:  total_len 124
 fs/cifs.ssp/connect.c: rfc1002 length 0x42
 fs/cifs.ssp/connect.c: disk share connection
 fs/cifs.ssp/connect.c: Tcon flags: 0x3
 fs/cifs.ssp/connect.c: CIFS Tcon rc = 0
 fs/cifs.ssp/cifssmb.c: In QFSDeviceInfo
 fs/cifs.ssp/transport.c: For smb_command 50
 fs/cifs.ssp/transport.c: Sending smb:  total_len 72
 fs/cifs.ssp/connect.c: rfc1002 length 0x44
 fs/cifs.ssp/cifssmb.c: In QFSAttributeInfo
 fs/cifs.ssp/transport.c: For smb_command 50
 fs/cifs.ssp/transport.c: Sending smb:  total_len 72
 fs/cifs.ssp/connect.c: rfc1002 length 0x50
 fs/cifs.ssp/transport.c: For smb_command 50
 fs/cifs.ssp/transport.c: Sending smb:  total_len 188
 fs/cifs.ssp/connect.c: rfc1002 length 0x27
 fs/cifs.ssp/connect.c: invalid transact2 word count
Status code returned 0xc0000257 NT_STATUS_PATH_NOT_COVERED
 fs/cifs.ssp/netmisc.c: Mapping smb error code 3 to POSIX err -66
 fs/cifs.ssp/cifssmb.c: Send error in QPathInfo = -66
 CIFS VFS: Path \\cifstest1\dfsroot\linktocifstest4\dir2 in not accessible: -66
 fs/cifs.ssp/connect.c: CIFS VFS: in cifs_put_tcon as Xid: 83 with uid: 0
 fs/cifs.ssp/cifssmb.c: In tree disconnect
 fs/cifs.ssp/transport.c: For smb_command 113
 fs/cifs.ssp/transport.c: Sending smb:  total_len 39
 fs/cifs.ssp/connect.c: rfc1002 length 0x27
 fs/cifs.ssp/connect.c: CIFS VFS: in cifs_put_smb_ses as Xid: 84 with uid: 0
 fs/cifs.ssp/cifssmb.c: In SMBLogoff for session disconnect
 fs/cifs.ssp/transport.c: For smb_command 116
 fs/cifs.ssp/transport.c: Sending smb:  total_len 43
 fs/cifs.ssp/connect.c: rfc1002 length 0x2b
 fs/cifs.ssp/connect.c: CIFS VFS: leaving cifs_mount (xid = 82) rc = -66
 CIFS VFS: cifs_mount failed w/return code = -66

Patch
diff mbox

>From c61a715cbeee404a1bcc2788090b4d453eb43b8e Mon Sep 17 00:00:00 2001
From: Igor Mammedov <niallain@gmail.com>
Date: Tue, 3 Feb 2009 12:43:56 +0300
Subject: [PATCH] [CIFS] Prevent OOPs when mounting with remote prefixpath.
 	Fix OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'.
 	Check if prefixpath in accesible while we are still in cifs_mount
 	and fail with reporting a error if we can't access prefixpath
         (i.e. if prefixpath is located on another server)

Signed-off-by: Igor Mammedov <niallain@gmail.com>
---
 fs/cifs/cifsproto.h |    1 +
 fs/cifs/connect.c   |   30 ++++++++++++++++++++++++++++++
 fs/cifs/inode.c     |    2 +-
 3 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 382ba62..22ff09c 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -42,6 +42,7 @@  extern void _FreeXid(unsigned int);
 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
 extern char *build_path_from_dentry(struct dentry *);
+extern char *build_path_to_root(struct cifs_sb_info *cifs_sb);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 /* extern void renew_parental_timestamps(struct dentry *direntry);*/
 extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2209be9..dcffaa9 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2181,6 +2181,24 @@  static void setup_cifs_sb(struct smb_vol *pvolume_info,
 }
 
 int
+is_path_accessible(int xid, struct cifsTconInfo *tcon,
+		struct cifs_sb_info *cifs_sb,  const char *full_path)
+{
+	int rc;
+	FILE_ALL_INFO *pfindData;
+	pfindData = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+	if (pfindData == NULL)
+		return -ENOMEM;
+
+	rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfindData,
+			0 /* not legacy */,
+			cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+			CIFS_MOUNT_MAP_SPECIAL_CHR);
+	kfree(pfindData);
+	return rc;
+}
+
+int
 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 	   char *mount_data, const char *devname)
 {
@@ -2190,6 +2208,7 @@  cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 	struct cifsSesInfo *pSesInfo = NULL;
 	struct cifsTconInfo *tcon = NULL;
 	struct TCP_Server_Info *srvTcp = NULL;
+	char *full_path;
 
 	xid = GetXid();
 
@@ -2426,6 +2445,17 @@  mount_fail_check:
 		cifs_sb->rsize = min(cifs_sb->rsize,
 			       (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
 
+
+	full_path = build_path_to_root(cifs_sb);
+	if (full_path != NULL) {
+		rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
+		kfree(full_path);
+		if (rc) {
+			cERROR(1, ("Remote DFS root not supported"));
+			goto mount_fail_check;
+		}
+	}
+
 	/* volume_info->password is freed above when existing session found
 	(in which case it is not needed anymore) but when new sesion is created
 	the password ptr is put in the new session structure (in which case the
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index bcf7b51..00c6a3f 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -621,7 +621,7 @@  static const struct inode_operations cifs_ipc_inode_ops = {
 	.lookup = cifs_lookup,
 };
 
-static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
+char *build_path_to_root(struct cifs_sb_info *cifs_sb)
 {
 	int pplen = cifs_sb->prepathlen;
 	int dfsplen;
-- 
1.6.0.2