From 9437f2113b60a5a8593aa4b41b6f6632f5cabcfd Mon Sep 17 00:00:00 2001 From: Ze Tan Date: Tue, 11 Aug 2026 14:00:46 +0800 Subject: [PATCH] smb/client: preserve open info type across compound queries contains_posix_file_info describes the metadata stored in the fi/posix_fi union. GET_REPARSE and QUERY_WSL_EA do not update that union, so clearing the flag while processing those responses can make POSIX metadata look like FILE_ALL_INFORMATION. Set the flag when CREATE or a validated query response actually populates the union, and leave it unchanged for auxiliary compound operations. This also avoids changing the type when a query fails before copying any metadata. The issue can be reproduced against a Samba server with SMB3 UNIX extensions enabled: mount -t cifs /// /mnt/cifs \ -o vers=3.1.1,posix,reparse=nfs,actimeo=0 mkfifo /mnt/cifs/test-fifo umount /mnt/cifs mount -t cifs /// /mnt/cifs \ -o vers=3.1.1,posix,reparse=nfs,actimeo=0 stat -c '%F %s' /mnt/cifs/test-fifo Before this change, stat reports "fifo 1024" although the server-side EOF is zero. After this change, it reports "fifo 0". Fixes: 9df23801c83d ("smb311: failure to open files of length 1040 when mounting with SMB3.1.1 POSIX extensions") Signed-off-by: Ze Tan Signed-off-by: Namjae Jeon Signed-off-by: Paulo Alcantara --- fs/smb/client/smb2inode.c | 9 +++++---- fs/smb/client/smb2pdu.c | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index d4ae8a5ad463..058b05f7a3e5 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c @@ -574,6 +574,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, idata->fi.Attributes = create_rsp->FileAttributes; idata->fi.AllocationSize = create_rsp->AllocationSize; idata->fi.EndOfFile = create_rsp->EndofFile; + idata->contains_posix_file_info = false; if (le32_to_cpu(idata->fi.NumberOfLinks) == 0) idata->fi.NumberOfLinks = cpu_to_le32(1); /* dummy value */ idata->unknown_nlink = true; @@ -597,7 +598,6 @@ 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) @@ -610,6 +610,8 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, le16_to_cpu(qi_rsp->OutputBufferOffset), le32_to_cpu(qi_rsp->OutputBufferLength), &rsp_iov[i + 1], sizeof(idata->fi), (char *)&idata->fi); + if (!rc) + idata->contains_posix_file_info = false; } SMB2_query_info_free(&rqst[num_rqst++]); if (rc) @@ -621,7 +623,6 @@ 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) @@ -635,6 +636,8 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, le32_to_cpu(qi_rsp->OutputBufferLength), &rsp_iov[i + 1], sizeof(idata->posix_fi) /* add SIDs */, (char *)&idata->posix_fi); + if (!rc) + idata->contains_posix_file_info = true; } if (rc == 0) rc = parse_posix_sids(idata, &rsp_iov[i + 1]); @@ -706,7 +709,6 @@ 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); @@ -728,7 +730,6 @@ 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/smb2pdu.c b/fs/smb/client/smb2pdu.c index d207591cc889..dea05aeb53a1 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -3372,6 +3372,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, #endif /* CIFS_DEBUG2 */ if (file_info) { + buf->contains_posix_file_info = false; file_info->CreationTime = rsp->CreationTime; file_info->LastAccessTime = rsp->LastAccessTime; file_info->LastWriteTime = rsp->LastWriteTime;