[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAH2r5mtLoAsZfHHe33=WfDjLZ1PNgV-SgcN1F-o0g1XXLsoAng@mail.gmail.com>
Date: Mon, 25 Nov 2024 15:24:03 -0600
From: Steve French <smfrench@...il.com>
To: Pali Rohár <pali@...nel.org>
Cc: Steve French <sfrench@...ba.org>, Paulo Alcantara <pc@...guebit.com>,
Ronnie Sahlberg <ronniesahlberg@...il.com>, linux-cifs@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH] cifs: Add support for parsing WSL-style symlinks
This patch
commit 06a7adf318a30bdcfa1222ed6d2640e6bb266d7b
Author: Pali Rohár <pali@...nel.org>
Date: Sat Sep 28 13:21:24 2024 +0200
cifs: Add support for parsing WSL-style symlinks
led to compile warning:
CC [M] fs/smb/client/reparse.o
CHECK fs/smb/client/reparse.c
fs/smb/client/reparse.c:679:45: warning: incorrect type in argument 4
(different base types)
fs/smb/client/reparse.c:679:45: expected unsigned short [usertype] *pwcs
fs/smb/client/reparse.c:679:45: got restricted __le16 [usertype]
*[assigned] symname_utf16
Let me know if updated version needed
On Sun, Oct 6, 2024 at 4:07 AM Pali Rohár <pali@...nel.org> wrote:
>
> Linux CIFS client currently does not implement readlink() for WSL-style
> symlinks. It is only able to detect that file is of WSL-style symlink, but
> is not able to read target symlink location.
>
> Add this missing functionality and implement support for parsing content of
> WSL-style symlink.
>
> The important note is that symlink target location stored for WSL symlink
> reparse point (IO_REPARSE_TAG_LX_SYMLINK) is in UTF-8 encoding instead of
> UTF-16 (which is used in whole SMB protocol and also in all other symlink
> styles). So for proper locale/cp support it is needed to do conversion from
> UTF-8 to local_nls.
>
> Signed-off-by: Pali Rohár <pali@...nel.org>
> ---
> fs/smb/client/reparse.c | 49 +++++++++++++++++++++++++++++++++++++++++
> fs/smb/common/smb2pdu.h | 9 ++++++++
> 2 files changed, 58 insertions(+)
>
> diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> index a577b2d2a4fc..6e9d914bac41 100644
> --- a/fs/smb/client/reparse.c
> +++ b/fs/smb/client/reparse.c
> @@ -875,6 +875,52 @@ static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym,
> cifs_sb);
> }
>
> +static int parse_reparse_wsl_symlink(struct reparse_wsl_symlink_data_buffer *buf,
> + struct cifs_sb_info *cifs_sb,
> + struct cifs_open_info_data *data)
> +{
> + int len = le16_to_cpu(buf->ReparseDataLength);
> + int symname_utf8_len;
> + __le16 *symname_utf16;
> + int symname_utf16_len;
> +
> + if (len <= sizeof(buf->Flags)) {
> + 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);
> + /*
> + * 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) {
> + 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,
> + UTF16_LITTLE_ENDIAN,
> + symname_utf16, symname_utf8_len * 2);
> + if (symname_utf16_len < 0) {
> + kfree(symname_utf16);
> + return symname_utf16_len;
> + }
> + symname_utf16_len *= 2; /* utf8s_to_utf16s() returns number of u16 items, not byte length */
> +
> + data->symlink_target = cifs_strndup_from_utf16((u8 *)symname_utf16,
> + symname_utf16_len, true,
> + cifs_sb->local_nls);
> + kfree(symname_utf16);
> + if (!data->symlink_target)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> int parse_reparse_point(struct reparse_data_buffer *buf,
> u32 plen, struct cifs_sb_info *cifs_sb,
> const char *full_path,
> @@ -894,6 +940,9 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
> (struct reparse_symlink_data_buffer *)buf,
> plen, unicode, cifs_sb, full_path, data);
> case IO_REPARSE_TAG_LX_SYMLINK:
> + return parse_reparse_wsl_symlink(
> + (struct reparse_wsl_symlink_data_buffer *)buf,
> + cifs_sb, data);
> case IO_REPARSE_TAG_AF_UNIX:
> case IO_REPARSE_TAG_LX_FIFO:
> case IO_REPARSE_TAG_LX_CHR:
> diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h
> index c769f9dbc0b4..275184c31a89 100644
> --- a/fs/smb/common/smb2pdu.h
> +++ b/fs/smb/common/smb2pdu.h
> @@ -1552,6 +1552,15 @@ struct reparse_symlink_data_buffer {
>
> /* See MS-FSCC 2.1.2.6 and cifspdu.h for struct reparse_posix_data */
>
> +/* For IO_REPARSE_TAG_LX_SYMLINK */
> +struct reparse_wsl_symlink_data_buffer {
> + __le32 ReparseTag;
> + __le16 ReparseDataLength;
> + __u16 Reserved;
> + __le32 Flags;
> + __u8 PathBuffer[]; /* Variable Length UTF-8 string without nul-term */
> +} __packed;
> +
> struct validate_negotiate_info_req {
> __le32 Capabilities;
> __u8 Guid[SMB2_CLIENT_GUID_SIZE];
> --
> 2.20.1
>
>
--
Thanks,
Steve
Powered by blists - more mailing lists