Linux CIFS filesystem development
 help / color / mirror / Atom feed
From: "Pali Rohár" <pali@kernel.org>
To: Steve French <sfrench@samba.org>,
	Paulo Alcantara <pc@manguebit.com>,
	Ronnie Sahlberg <ronniesahlberg@gmail.com>
Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 6/7] cifs: Add support for creating WSL-style symlinks
Date: Thu, 10 Oct 2024 23:50:34 +0200	[thread overview]
Message-ID: <20241010215034.pai6w6khigohip3g@pali> (raw)
In-Reply-To: <20241006100046.30772-7-pali@kernel.org>

On Sunday 06 October 2024 12:00:45 Pali Rohár wrote:
> This change implements support for creating new symlink in WSL-style by
> Linux cifs client when -o reparse=wsl mount option is specified. WSL-style
> symlink uses reparse point with tag IO_REPARSE_TAG_LX_SYMLINK and symlink
> target location is stored in reparse buffer in UTF-8 encoding prefixed by
> 32-bit flags. Flags bits are unknown, but it was observed that WSL always
> sets flags to value 0x02000000. Do same in Linux cifs client.
> 
> New symlinks would be created in WSL-style only in case the mount option
> -o reparse=wsl is specified, which is not by default. So default CIFS
> mounts are not affected by this change.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  fs/smb/client/reparse.c | 65 +++++++++++++++++++++++++++++++++--------
>  1 file changed, 53 insertions(+), 12 deletions(-)
> 
> diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> index 402eb568f466..6606c40487ae 100644
> --- a/fs/smb/client/reparse.c
> +++ b/fs/smb/client/reparse.c
> @@ -506,9 +506,17 @@ static int mknod_nfs(unsigned int xid, struct inode *inode,
>  	return rc;
>  }
>  
> -static int wsl_set_reparse_buf(struct reparse_data_buffer *buf,
> -			       mode_t mode, struct kvec *iov)
> +static int wsl_set_reparse_buf(struct reparse_data_buffer **buf,
> +			       mode_t mode, const char *symname,
> +			       struct cifs_sb_info *cifs_sb,
> +			       struct kvec *iov)
>  {
> +	struct reparse_wsl_symlink_data_buffer *symlink_buf;
> +	__le16 *symname_utf16;
> +	int symname_utf16_len;
> +	int symname_utf8_maxlen;
> +	int symname_utf8_len;
> +	size_t buf_len;
>  	u32 tag;
>  
>  	switch ((tag = reparse_mode_wsl_tag(mode))) {
> @@ -516,17 +524,45 @@ static int wsl_set_reparse_buf(struct reparse_data_buffer *buf,
>  	case IO_REPARSE_TAG_LX_CHR:
>  	case IO_REPARSE_TAG_LX_FIFO:
>  	case IO_REPARSE_TAG_AF_UNIX:
> +		buf_len = sizeof(struct reparse_data_buffer);
> +		*buf = kzalloc(buf_len, GFP_KERNEL);
> +		if (!*buf)
> +			return -ENOMEM;
> +		break;
> +	case IO_REPARSE_TAG_LX_SYMLINK:
> +		symname_utf16 = cifs_strndup_to_utf16(symname, strlen(symname),
> +						      &symname_utf16_len,
> +						      cifs_sb->local_nls,
> +						      NO_MAP_UNI_RSVD);
> +		if (!symname_utf16)
> +			return -ENOMEM;
> +		symname_utf8_maxlen = symname_utf16_len/2*3;
> +		symlink_buf = kzalloc(sizeof(struct reparse_wsl_symlink_data_buffer) +
> +				      symname_utf8_maxlen, GFP_KERNEL);
> +		if (!symlink_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 */
> +		symname_utf8_len = utf16s_to_utf8s(symname_utf16, symname_utf16_len/2,
> +						   UTF16_LITTLE_ENDIAN,
> +						   symlink_buf->PathBuffer,
> +						   symname_utf8_maxlen);
> +		*buf = (struct reparse_data_buffer *)symlink_buf;
> +		buf_len = sizeof(struct reparse_wsl_symlink_data_buffer) + symname_utf8_len;
> +		kfree(symname_utf16);
>  		break;
> -	case IO_REPARSE_TAG_LX_SYMLINK: /* TODO: add support for WSL symlinks */
>  	default:
>  		return -EOPNOTSUPP;
>  	}
>  
> -	buf->ReparseTag = cpu_to_le32(tag);
> -	buf->Reserved = 0;
> -	buf->ReparseDataLength = 0;
> -	iov->iov_base = buf;
> -	iov->iov_len = sizeof(*buf);
> +	(*buf)->ReparseTag = cpu_to_le32(tag);
> +	(*buf)->Reserved = 0;
> +	(*buf)->ReparseDataLength = buf_len - sizeof(struct reparse_data_buffer);

ReparseDataLength is in little endian, so it should be:

  (*buf)->ReparseDataLength = cpu_to_le16(buf_len - sizeof(struct reparse_data_buffer));

> +	iov->iov_base = *buf;
> +	iov->iov_len = buf_len;
>  	return 0;
>  }
>  
> @@ -618,25 +654,29 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
>  		     const char *full_path, umode_t mode, dev_t dev,
>  		     const char *symname)
>  {
> +	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
>  	struct cifs_open_info_data data;
> -	struct reparse_data_buffer buf;
> +	struct reparse_data_buffer *buf;
>  	struct smb2_create_ea_ctx *cc;
>  	struct inode *new;
>  	unsigned int len;
>  	struct kvec reparse_iov, xattr_iov;
>  	int rc;
>  
> -	rc = wsl_set_reparse_buf(&buf, mode, &reparse_iov);
> +	rc = wsl_set_reparse_buf(&buf, mode, symname, cifs_sb, &reparse_iov);
>  	if (rc)
>  		return rc;
>  
>  	rc = wsl_set_xattrs(inode, mode, dev, &xattr_iov);
> -	if (rc)
> +	if (rc) {
> +		kfree(buf);
>  		return rc;
> +	}
>  
>  	data = (struct cifs_open_info_data) {
>  		.reparse_point = true,
> -		.reparse = { .tag = le32_to_cpu(buf.ReparseTag), .buf = &buf, },
> +		.reparse = { .tag = le32_to_cpu(buf->ReparseTag), .buf = buf, },
> +		.symlink_target = kstrdup(symname, GFP_KERNEL),
>  	};
>  
>  	cc = xattr_iov.iov_base;
> @@ -653,6 +693,7 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
>  		rc = PTR_ERR(new);
>  	cifs_free_open_info(&data);
>  	kfree(xattr_iov.iov_base);
> +	kfree(buf);
>  	return rc;
>  }
>  
> -- 
> 2.20.1
> 

  reply	other threads:[~2024-10-10 21:50 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-06 10:00 [PATCH 0/7] cifs: Improve mount option -o reparse and support for native Windows sockets Pali Rohár
2024-10-06 10:00 ` [PATCH 1/7] cifs: Add mount option -o reparse=native Pali Rohár
2024-10-07  4:28   ` Steve French
2024-10-07 18:36     ` Pali Rohár
     [not found]       ` <CAH2r5mttO-aDq94QrLQm10xJRGLg=PULqX9fcfoykAweVVO+uQ@mail.gmail.com>
2024-10-10 22:21         ` Steve French
2024-10-10 22:38           ` Pali Rohár
     [not found]             ` <CAH2r5msEiD05ehJs_a05sP_rX7BkVH-9LZp8Sj6EFbpZA9bfrg@mail.gmail.com>
2024-10-10 22:44               ` Pali Rohár
2024-10-06 10:00 ` [PATCH 2/7] cifs: Add mount option -o reparse=none Pali Rohár
2024-10-06 10:00 ` [PATCH 3/7] cifs: Add support for creating native Windows sockets Pali Rohár
2024-10-10 21:47   ` Pali Rohár
2024-10-06 10:00 ` [PATCH 4/7] cifs: Add support for creating NFS-style symlinks Pali Rohár
2024-10-06 10:00 ` [PATCH 5/7] cifs: Improve guard for excluding $LXDEV xattr Pali Rohár
2024-10-06 10:00 ` [PATCH 6/7] cifs: Add support for creating WSL-style symlinks Pali Rohár
2024-10-10 21:50   ` Pali Rohár [this message]
2024-10-06 10:00 ` [PATCH 7/7] cifs: Validate content of WSL reparse point buffers Pali Rohár
2024-10-07  4:23 ` [PATCH 0/7] cifs: Improve mount option -o reparse and support for native Windows sockets Steve French
2024-10-12  8:52 ` [PATCH v2 0/7] Allow to choose symlink and socket type Pali Rohár
2024-10-12  8:55   ` [PATCH v2 1/7] cifs: Add mount option -o symlink= for choosing symlink create type Pali Rohár
2024-10-12  8:55   ` [PATCH v2 2/7] cifs: Add mount option -o reparse=none Pali Rohár
2024-10-12  8:55   ` [PATCH v2 3/7] cifs: Add support for creating native Windows sockets Pali Rohár
2024-10-12  8:56   ` [PATCH v2 4/7] cifs: Add support for creating NFS-style symlinks Pali Rohár
2024-12-09 18:00     ` Pali Rohár
2024-10-12  8:56   ` [PATCH v2 5/7] cifs: Improve guard for excluding $LXDEV xattr Pali Rohár
2024-10-12  8:56   ` [PATCH v2 6/7] cifs: Add support for creating WSL-style symlinks Pali Rohár
2024-10-12  8:56   ` [PATCH v2 7/7] cifs: Validate content of WSL reparse point buffers Pali Rohár
     [not found]   ` <CAH2r5mtGqqM35Cy5k9NN=X05rTZPk-adhb7LgoV8PGNVL9P6FQ@mail.gmail.com>
2024-10-13  4:19     ` Fwd: [PATCH v2 0/7] Allow to choose symlink and socket type Steve French
2024-10-13  8:59     ` Pali Rohár
2024-10-13 13:38     ` Pali Rohár
2024-10-14  9:32       ` Pali Rohár
2024-10-28 10:13   ` Pali Rohár

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241010215034.pai6w6khigohip3g@pali \
    --to=pali@kernel.org \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pc@manguebit.com \
    --cc=ronniesahlberg@gmail.com \
    --cc=sfrench@samba.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox