lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAH2r5msObxLw_xSCbEY3eySvKWoqD6dRQd9t3BmxbgvnkyodRQ@mail.gmail.com>
Date: Tue, 8 Apr 2025 18:41:07 -0500
From: Steve French <smfrench@...il.com>
To: Pali Rohár <pali@...nel.org>
Cc: Paulo Alcantara <pc@...guebit.com>, linux-cifs@...r.kernel.org, 
	linux-kernel@...r.kernel.org, Tom Talpey <tom@...pey.com>
Subject: Re: [PATCH] cifs: Fix support for WSL-style symlinks

Merged into cifs-2.6.git for-next pending additional review

On Tue, Apr 8, 2025 at 5:34 PM Pali Rohár <pali@...nel.org> wrote:
>
> MS-FSCC in section 2.1.2.7 LX SYMLINK REPARSE_DATA_BUFFER now contains
> documentation about WSL symlink reparse point buffers.
>
> https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/68337353-9153-4ee1-ac6b-419839c3b7ad
>
> Fix the struct reparse_wsl_symlink_data_buffer to reflect buffer fields
> according to the MS-FSCC documentation.
>
> Fix the Linux SMB client to correctly fill the WSL symlink reparse point
> buffer when creaing new WSL-style symlink. There was a mistake during
> filling the data part of the reparse point buffer. It should starts with
> bytes "\x02\x00\x00\x00" (which represents version 2) but this constant was
> written as number 0x02000000 encoded in little endian, which resulted bytes
> "\x00\x00\x00\x02". This change is fixing this mistake.
>
> Fixes: 4e2043be5c14 ("cifs: Add support for creating WSL-style symlinks")
> Signed-off-by: Pali Rohár <pali@...nel.org>
> ---
>  fs/smb/client/reparse.c | 25 ++++++++++++++++---------
>  fs/smb/common/smb2pdu.h |  6 +++---
>  2 files changed, 19 insertions(+), 12 deletions(-)
>
> diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> index 7cefe903edb5..dbd3dd9b678f 100644
> --- a/fs/smb/client/reparse.c
> +++ b/fs/smb/client/reparse.c
> @@ -520,12 +520,12 @@ static int wsl_set_reparse_buf(struct reparse_data_buffer **buf,
>                         kfree(symname_utf16);
>                         return -ENOMEM;
>                 }
> -               /* Flag 0x02000000 is unknown, but all wsl symlinks have this value */
> -               symlink_buf->Flags = cpu_to_le32(0x02000000);
> -               /* PathBuffer is in UTF-8 but without trailing null-term byte */
> +               /* Version field must be set to 2 (MS-FSCC 2.1.2.7) */
> +               symlink_buf->Version = cpu_to_le32(2);
> +               /* Target for Version 2 is in UTF-8 but without trailing null-term byte */
>                 symname_utf8_len = utf16s_to_utf8s((wchar_t *)symname_utf16, symname_utf16_len/2,
>                                                    UTF16_LITTLE_ENDIAN,
> -                                                  symlink_buf->PathBuffer,
> +                                                  symlink_buf->Target,
>                                                    symname_utf8_maxlen);
>                 *buf = (struct reparse_data_buffer *)symlink_buf;
>                 buf_len = sizeof(struct reparse_wsl_symlink_data_buffer) + symname_utf8_len;
> @@ -995,29 +995,36 @@ static int parse_reparse_wsl_symlink(struct reparse_wsl_symlink_data_buffer *buf
>                                      struct cifs_open_info_data *data)
>  {
>         int len = le16_to_cpu(buf->ReparseDataLength);
> +       int data_offset = offsetof(typeof(*buf), Target) - offsetof(typeof(*buf), Version);
>         int symname_utf8_len;
>         __le16 *symname_utf16;
>         int symname_utf16_len;
>
> -       if (len <= sizeof(buf->Flags)) {
> +       if (len <= data_offset) {
>                 cifs_dbg(VFS, "srv returned malformed wsl symlink buffer\n");
>                 return -EIO;
>         }
>
> -       /* PathBuffer is in UTF-8 but without trailing null-term byte */
> -       symname_utf8_len = len - sizeof(buf->Flags);
> +       /* MS-FSCC 2.1.2.7 defines layout of the Target field only for Version 2. */
> +       if (le32_to_cpu(buf->Version) != 2) {
> +               cifs_dbg(VFS, "srv returned unsupported wsl symlink version %u\n", le32_to_cpu(buf->Version));
> +               return -EIO;
> +       }
> +
> +       /* Target for Version 2 is in UTF-8 but without trailing null-term byte */
> +       symname_utf8_len = len - data_offset;
>         /*
>          * Check that buffer does not contain null byte
>          * because Linux cannot process symlink with null byte.
>          */
> -       if (strnlen(buf->PathBuffer, symname_utf8_len) != symname_utf8_len) {
> +       if (strnlen(buf->Target, symname_utf8_len) != symname_utf8_len) {
>                 cifs_dbg(VFS, "srv returned null byte in wsl symlink target location\n");
>                 return -EIO;
>         }
>         symname_utf16 = kzalloc(symname_utf8_len * 2, GFP_KERNEL);
>         if (!symname_utf16)
>                 return -ENOMEM;
> -       symname_utf16_len = utf8s_to_utf16s(buf->PathBuffer, symname_utf8_len,
> +       symname_utf16_len = utf8s_to_utf16s(buf->Target, symname_utf8_len,
>                                             UTF16_LITTLE_ENDIAN,
>                                             (wchar_t *) symname_utf16, symname_utf8_len * 2);
>         if (symname_utf16_len < 0) {
> diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h
> index 764dca80c15c..f79a5165a7cc 100644
> --- a/fs/smb/common/smb2pdu.h
> +++ b/fs/smb/common/smb2pdu.h
> @@ -1567,13 +1567,13 @@ struct reparse_nfs_data_buffer {
>         __u8    DataBuffer[];
>  } __packed;
>
> -/* For IO_REPARSE_TAG_LX_SYMLINK */
> +/* For IO_REPARSE_TAG_LX_SYMLINK - see MS-FSCC 2.1.2.7 */
>  struct reparse_wsl_symlink_data_buffer {
>         __le32  ReparseTag;
>         __le16  ReparseDataLength;
>         __u16   Reserved;
> -       __le32  Flags;
> -       __u8    PathBuffer[]; /* Variable Length UTF-8 string without nul-term */
> +       __le32  Version; /* Always 2 */
> +       __u8    Target[]; /* Variable Length UTF-8 string without nul-term */
>  } __packed;
>
>  struct validate_negotiate_info_req {
> --
> 2.20.1
>
>


-- 
Thanks,

Steve

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ