diff mbox series

cifs: sanitize paths in cifs_update_super_prepath.

Message ID 20230404185908.993738-1-tbecker@redhat.com
State New
Headers show
Series cifs: sanitize paths in cifs_update_super_prepath. | expand

Commit Message

Thiago Becker April 4, 2023, 6:59 p.m. UTC
After a server reboot, clients are failing to move files with ENOENT.
This is caused by DFS referrals containing multiple separators, which
the server move call doesn't recognize.

BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=2182472
Fixes: a31080899d5f ("cifs: sanitize multiple delimiters in prepath")
Actually-Fixes: 24e0a1eff9e2 ("cifs: switch to new mount api")
Signed-off-by: Thiago Rafael Becker <tbecker@redhat.com>
---
 fs/cifs/fs_context.c | 6 +++---
 fs/cifs/misc.c       | 4 +++-
 2 files changed, 6 insertions(+), 4 deletions(-)

Comments

Paulo Alcantara April 4, 2023, 7:54 p.m. UTC | #1
Thiago Becker <tbecker@redhat.com> writes:

> After a server reboot, clients are failing to move files with ENOENT.
> This is caused by DFS referrals containing multiple separators, which
> the server move call doesn't recognize.
>
> BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=2182472
> Fixes: a31080899d5f ("cifs: sanitize multiple delimiters in prepath")
> Actually-Fixes: 24e0a1eff9e2 ("cifs: switch to new mount api")
> Signed-off-by: Thiago Rafael Becker <tbecker@redhat.com>
> ---
>  fs/cifs/fs_context.c | 6 +++---
>  fs/cifs/misc.c       | 4 +++-
>  2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c
> index 6d13f8207e96a..c4d9139b89d29 100644
> --- a/fs/cifs/fs_context.c
> +++ b/fs/cifs/fs_context.c
> @@ -445,7 +445,7 @@ int smb3_parse_opt(const char *options, const char *key, char **val)
>   * cleaning up the original.
>   */
>  #define IS_DELIM(c) ((c) == '/' || (c) == '\\')
> -static char *sanitize_path(char *path)
> +char *sanitize_path(char *path, gfp_t gfp)

Could you please add a {cifs,smb3}_ prefix to it?

>  {
>  	char *cursor1 = path, *cursor2 = path;
>  
> @@ -469,7 +469,7 @@ static char *sanitize_path(char *path)
>  		cursor2--;
>  
>  	*(cursor2) = '\0';
> -	return kstrdup(path, GFP_KERNEL);
> +	return kstrdup(path, gfp);
>  }
>  
>  /*
> @@ -531,7 +531,7 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
>  	if (!*pos)
>  		return 0;
>  
> -	ctx->prepath = sanitize_path(pos);
> +	ctx->prepath = sanitize_path(pos, GFP_KERNEL);
>  	if (!ctx->prepath)
>  		return -ENOMEM;
>  
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index b44fb51968bfb..e6f208110de83 100644
> --- a/fs/cifs/misc.c
> +++ b/fs/cifs/misc.c
> @@ -1190,12 +1190,14 @@ int match_target_ip(struct TCP_Server_Info *server,
>  	return 0;
>  }
>  
> +extern char *sanitize_path(char *path, gfp_t gfp);

Please do the above in fs/cifs/fs_context.h.

Otherwise, looks good to me.

Reviewed-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
kernel test robot April 4, 2023, 9:34 p.m. UTC | #2
Hi Thiago,

kernel test robot noticed the following build warnings:

[auto build test WARNING on cifs/for-next]
[also build test WARNING on linus/master v6.3-rc5 next-20230404]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Thiago-Becker/cifs-sanitize-paths-in-cifs_update_super_prepath/20230405-030114
base:   git://git.samba.org/sfrench/cifs-2.6.git for-next
patch link:    https://lore.kernel.org/r/20230404185908.993738-1-tbecker%40redhat.com
patch subject: [PATCH] cifs: sanitize paths in cifs_update_super_prepath.
config: s390-allyesconfig (https://download.01.org/0day-ci/archive/20230405/202304050514.TB9sze0P-lkp@intel.com/config)
compiler: s390-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/4d179c3f90c01aab96bf6a02f70cc111da39d61c
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Thiago-Becker/cifs-sanitize-paths-in-cifs_update_super_prepath/20230405-030114
        git checkout 4d179c3f90c01aab96bf6a02f70cc111da39d61c
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=s390 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=s390 SHELL=/bin/bash fs/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304050514.TB9sze0P-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> fs/cifs/fs_context.c:448:7: warning: no previous prototype for 'sanitize_path' [-Wmissing-prototypes]
     448 | char *sanitize_path(char *path, gfp_t gfp)
         |       ^~~~~~~~~~~~~


vim +/sanitize_path +448 fs/cifs/fs_context.c

   438	
   439	/*
   440	 * Remove duplicate path delimiters. Windows is supposed to do that
   441	 * but there are some bugs that prevent rename from working if there are
   442	 * multiple delimiters.
   443	 *
   444	 * Returns a sanitized duplicate of @path. The caller is responsible for
   445	 * cleaning up the original.
   446	 */
   447	#define IS_DELIM(c) ((c) == '/' || (c) == '\\')
 > 448	char *sanitize_path(char *path, gfp_t gfp)
   449	{
   450		char *cursor1 = path, *cursor2 = path;
   451	
   452		/* skip all prepended delimiters */
   453		while (IS_DELIM(*cursor1))
   454			cursor1++;
   455	
   456		/* copy the first letter */
   457		*cursor2 = *cursor1;
   458	
   459		/* copy the remainder... */
   460		while (*(cursor1++)) {
   461			/* ... skipping all duplicated delimiters */
   462			if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2))
   463				continue;
   464			*(++cursor2) = *cursor1;
   465		}
   466	
   467		/* if the last character is a delimiter, skip it */
   468		if (IS_DELIM(*(cursor2 - 1)))
   469			cursor2--;
   470	
   471		*(cursor2) = '\0';
   472		return kstrdup(path, gfp);
   473	}
   474
kernel test robot April 4, 2023, 10:26 p.m. UTC | #3
Hi Thiago,

kernel test robot noticed the following build warnings:

[auto build test WARNING on cifs/for-next]
[also build test WARNING on linus/master v6.3-rc5 next-20230404]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Thiago-Becker/cifs-sanitize-paths-in-cifs_update_super_prepath/20230405-030114
base:   git://git.samba.org/sfrench/cifs-2.6.git for-next
patch link:    https://lore.kernel.org/r/20230404185908.993738-1-tbecker%40redhat.com
patch subject: [PATCH] cifs: sanitize paths in cifs_update_super_prepath.
config: x86_64-randconfig-a003-20230403 (https://download.01.org/0day-ci/archive/20230405/202304050627.7O0sKgk8-lkp@intel.com/config)
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/4d179c3f90c01aab96bf6a02f70cc111da39d61c
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Thiago-Becker/cifs-sanitize-paths-in-cifs_update_super_prepath/20230405-030114
        git checkout 4d179c3f90c01aab96bf6a02f70cc111da39d61c
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash fs/cifs/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304050627.7O0sKgk8-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> fs/cifs/fs_context.c:448:7: warning: no previous prototype for function 'sanitize_path' [-Wmissing-prototypes]
   char *sanitize_path(char *path, gfp_t gfp)
         ^
   fs/cifs/fs_context.c:448:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   char *sanitize_path(char *path, gfp_t gfp)
   ^
   static 
   1 warning generated.


vim +/sanitize_path +448 fs/cifs/fs_context.c

   438	
   439	/*
   440	 * Remove duplicate path delimiters. Windows is supposed to do that
   441	 * but there are some bugs that prevent rename from working if there are
   442	 * multiple delimiters.
   443	 *
   444	 * Returns a sanitized duplicate of @path. The caller is responsible for
   445	 * cleaning up the original.
   446	 */
   447	#define IS_DELIM(c) ((c) == '/' || (c) == '\\')
 > 448	char *sanitize_path(char *path, gfp_t gfp)
   449	{
   450		char *cursor1 = path, *cursor2 = path;
   451	
   452		/* skip all prepended delimiters */
   453		while (IS_DELIM(*cursor1))
   454			cursor1++;
   455	
   456		/* copy the first letter */
   457		*cursor2 = *cursor1;
   458	
   459		/* copy the remainder... */
   460		while (*(cursor1++)) {
   461			/* ... skipping all duplicated delimiters */
   462			if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2))
   463				continue;
   464			*(++cursor2) = *cursor1;
   465		}
   466	
   467		/* if the last character is a delimiter, skip it */
   468		if (IS_DELIM(*(cursor2 - 1)))
   469			cursor2--;
   470	
   471		*(cursor2) = '\0';
   472		return kstrdup(path, gfp);
   473	}
   474
diff mbox series

Patch

diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c
index 6d13f8207e96a..c4d9139b89d29 100644
--- a/fs/cifs/fs_context.c
+++ b/fs/cifs/fs_context.c
@@ -445,7 +445,7 @@  int smb3_parse_opt(const char *options, const char *key, char **val)
  * cleaning up the original.
  */
 #define IS_DELIM(c) ((c) == '/' || (c) == '\\')
-static char *sanitize_path(char *path)
+char *sanitize_path(char *path, gfp_t gfp)
 {
 	char *cursor1 = path, *cursor2 = path;
 
@@ -469,7 +469,7 @@  static char *sanitize_path(char *path)
 		cursor2--;
 
 	*(cursor2) = '\0';
-	return kstrdup(path, GFP_KERNEL);
+	return kstrdup(path, gfp);
 }
 
 /*
@@ -531,7 +531,7 @@  smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
 	if (!*pos)
 		return 0;
 
-	ctx->prepath = sanitize_path(pos);
+	ctx->prepath = sanitize_path(pos, GFP_KERNEL);
 	if (!ctx->prepath)
 		return -ENOMEM;
 
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index b44fb51968bfb..e6f208110de83 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1190,12 +1190,14 @@  int match_target_ip(struct TCP_Server_Info *server,
 	return 0;
 }
 
+extern char *sanitize_path(char *path, gfp_t gfp);
+
 int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
 {
 	kfree(cifs_sb->prepath);
 
 	if (prefix && *prefix) {
-		cifs_sb->prepath = kstrdup(prefix, GFP_ATOMIC);
+		cifs_sb->prepath = sanitize_path(prefix, GFP_ATOMIC);
 		if (!cifs_sb->prepath)
 			return -ENOMEM;