Skip to content

Commit 090c7d0

Browse files
smfrenchmehmetb0
authored andcommitted
smb311: failure to open files of length 1040 when mounting with SMB3.1.1 POSIX extensions
BugLink: https://bugs.launchpad.net/bugs/2117533 [ Upstream commit 9df2380 ] 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 <[email protected]> Tested-by: Oleh Nykyforchyn <[email protected]> Acked-by: Paulo Alcantara (Red Hat) <[email protected]> Cc: [email protected] Signed-off-by: Steve French <[email protected]> Signed-off-by: Sasha Levin <[email protected]> [nwager: Dropped hunks due to missing commits: 843bd00 ("cifs: Remove intermediate object of failed create SFU call") ea41367 ("smb: client: introduce SMB2_OP_QUERY_WSL_EA")] Signed-off-by: Noah Wager <[email protected]> Signed-off-by: Mehmet Basaran <[email protected]>
1 parent 6e243eb commit 090c7d0

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

fs/smb/client/cifsglob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ struct cifs_cred {
199199
struct cifs_open_info_data {
200200
bool adjust_tz;
201201
bool reparse_point;
202+
bool contains_posix_file_info;
202203
struct {
203204
/* ioctl response buffer */
204205
struct {

fs/smb/client/reparse.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,30 @@ static inline bool reparse_inode_match(struct inode *inode,
6464

6565
static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
6666
{
67-
struct smb2_file_all_info *fi = &data->fi;
68-
u32 attrs = le32_to_cpu(fi->Attributes);
67+
u32 attrs;
6968
bool ret;
7069

71-
ret = data->reparse_point || (attrs & ATTR_REPARSE);
72-
if (ret)
73-
attrs |= ATTR_REPARSE;
74-
fi->Attributes = cpu_to_le32(attrs);
70+
if (data->contains_posix_file_info) {
71+
struct smb311_posix_qinfo *fi = &data->posix_fi;
72+
73+
attrs = le32_to_cpu(fi->DosAttributes);
74+
if (data->reparse_point) {
75+
attrs |= ATTR_REPARSE;
76+
fi->DosAttributes = cpu_to_le32(attrs);
77+
}
78+
79+
} else {
80+
struct smb2_file_all_info *fi = &data->fi;
81+
82+
attrs = le32_to_cpu(fi->Attributes);
83+
if (data->reparse_point) {
84+
attrs |= ATTR_REPARSE;
85+
fi->Attributes = cpu_to_le32(attrs);
86+
}
87+
}
88+
89+
ret = attrs & ATTR_REPARSE;
90+
7591
return ret;
7692
}
7793

fs/smb/client/smb2inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
500500
switch (cmds[i]) {
501501
case SMB2_OP_QUERY_INFO:
502502
idata = in_iov[i].iov_base;
503+
idata->contains_posix_file_info = false;
503504
if (rc == 0 && cfile && cfile->symlink_target) {
504505
idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
505506
if (!idata->symlink_target)
@@ -523,6 +524,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
523524
break;
524525
case SMB2_OP_POSIX_QUERY_INFO:
525526
idata = in_iov[i].iov_base;
527+
idata->contains_posix_file_info = true;
526528
if (rc == 0 && cfile && cfile->symlink_target) {
527529
idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
528530
if (!idata->symlink_target)
@@ -611,6 +613,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
611613
idata = in_iov[i].iov_base;
612614
idata->reparse.io.iov = *iov;
613615
idata->reparse.io.buftype = resp_buftype[i + 1];
616+
idata->contains_posix_file_info = false; /* BB VERIFY */
614617
rbuf = reparse_buf_ptr(iov);
615618
if (IS_ERR(rbuf)) {
616619
rc = PTR_ERR(rbuf);

fs/smb/client/smb2ops.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,7 @@ static int smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
965965
if (!data->symlink_target)
966966
return -ENOMEM;
967967
}
968+
data->contains_posix_file_info = false;
968969
return SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid, &data->fi);
969970
}
970971

0 commit comments

Comments
 (0)