From patchwork Sat Feb 27 08:12:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 12107589 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23E4DC433E0 for ; Sat, 27 Feb 2021 08:14:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D50EF64EBC for ; Sat, 27 Feb 2021 08:14:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229946AbhB0INp (ORCPT ); Sat, 27 Feb 2021 03:13:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52694 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229864AbhB0INl (ORCPT ); Sat, 27 Feb 2021 03:13:41 -0500 Received: from mail-lf1-x12c.google.com (mail-lf1-x12c.google.com [IPv6:2a00:1450:4864:20::12c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 36356C06174A for ; Sat, 27 Feb 2021 00:13:01 -0800 (PST) Received: by mail-lf1-x12c.google.com with SMTP id d3so17378078lfg.10 for ; Sat, 27 Feb 2021 00:13:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to:cc; bh=l8yjvGadR6AoGzW9i4/uTXyz661ic6d+j5Ldu1HCuds=; b=OnYugKGDM0RLYnu+I/25bMGLduJ9QDI+biLi4w/6adnpaQoUpF8ixfZnEmbsClWMgu 23LPW4/JSDLnXqgclcAs0JGn0U5QsfKo45LL1wcPQ45agPZ3Lw73Co4UfYGRO5ziaZLQ lw9Z6upWWyK0ZDtDoCk5YuLJfvxkZhLRo3RYDyf9mGpCXba/iX00EJD2ty5egOD0Ibf7 XYjgHgp9xPgMKfTMFduYoOts6eCp4QNrKS3Cc2hzhfObE4d5mOxvaexf0qeNQBraWcmd GW7xNrm5Iqasq7sLC6/ycXdasA2vhDD4HmA8+n6VMNBsGdnALmXHFrkS0QHwosL+TPe0 whfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=l8yjvGadR6AoGzW9i4/uTXyz661ic6d+j5Ldu1HCuds=; b=JWKLxdTRMXchDoTf/y8xrF0Pmh3Rwz0S6V6nP2zlwTeyRGssfxja2DlTVxYrEoKx1R YtekgsQ72c7+SwEH6r12+4/dRCYnvMenlDRUtByaSUTuarbVM97fV1GiHCaSV/gANT+C rjZSNvi2V5jN5oeWmJMLgbBcI6c3riz0nHtOhjdZwNuzkuhAuciPx9vpft1mxuodyIxh Ce4uu4K0jpm34U2P8udcXLrzqgkofz/zQcrK+u/8eIeMv9RA1dzZ145fJ6T/wd/V1ra3 k9X88REEFqWmTLPPGHlg/h2Q/zMhSZ4kzJJsWFwl/XQBE+hmllLjT01zhINbRpXi8Ssu WlNg== X-Gm-Message-State: AOAM5302hA35Yb+5L4EUq7kt9MNQSgXLCLZRE/55bwbHXPfdozsbenO9 dbmcjrPGulfs/gcoQvDdDPl/1UrhhIIueKZbnHgml/NelF9zPA== X-Google-Smtp-Source: ABdhPJweb+JzmXLy77fKd/uSI9f4ijtjm+z4rac+E7/gDv0r+zvUwI/JjsEBUrO/VZVDBKc44XvrOmo9L2LplyHFjCA= X-Received: by 2002:a05:6512:31c1:: with SMTP id j1mr3983739lfe.313.1614413579440; Sat, 27 Feb 2021 00:12:59 -0800 (PST) MIME-Version: 1.0 From: Steve French Date: Sat, 27 Feb 2021 02:12:48 -0600 Message-ID: Subject: [PATCH v2] smb3: allow files to be created with backslash in name To: CIFS Cc: Xiaoli Feng , ronnie sahlberg Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Backslash is reserved in Windows (and SMB2/SMB3 by default) but allowed in POSIX so must be remapped when POSIX extensions are not enabled. The default mapping for SMB3 mounts ("SFM") allows mapping backslash (ie 0x5C in UTF8) to 0xF026 in UCS-2 (using the Unicode remapping range reserved for these characters), but this was not mapped by cifs.ko (unlike asterisk, greater than, question mark etc). This patch fixes that to allow creating files and directories with backslash in the file or directory name. Before this patch: touch "/mnt2/subdir/filewith\slash" would return touch: setting times of '/mnt2/subdir/filewith\slash': Invalid argument With the patch tReported-by: Xiaoli Feng ouch and mkdir with the backslash in the name works. Version two of the patch works with files in subdirectories not just the root of the share. This problem was found while debugging xfstest generic/453 https://bugzilla.kernel.org/show_bug.cgi?id=210961 Reported-by: Xiaoli Feng --- Thanks, Steve From 95c5d0607a54f02551bdd9ecc7f41b1d35b19211 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 27 Feb 2021 02:01:46 -0600 Subject: [PATCH] smb3: allow files to be created with backslash in name Backslash is reserved in Windows (and SMB2/SMB3 by default) but allowed in POSIX so must be remapped when POSIX extensions are not enabled. The default mapping for SMB3 mounts ("SFM") allows mapping backslash (ie 0x5C in UTF8) to 0xF026 in UCS-2 (using the Unicode remapping range reserved for these characters), but this was not mapped by cifs.ko (unlike asterisk, greater than, question mark etc). This patch fixes that to allow creating files and directories with backslash in the file or directory name. Before this patch: touch "/mnt2/filewith\slash" would return touch: setting times of '/mnt2/filewith\slash': Invalid argument With the patch touch and mkdir with the backslash in the name works. This problem was found while debugging xfstest generic/453 https://bugzilla.kernel.org/show_bug.cgi?id=210961 Reported-by: Xiaoli Feng Signed-off-by: Steve French --- fs/cifs/cifs_unicode.c | 15 ++++++++++----- fs/cifs/cifs_unicode.h | 3 +++ fs/cifs/cifsglob.h | 5 +---- fs/cifs/dir.c | 18 ++++++++++++------ fs/cifs/misc.c | 2 +- fs/cifs/smb2misc.c | 18 +++++++++++------- 6 files changed, 38 insertions(+), 23 deletions(-) diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 9bd03a231032..4898b1553796 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -98,6 +98,9 @@ convert_sfm_char(const __u16 src_char, char *target) case SFM_PERIOD: *target = '.'; break; + case SFM_SLASH: + *target = '\\'; + break; default: return false; } @@ -431,6 +434,9 @@ static __le16 convert_to_sfm_char(char src_char, bool end_of_string) case '|': dest_char = cpu_to_le16(SFM_PIPE); break; + case '\\': + dest_char = cpu_to_le16(SFM_SLASH); + break; case '.': if (end_of_string) dest_char = cpu_to_le16(SFM_PERIOD); @@ -443,6 +449,9 @@ static __le16 convert_to_sfm_char(char src_char, bool end_of_string) else dest_char = 0; break; + case '/': + dest_char = cpu_to_le16(UCS2_SLASH); + break; default: dest_char = 0; } @@ -502,11 +511,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, dst_char = convert_to_sfm_char(src_char, end_of_string); } else dst_char = 0; - /* - * FIXME: We can not handle remapping backslash (UNI_SLASH) - * until all the calls to build_path_from_dentry are modified, - * as they use backslash as separator. - */ + if (dst_char == 0) { charlen = cp->char2uni(source + i, srclen - i, &tmp); dst_char = cpu_to_le16(tmp); diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index 80b3d845419f..8cd58c71cbb6 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h @@ -24,6 +24,9 @@ #define UNIUPR_NOLOWER /* Example to not expand lower case tables */ +/* Unicode encoding of backslash character */ +#define UCS2_SLASH 0x005C + /* * Windows maps these to the user defined 16 bit Unicode range since they are * reserved symbols (along with \ and /), otherwise illegal to store diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 3de3c5908a72..95bd980ec849 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1430,10 +1430,7 @@ CIFS_FILE_SB(struct file *file) static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) - return '/'; - else - return '\\'; + return '/'; } static inline void diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 97ac363b5df1..bba0fa1c118b 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -209,12 +209,18 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon) le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength))) return -ENAMETOOLONG; - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) { - for (i = 0; i < direntry->d_name.len; i++) { - if (direntry->d_name.name[i] == '\\') { - cifs_dbg(FYI, "Invalid file name\n"); - return -EINVAL; - } + /* + * SMB3.1.1 POSIX Extensions, CIFS Unix Extensions and SFM mappings + * allow \ in paths (or in latter case remaps \ to 0xF026) + */ + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) || + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)) + return 0; + + for (i = 0; i < direntry->d_name.len; i++) { + if (direntry->d_name.name[i] == '\\') { + cifs_dbg(FYI, "Invalid file name\n"); + return -EINVAL; } } return 0; diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 82e176720ca6..9361644f7310 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1186,7 +1186,7 @@ int update_super_prepath(struct cifs_tcon *tcon, char *prefix) goto out; } - convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); + convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); /* BB Check this */ } else cifs_sb->prepath = NULL; diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 60d4bd1eae2b..ce4f00069653 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -476,13 +476,17 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb) if (from[0] == '\\') start_of_path = from + 1; - /* SMB311 POSIX extensions paths do not include leading slash */ - else if (cifs_sb_master_tlink(cifs_sb) && - cifs_sb_master_tcon(cifs_sb)->posix_extensions && - (from[0] == '/')) { - start_of_path = from + 1; - } else - start_of_path = from; + start_of_path = from; + /* + * Only old CIFS Unix extensions paths include leading slash + * Need to skip if for SMB3.1.1 POSIX Extensions and SMB1/2/3 + */ + if (from[0] == '/') { + if (((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == false) || + (cifs_sb_master_tlink(cifs_sb) && + (cifs_sb_master_tcon(cifs_sb)->posix_extensions))) + start_of_path = from + 1; + } to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len, cifs_sb->local_nls, map_type); -- 2.27.0