Re: [linux-cifs-client[[patch] Attempt #2 to handle null nameidata

Jeff Layton <[email protected]>
Newsgroups gmane.linux.file-systems.cifs
Message-ID <[email protected]>
On Wed,  7 Apr 2010 11:19:10 -0500
[email protected] wrote:

> While creating a file on a server which supports unix extensions
> such as Samba, if a file is being created which does not supply
> nameidata (i.e. nd is null), cifs client can oops when calling
> cifs_posix_open.
> 
> Signed-off-by: Shirish Pargaonkar <[email protected]>
> Reported-by: Eugene Teo <[email protected]>
> ---
> 

This patch is hideous, but I suppose it's the best that can be done
short of rewriting this code to have a sane API.

> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 88e2bc4..efb8772 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -95,8 +95,10 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
>  				__u16 fileHandle, struct file *file,
>  				struct vfsmount *mnt, unsigned int oflags);
>  extern int cifs_posix_open(char *full_path, struct inode **pinode,
> -			   struct vfsmount *mnt, int mode, int oflags,
> -			   __u32 *poplock, __u16 *pnetfid, int xid);
> +				struct vfsmount *mnt,
> +				struct super_block *sb,
> +				int mode, int oflags,
> +				__u32 *poplock, __u16 *pnetfid, int xid);
>  extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
>  				     FILE_UNIX_BASIC_INFO *info,
>  				     struct cifs_sb_info *cifs_sb);
> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
> index 6ccf726..9e9d48f 100644
> --- a/fs/cifs/dir.c
> +++ b/fs/cifs/dir.c
> @@ -183,13 +183,14 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
>  }
>  
>  int cifs_posix_open(char *full_path, struct inode **pinode,
> -		    struct vfsmount *mnt, int mode, int oflags,
> -		    __u32 *poplock, __u16 *pnetfid, int xid)
> +			struct vfsmount *mnt, struct super_block *sb,
> +			int mode, int oflags,
> +			__u32 *poplock, __u16 *pnetfid, int xid)
>  {
>  	int rc;
>  	FILE_UNIX_BASIC_INFO *presp_data;
>  	__u32 posix_flags = 0;
> -	struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
> +	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
>  	struct cifs_fattr fattr;
>  
>  	cFYI(1, ("posix open %s", full_path));
> @@ -242,7 +243,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
>  
>  	/* get new inode and set it up */
>  	if (*pinode == NULL) {
> -		*pinode = cifs_iget(mnt->mnt_sb, &fattr);
> +		*pinode = cifs_iget(sb, &fattr);
>  		if (!*pinode) {
>  			rc = -ENOMEM;
>  			goto posix_open_ret;
> @@ -251,7 +252,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
>  		cifs_fattr_to_inode(*pinode, &fattr);
>  	}
>  
> -	cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
> +	if (mnt)
> +		cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
>

The cifs_create codepath closes the file (via CIFSSMBClose) when nd is
NULL. The NULL mnt case here is analogous, right? Shouldn't it also
CIFSSMBClose the file?

>  posix_open_ret:
>  	kfree(presp_data);
> @@ -315,13 +317,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
>  	if (nd && (nd->flags & LOOKUP_OPEN))
>  		oflags = nd->intent.open.flags;
>  	else
> -		oflags = FMODE_READ;
> +		oflags = FMODE_READ | SMB_O_CREAT;
>  
>  	if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
>  	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>  			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
> -		rc = cifs_posix_open(full_path, &newinode, nd->path.mnt,
> -				     mode, oflags, &oplock, &fileHandle, xid);
> +		rc = cifs_posix_open(full_path, &newinode,
> +			nd ? nd->path.mnt : NULL,
> +			inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
>  		/* EIO could indicate that (posix open) operation is not
>  		   supported, despite what server claimed in capability
>  		   negotation.  EREMOTE indicates DFS junction, which is not
> @@ -678,6 +681,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
>  		     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
>  		     (nd->intent.open.flags & O_CREAT)) {
>  			rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
> +					parent_dir_inode->i_sb,
>  					nd->intent.open.create_mode,
>  					nd->intent.open.flags, &oplock,
>  					&fileHandle, xid);
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 3d8f8a9..503a459 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -297,10 +297,12 @@ int cifs_open(struct inode *inode, struct file *file)
>  	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>  			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
>  		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
> +		oflags |= SMB_O_CREAT;
>  		/* can not refresh inode info since size could be stale */
>  		rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
> -				     cifs_sb->mnt_file_mode /* ignored */,
> -				     oflags, &oplock, &netfid, xid);
> +				inode->i_sb,
> +				cifs_sb->mnt_file_mode /* ignored */,
> +				oflags, &oplock, &netfid, xid);
>  		if (rc == 0) {
>  			cFYI(1, ("posix open succeeded"));
>  			/* no need for special case handling of setting mode
> @@ -512,8 +514,9 @@ reopen_error_exit:
>  		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
>  		/* can not refresh inode info since size could be stale */
>  		rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
> -				     cifs_sb->mnt_file_mode /* ignored */,
> -				     oflags, &oplock, &netfid, xid);
> +				inode->i_sb,
> +				cifs_sb->mnt_file_mode /* ignored */,
> +				oflags, &oplock, &netfid, xid);
>  		if (rc == 0) {
>  			cFYI(1, ("posix reopen succeeded"));
>  			goto reopen_success;
> _______________________________________________
> linux-cifs-client mailing list
> [email protected]
> https://lists.samba.org/mailman/listinfo/linux-cifs-client
> 

Ugly, but I suppose it's all that can reasonably be done short of
making all of this code use a more sane API.

-- 
Jeff Layton <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.