Re: [PATCH RESEND 10/11] cifs: Add support for parsing WSL symlinks in version 1 format

Pali Rohár <[email protected]>
Newsgroups org.kernel.vger.linux-cifs,org.kernel.vger.linux-kernel
Message-ID <20260706210241.p5i4rxkab2sharmp@pali>
On Monday 06 July 2026 20:48:18 Pali Rohár wrote:
> +	switch (version) {
> +	case 1:
> +		/*
> +		 * Layout version 1 stores the symlink target in the data section of
> +		 * the file encoded in UTF-8 without trailing null-term byte.
> +		 */
>  
> -	if (version != 2) {
> +		oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_DATA,
> +				     FILE_OPEN, CREATE_NOT_DIR | OPEN_REPARSE_POINT,
> +				     ACL_NO_MODE);
> +		oparms.fid = &fid;
> +		oplock = tcon->ses->server->oplocks ? REQ_OPLOCK : 0;
> +		rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
> +		if (rc)
> +			goto out;
> +
> +		free_symname_utf8 = true;
> +		symname_utf8_len = le64_to_cpu(data->fi.EndOfFile);

And Sashiko found another issue
https://sashiko.dev/#/patchset/20260706184819.22124-1-pali%40kernel.org

  Does this unconditionally read EndOfFile from the smb2_file_all_info
  struct, even when data->contains_posix_file_info is true?

  If the mount uses POSIX extensions, smb311_posix_get_fattr() populates the
  posix_fi union member instead of fi, so could this read garbage data
  overlaying DosAttributes and Inode? Also, should there be a bounds check
  against something like PATH_MAX before passing this length to kmalloc()?

I did not though about combining POSIX extensions and WSL together.

And I must admit that it is tricky that sometimes it is needed to read
data from data->posix_fi and sometimes from data->fi. Following change
should address this issue. About bounds checks, do you have any
suggestion which one to use?


diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index 3fe57d166776..d7cb8eca7838 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -1114,6 +1114,7 @@ static int parse_reparse_wsl_symlink(struct reparse_wsl_symlink_data_buffer *buf
 	__le16 *symname_utf16;
 	int symname_utf16_len;
 	struct cifs_fid fid;
+	u64 file_size;
 	__u32 oplock;
 	int buf_type;
 	int rc = 0;
@@ -1133,8 +1134,12 @@ static int parse_reparse_wsl_symlink(struct reparse_wsl_symlink_data_buffer *buf
 		 * the file encoded in UTF-8 without trailing null-term byte.
 		 */

+		file_size = data->contains_posix_file_info ?
+			le64_to_cpu(data->posix_fi.EndOfFile) :
+			le64_to_cpu(data->fi.EndOfFile);
+
 		free_symname_utf8 = true;
-		symname_utf8_len = le64_to_cpu(data->fi.EndOfFile);
+		symname_utf8_len = file_size;
 		symname_utf8 = kmalloc(symname_utf8_len, GFP_KERNEL);
 		if (!symname_utf8) {
 			rc = -ENOMEM;
@@ -1162,7 +1167,7 @@ static int parse_reparse_wsl_symlink(struct reparse_wsl_symlink_data_buffer *buf
 						       &symname_utf8_len,
 						       &symname_utf8,
 						       &buf_type);
-		if (!rc && symname_utf8_len != le64_to_cpu(data->fi.EndOfFile))
+		if (!rc && symname_utf8_len != file_size)
 			rc = -EIO;

 		tcon->ses->server->ops->close(xid, tcon, &fid);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.