]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.13
authorSasha Levin <sashal@kernel.org>
Sat, 8 Mar 2025 14:08:41 +0000 (09:08 -0500)
committerSasha Levin <sashal@kernel.org>
Sat, 8 Mar 2025 14:08:41 +0000 (09:08 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.13/cifs-remove-symlink-member-from-cifs_open_info_data-.patch [new file with mode: 0644]
queue-6.13/series
queue-6.13/smb311-failure-to-open-files-of-length-1040-when-mou.patch [new file with mode: 0644]

diff --git a/queue-6.13/cifs-remove-symlink-member-from-cifs_open_info_data-.patch b/queue-6.13/cifs-remove-symlink-member-from-cifs_open_info_data-.patch
new file mode 100644 (file)
index 0000000..3b80979
--- /dev/null
@@ -0,0 +1,82 @@
+From 7db09b0bddf57b0194eb3226abf04e08ee222b5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Dec 2024 14:50:38 +0100
+Subject: cifs: Remove symlink member from cifs_open_info_data union
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 65c49767dd4fc058673f9259fda1772fd398eaa7 ]
+
+Member 'symlink' is part of the union in struct cifs_open_info_data. Its
+value is assigned on few places, but is always read through another union
+member 'reparse_point'. So to make code more readable, always use only
+'reparse_point' member and drop whole union structure. No function change.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: 9df23801c83d ("smb311: failure to open files of length 1040 when mounting with SMB3.1.1 POSIX extensions")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/cifsglob.h | 5 +----
+ fs/smb/client/inode.c    | 2 +-
+ fs/smb/client/smb1ops.c  | 4 ++--
+ 3 files changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
+index 1e6085f2f78ee..3877b861529ea 100644
+--- a/fs/smb/client/cifsglob.h
++++ b/fs/smb/client/cifsglob.h
+@@ -215,10 +215,7 @@ struct cifs_cred {
+ struct cifs_open_info_data {
+       bool adjust_tz;
+-      union {
+-              bool reparse_point;
+-              bool symlink;
+-      };
++      bool reparse_point;
+       struct {
+               /* ioctl response buffer */
+               struct {
+diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
+index 0d149b315a832..4d8effe78be57 100644
+--- a/fs/smb/client/inode.c
++++ b/fs/smb/client/inode.c
+@@ -990,7 +990,7 @@ cifs_get_file_info(struct file *filp)
+               /* TODO: add support to query reparse tag */
+               data.adjust_tz = false;
+               if (data.symlink_target) {
+-                      data.symlink = true;
++                      data.reparse_point = true;
+                       data.reparse.tag = IO_REPARSE_TAG_SYMLINK;
+               }
+               path = build_path_from_dentry(dentry, page);
+diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
+index c70f4961c4eb7..bd791aa54681f 100644
+--- a/fs/smb/client/smb1ops.c
++++ b/fs/smb/client/smb1ops.c
+@@ -551,7 +551,7 @@ static int cifs_query_path_info(const unsigned int xid,
+       int rc;
+       FILE_ALL_INFO fi = {};
+-      data->symlink = false;
++      data->reparse_point = false;
+       data->adjust_tz = false;
+       /* could do find first instead but this returns more info */
+@@ -592,7 +592,7 @@ static int cifs_query_path_info(const unsigned int xid,
+               /* Need to check if this is a symbolic link or not */
+               tmprc = CIFS_open(xid, &oparms, &oplock, NULL);
+               if (tmprc == -EOPNOTSUPP)
+-                      data->symlink = true;
++                      data->reparse_point = true;
+               else if (tmprc == 0)
+                       CIFSSMBClose(xid, tcon, fid.netfid);
+       }
+-- 
+2.39.5
+
index b65c7ec462ca5fcdf309fd7dbbc21ed5fbc5dd94..3fad2bed04a8aa6aced47f266daa775024a56e28 100644 (file)
@@ -1 +1,3 @@
 rust-block-fix-formatting-in-gendisk-doc.patch
+cifs-remove-symlink-member-from-cifs_open_info_data-.patch
+smb311-failure-to-open-files-of-length-1040-when-mou.patch
diff --git a/queue-6.13/smb311-failure-to-open-files-of-length-1040-when-mou.patch b/queue-6.13/smb311-failure-to-open-files-of-length-1040-when-mou.patch
new file mode 100644 (file)
index 0000000..83d2f9d
--- /dev/null
@@ -0,0 +1,147 @@
+From 8ce8e1b13fa4b829a13245289c3a4c329597e763 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 16 Feb 2025 22:17:54 -0600
+Subject: smb311: failure to open files of length 1040 when mounting with
+ SMB3.1.1 POSIX extensions
+
+From: Steve French <stfrench@microsoft.com>
+
+[ Upstream commit 9df23801c83d3e12b4c09be39d37d2be385e52f9 ]
+
+If a file size has bits 0x410 = ATTR_DIRECTORY | ATTR_REPARSE set
+then during queryinfo (stat) the file is regarded as a directory
+and subsequent opens can fail. A simple test example is trying
+to open any file 1040 bytes long when mounting with "posix"
+(SMB3.1.1 POSIX/Linux Extensions).
+
+The cause of this bug is that Attributes field in smb2_file_all_info
+struct occupies the same place that EndOfFile field in
+smb311_posix_qinfo, and sometimes the latter struct is incorrectly
+processed as if it was the first one.
+
+Reported-by: Oleh Nykyforchyn <oleh.nyk@gmail.com>
+Tested-by: Oleh Nykyforchyn <oleh.nyk@gmail.com>
+Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/cifsglob.h  |  1 +
+ fs/smb/client/reparse.h   | 28 ++++++++++++++++++++++------
+ fs/smb/client/smb2inode.c |  4 ++++
+ fs/smb/client/smb2ops.c   |  3 ++-
+ 4 files changed, 29 insertions(+), 7 deletions(-)
+
+diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
+index 3877b861529ea..37b7d84e26913 100644
+--- a/fs/smb/client/cifsglob.h
++++ b/fs/smb/client/cifsglob.h
+@@ -216,6 +216,7 @@ struct cifs_cred {
+ struct cifs_open_info_data {
+       bool adjust_tz;
+       bool reparse_point;
++      bool contains_posix_file_info;
+       struct {
+               /* ioctl response buffer */
+               struct {
+diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
+index ff05b0e75c928..f080f92cb1e74 100644
+--- a/fs/smb/client/reparse.h
++++ b/fs/smb/client/reparse.h
+@@ -97,14 +97,30 @@ static inline bool reparse_inode_match(struct inode *inode,
+ static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
+ {
+-      struct smb2_file_all_info *fi = &data->fi;
+-      u32 attrs = le32_to_cpu(fi->Attributes);
++      u32 attrs;
+       bool ret;
+-      ret = data->reparse_point || (attrs & ATTR_REPARSE);
+-      if (ret)
+-              attrs |= ATTR_REPARSE;
+-      fi->Attributes = cpu_to_le32(attrs);
++      if (data->contains_posix_file_info) {
++              struct smb311_posix_qinfo *fi = &data->posix_fi;
++
++              attrs = le32_to_cpu(fi->DosAttributes);
++              if (data->reparse_point) {
++                      attrs |= ATTR_REPARSE;
++                      fi->DosAttributes = cpu_to_le32(attrs);
++              }
++
++      } else {
++              struct smb2_file_all_info *fi = &data->fi;
++
++              attrs = le32_to_cpu(fi->Attributes);
++              if (data->reparse_point) {
++                      attrs |= ATTR_REPARSE;
++                      fi->Attributes = cpu_to_le32(attrs);
++              }
++      }
++
++      ret = attrs & ATTR_REPARSE;
++
+       return ret;
+ }
+diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
+index 7dfd3eb3847b3..6048b3fed3e78 100644
+--- a/fs/smb/client/smb2inode.c
++++ b/fs/smb/client/smb2inode.c
+@@ -648,6 +648,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
+               switch (cmds[i]) {
+               case SMB2_OP_QUERY_INFO:
+                       idata = in_iov[i].iov_base;
++                      idata->contains_posix_file_info = false;
+                       if (rc == 0 && cfile && cfile->symlink_target) {
+                               idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
+                               if (!idata->symlink_target)
+@@ -671,6 +672,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
+                       break;
+               case SMB2_OP_POSIX_QUERY_INFO:
+                       idata = in_iov[i].iov_base;
++                      idata->contains_posix_file_info = true;
+                       if (rc == 0 && cfile && cfile->symlink_target) {
+                               idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
+                               if (!idata->symlink_target)
+@@ -768,6 +770,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
+                               idata = in_iov[i].iov_base;
+                               idata->reparse.io.iov = *iov;
+                               idata->reparse.io.buftype = resp_buftype[i + 1];
++                              idata->contains_posix_file_info = false; /* BB VERIFY */
+                               rbuf = reparse_buf_ptr(iov);
+                               if (IS_ERR(rbuf)) {
+                                       rc = PTR_ERR(rbuf);
+@@ -789,6 +792,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
+               case SMB2_OP_QUERY_WSL_EA:
+                       if (!rc) {
+                               idata = in_iov[i].iov_base;
++                              idata->contains_posix_file_info = false;
+                               qi_rsp = rsp_iov[i + 1].iov_base;
+                               data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset);
+                               size[0] = le32_to_cpu(qi_rsp->OutputBufferLength);
+diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
+index 793e9b2b79d6f..17c3063a9ca5b 100644
+--- a/fs/smb/client/smb2ops.c
++++ b/fs/smb/client/smb2ops.c
+@@ -1001,6 +1001,7 @@ static int smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
+               if (!data->symlink_target)
+                       return -ENOMEM;
+       }
++      data->contains_posix_file_info = false;
+       return SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid, &data->fi);
+ }
+@@ -5150,7 +5151,7 @@ int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
+                            FILE_CREATE, CREATE_NOT_DIR |
+                            CREATE_OPTION_SPECIAL, ACL_NO_MODE);
+       oparms.fid = &fid;
+-
++      idata.contains_posix_file_info = false;
+       rc = server->ops->open(xid, &oparms, &oplock, &idata);
+       if (rc)
+               goto out;
+-- 
+2.39.5
+