mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 08:15:07 -04:00
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 //<server>/<share> /mnt/cifs \
-o vers=3.1.1,posix,reparse=nfs,actimeo=0
mkfifo /mnt/cifs/test-fifo
umount /mnt/cifs
mount -t cifs //<server>/<share> /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: 9df23801c8 ("smb311: failure to open files of length 1040 when mounting with SMB3.1.1 POSIX extensions")
Signed-off-by: Ze Tan <tanze@kylinos.cn>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user