Message ID | YeHUxJ9zTVNrKveF@himera.home (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2,1/2] cifs: alloc_path_with_tree_prefix: do not append sep. if the path is empty | expand |
tentatively merged into cifs-2.6.git for-next pending more testing On Fri, Jan 14, 2022 at 5:04 PM Eugene Korenevsky <ekorenevsky@astralinux.ru> wrote: > > Windows SMB server responds with STATUS_OBJECT_NAME_INVALID code to > SMB2 QUERY_INFO request for "\<server>\<dfsname>\<linkpath>" DFS reference, > where <dfsname> contains non-ASCII unicode symbols. > > Check such DFS reference and emulate -EREMOTE if it is actual. > > BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=215440 > Signed-off-by: Eugene Korenevsky <ekorenevsky@astralinux.ru> > --- > v2: No changes, this is a new patch in the patchset for #215440 fix > > fs/cifs/cifsproto.h | 5 +++++ > fs/cifs/connect.c | 5 +++++ > fs/cifs/inode.c | 6 ++++++ > fs/cifs/misc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 65 insertions(+) > > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h > index 4f5a3e857df4..b3a9cc0def2c 100644 > --- a/fs/cifs/cifsproto.h > +++ b/fs/cifs/cifsproto.h > @@ -626,6 +626,11 @@ static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, > int match_target_ip(struct TCP_Server_Info *server, > const char *share, size_t share_len, > bool *result); > + > +int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid, > + struct cifs_tcon *tcon, > + struct cifs_sb_info *cifs_sb, > + const char *dfs_link_path); > #endif > > static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > index 1060164b984a..db0f8a1c8fb5 100644 > --- a/fs/cifs/connect.c > +++ b/fs/cifs/connect.c > @@ -3322,6 +3322,11 @@ static int is_path_remote(struct mount_ctx *mnt_ctx) > > rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, > full_path); > +#ifdef CONFIG_CIFS_DFS_UPCALL > + if (rc == -ENOENT && is_tcon_dfs(tcon)) > + rc = cifs_dfs_query_info_nonascii_quirk(xid, tcon, cifs_sb, > + full_path); > +#endif > if (rc != 0 && rc != -EREMOTE) { > kfree(full_path); > return rc; > diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c > index 279622e4eb1c..baa197edd8c5 100644 > --- a/fs/cifs/inode.c > +++ b/fs/cifs/inode.c > @@ -952,6 +952,12 @@ cifs_get_inode_info(struct inode **inode, > rc = server->ops->query_path_info(xid, tcon, cifs_sb, > full_path, tmp_data, > &adjust_tz, &is_reparse_point); > +#ifdef CONFIG_CIFS_DFS_UPCALL > + if (rc == -ENOENT && is_tcon_dfs(tcon)) > + rc = cifs_dfs_query_info_nonascii_quirk(xid, tcon, > + cifs_sb, > + full_path); > +#endif > data = tmp_data; > } > > diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c > index 5148d48d6a35..56598f7dbe00 100644 > --- a/fs/cifs/misc.c > +++ b/fs/cifs/misc.c > @@ -1302,4 +1302,53 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix) > cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; > return 0; > } > + > +/** cifs_dfs_query_info_nonascii_quirk > + * Handle weird Windows SMB server behaviour. It responds with > + * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request > + * for "\<server>\<dfsname>\<linkpath>" DFS reference, > + * where <dfsname> contains non-ASCII unicode symbols. > + * > + * Check such DFS reference and emulate -ENOENT if it is actual. > + */ > +int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid, > + struct cifs_tcon *tcon, > + struct cifs_sb_info *cifs_sb, > + const char *linkpath) > +{ > + char *treename, *dfspath, sep; > + int treenamelen, linkpathlen, rc; > + > + treename = tcon->treeName; > + /* MS-DFSC: All paths in REQ_GET_DFS_REFERRAL and RESP_GET_DFS_REFERRAL > + * messages MUST be encoded with exactly one leading backslash, not two > + * leading backslashes. > + */ > + sep = CIFS_DIR_SEP(cifs_sb); > + if (treename[0] == sep && treename[1] == sep) > + treename++; > + linkpathlen = strlen(linkpath); > + treenamelen = strnlen(treename, MAX_TREE_SIZE + 1); > + dfspath = kzalloc(treenamelen + linkpathlen + 1, GFP_KERNEL); > + if (!dfspath) > + return -ENOMEM; > + if (treenamelen) > + memcpy(dfspath, treename, treenamelen); > + memcpy(dfspath + treenamelen, linkpath, linkpathlen); > + rc = dfs_cache_find(xid, tcon->ses, cifs_sb->local_nls, > + cifs_remap(cifs_sb), dfspath, NULL, NULL); > + if (rc == 0) { > + cifs_dbg(FYI, "DFS ref '%s' is found, emulate -EREMOTE\n", > + dfspath); > + rc = -EREMOTE; > + } else if (rc == -EEXIST) { > + cifs_dbg(FYI, "DFS ref '%s' is not found, emulate -ENOENT\n", > + dfspath); > + rc = -ENOENT; > + } else { > + cifs_dbg(FYI, "%s: dfs_cache_find returned %d\n", __func__, rc); > + } > + kfree(dfspath); > + return rc; > +} > #endif > -- > 2.30.2 >
On 01/14, Eugene Korenevsky wrote: >Windows SMB server responds with STATUS_OBJECT_NAME_INVALID code to >SMB2 QUERY_INFO request for "\<server>\<dfsname>\<linkpath>" DFS reference, >where <dfsname> contains non-ASCII unicode symbols. > >Check such DFS reference and emulate -EREMOTE if it is actual. > >BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=215440 >Signed-off-by: Eugene Korenevsky <ekorenevsky@astralinux.ru> The patch fixes the initial issue (mount and listing files) as per reported in the mentioned bugzilla, but it still fails to create files: % echo "test" | sudo tee myfile tee: myfile: No such file or directory test % dmesg ... [20510.826644] CIFS: fs/cifs/dfs_cache.c: cache_refresh_path: search path: \w19-addc.mori.test\дфс\test [20510.826653] CIFS: fs/cifs/dfs_cache.c: get_dfs_referral: get an DFS referral for \w19-addc.mori.test\дфс\test [45/504] [20510.826658] CIFS: fs/cifs/smb2ops.c: smb2_get_dfs_refer: path: \w19-addc.mori.test\дфс\test [20510.826665] CIFS: fs/cifs/smb2pdu.c: SMB2 IOCTL [20510.826670] CIFS: fs/cifs/transport.c: wait_for_free_credits: remove 1 credits total=577 [20510.826690] CIFS: fs/cifs/transport.c: Sending smb: smb_len=184 [20510.828315] CIFS: fs/cifs/connect.c: RFC1002 header 0x12a [20510.828331] CIFS: fs/cifs/smb2misc.c: SMB2 data length 186 offset 112 [20510.828336] CIFS: fs/cifs/smb2misc.c: SMB2 len 298 [20510.828342] CIFS: fs/cifs/smb2ops.c: smb2_add_credits: added 10 credits total=587 [20510.828364] CIFS: fs/cifs/transport.c: cifs_sync_mid_result: cmd=11 mid=41 state=4 [20510.828397] CIFS: fs/cifs/misc.c: Null buffer passed to cifs_small_buf_release [20510.828406] CIFS: fs/cifs/misc.c: num_referrals: 1 dfs flags: 0x3 ... [20510.828432] CIFS: fs/cifs/misc.c: DFS ref '\w19-addc.mori.test\дфс\test' is not found, emulate -ENOENT ... Cheers, Enzo
On Mon, Jan 17, 2022 at 06:14:05PM -0300, Enzo Matsumiya wrote: > The patch fixes the initial issue (mount and listing files) as per > reported in the mentioned bugzilla, but it still fails to create files: > > % echo "test" | sudo tee myfile > tee: myfile: No such file or directory > test Sorry, cannot reproduce. ``` # mount ... //192.168.57.14/дфс on /tmp/x type cifs (rw,relatime,vers=default,cache=strict,username=user,domain=WIN-TCIN4O86A6M,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.57.14,file_mode=0755,dir_mode=0755,soft,nounix,mapposix,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1) //WIN-TCIN4O86A6M/дфс/temp on /tmp/x/temp type cifs (rw,relatime,vers=3.1.1,cache=strict,username=user,domain=WIN-TCIN4O86A6M,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.57.4,file_mode=0755,dir_mode=0755,soft,nounix,mapposix,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1) # pwd /tmp/x/temp # echo test | tee myfile test # rm myfile # echo test | tee myfile test # cat myfile test # rm myfile && echo ok ok ``` Could you provide your 'mount' output as well? -- Eugene
we can do a followon to this if you find any problems with it later in the week. On Thu, Jan 20, 2022 at 1:16 PM Eugene Korenevsky <ekorenevsky@astralinux.ru> wrote: > > On Mon, Jan 17, 2022 at 06:14:05PM -0300, Enzo Matsumiya wrote: > > > The patch fixes the initial issue (mount and listing files) as per > > reported in the mentioned bugzilla, but it still fails to create files: > > > > % echo "test" | sudo tee myfile > > tee: myfile: No such file or directory > > test > > > Sorry, cannot reproduce. > > ``` > # mount > ... > //192.168.57.14/дфс on /tmp/x type cifs (rw,relatime,vers=default,cache=strict,username=user,domain=WIN-TCIN4O86A6M,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.57.14,file_mode=0755,dir_mode=0755,soft,nounix,mapposix,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1) > //WIN-TCIN4O86A6M/дфс/temp on /tmp/x/temp type cifs (rw,relatime,vers=3.1.1,cache=strict,username=user,domain=WIN-TCIN4O86A6M,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.57.4,file_mode=0755,dir_mode=0755,soft,nounix,mapposix,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1) > # pwd > /tmp/x/temp > # echo test | tee myfile > test > # rm myfile > # echo test | tee myfile > test > # cat myfile > test > # rm myfile && echo ok > ok > ``` > > Could you provide your 'mount' output as well? > > > -- > Eugene
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 4f5a3e857df4..b3a9cc0def2c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -626,6 +626,11 @@ static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, int match_target_ip(struct TCP_Server_Info *server, const char *share, size_t share_len, bool *result); + +int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid, + struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, + const char *dfs_link_path); #endif static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 1060164b984a..db0f8a1c8fb5 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3322,6 +3322,11 @@ static int is_path_remote(struct mount_ctx *mnt_ctx) rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, full_path); +#ifdef CONFIG_CIFS_DFS_UPCALL + if (rc == -ENOENT && is_tcon_dfs(tcon)) + rc = cifs_dfs_query_info_nonascii_quirk(xid, tcon, cifs_sb, + full_path); +#endif if (rc != 0 && rc != -EREMOTE) { kfree(full_path); return rc; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 279622e4eb1c..baa197edd8c5 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -952,6 +952,12 @@ cifs_get_inode_info(struct inode **inode, rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, tmp_data, &adjust_tz, &is_reparse_point); +#ifdef CONFIG_CIFS_DFS_UPCALL + if (rc == -ENOENT && is_tcon_dfs(tcon)) + rc = cifs_dfs_query_info_nonascii_quirk(xid, tcon, + cifs_sb, + full_path); +#endif data = tmp_data; } diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 5148d48d6a35..56598f7dbe00 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1302,4 +1302,53 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; return 0; } + +/** cifs_dfs_query_info_nonascii_quirk + * Handle weird Windows SMB server behaviour. It responds with + * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request + * for "\<server>\<dfsname>\<linkpath>" DFS reference, + * where <dfsname> contains non-ASCII unicode symbols. + * + * Check such DFS reference and emulate -ENOENT if it is actual. + */ +int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid, + struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, + const char *linkpath) +{ + char *treename, *dfspath, sep; + int treenamelen, linkpathlen, rc; + + treename = tcon->treeName; + /* MS-DFSC: All paths in REQ_GET_DFS_REFERRAL and RESP_GET_DFS_REFERRAL + * messages MUST be encoded with exactly one leading backslash, not two + * leading backslashes. + */ + sep = CIFS_DIR_SEP(cifs_sb); + if (treename[0] == sep && treename[1] == sep) + treename++; + linkpathlen = strlen(linkpath); + treenamelen = strnlen(treename, MAX_TREE_SIZE + 1); + dfspath = kzalloc(treenamelen + linkpathlen + 1, GFP_KERNEL); + if (!dfspath) + return -ENOMEM; + if (treenamelen) + memcpy(dfspath, treename, treenamelen); + memcpy(dfspath + treenamelen, linkpath, linkpathlen); + rc = dfs_cache_find(xid, tcon->ses, cifs_sb->local_nls, + cifs_remap(cifs_sb), dfspath, NULL, NULL); + if (rc == 0) { + cifs_dbg(FYI, "DFS ref '%s' is found, emulate -EREMOTE\n", + dfspath); + rc = -EREMOTE; + } else if (rc == -EEXIST) { + cifs_dbg(FYI, "DFS ref '%s' is not found, emulate -ENOENT\n", + dfspath); + rc = -ENOENT; + } else { + cifs_dbg(FYI, "%s: dfs_cache_find returned %d\n", __func__, rc); + } + kfree(dfspath); + return rc; +} #endif
Windows SMB server responds with STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request for "\<server>\<dfsname>\<linkpath>" DFS reference, where <dfsname> contains non-ASCII unicode symbols. Check such DFS reference and emulate -EREMOTE if it is actual. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=215440 Signed-off-by: Eugene Korenevsky <ekorenevsky@astralinux.ru> --- v2: No changes, this is a new patch in the patchset for #215440 fix fs/cifs/cifsproto.h | 5 +++++ fs/cifs/connect.c | 5 +++++ fs/cifs/inode.c | 6 ++++++ fs/cifs/misc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+)