summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2024-01-25 23:04:05 +0300
committerSteve French <stfrench@microsoft.com>2024-03-11 03:33:58 +0300
commit6914d288c63682e20e0f6e1e0b8e8f5847012d67 (patch)
tree3f03af0444e706f50b0c2c520284674f4091934f /fs
parentc520ba7573a84bd37f8803a3beeb8f6f995bf9e1 (diff)
downloadlinux-6914d288c63682e20e0f6e1e0b8e8f5847012d67.tar.xz
smb: client: fix potential broken compound request
Now that smb2_compound_op() can accept up to 5 commands in a single compound request, set the appropriate NextCommand and related flags to all subsequent commands as well as handling the case where a valid @cfile is passed and therefore skipping create and close requests in the compound chain. This fix a potential broken compound request that could be sent from smb2_get_reparse_inode() if the client found a valid open file (@cfile) prior to calling smb2_compound_op(). Signed-off-by: Paulo Alcantara <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/smb/client/smb2inode.c106
1 files changed, 63 insertions, 43 deletions
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index f697c14cd8c6..a4413aaffd5e 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -223,14 +223,13 @@ replay_again:
SMB2_O_INFO_FILE, 0,
sizeof(struct smb2_file_all_info) +
PATH_MAX * 2, 0, NULL);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
}
-
- if (rc)
+ if (!rc && (!cfile || num_rqst > 1)) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ } else if (rc) {
goto finished;
+ }
num_rqst++;
trace_smb3_query_info_compound_enter(xid, ses->Suid,
tcon->tid, full_path);
@@ -260,14 +259,13 @@ replay_again:
sizeof(struct smb311_posix_qinfo *) +
(PATH_MAX * 2) +
(sizeof(struct cifs_sid) * 2), 0, NULL);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
}
-
- if (rc)
+ if (!rc && (!cfile || num_rqst > 1)) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ } else if (rc) {
goto finished;
+ }
num_rqst++;
trace_smb3_posix_query_info_compound_enter(xid, ses->Suid,
tcon->tid, full_path);
@@ -325,13 +323,13 @@ replay_again:
FILE_END_OF_FILE_INFORMATION,
SMB2_O_INFO_FILE, 0,
data, size);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
}
- if (rc)
+ if (!rc && (!cfile || num_rqst > 1)) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ } else if (rc) {
goto finished;
+ }
num_rqst++;
trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
break;
@@ -356,14 +354,13 @@ replay_again:
COMPOUND_FID, current->tgid,
FILE_BASIC_INFORMATION,
SMB2_O_INFO_FILE, 0, data, size);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
}
-
- if (rc)
+ if (!rc && (!cfile || num_rqst > 1)) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ } else if (rc) {
goto finished;
+ }
num_rqst++;
trace_smb3_set_info_compound_enter(xid, ses->Suid,
tcon->tid, full_path);
@@ -397,13 +394,13 @@ replay_again:
COMPOUND_FID, COMPOUND_FID,
current->tgid, FILE_RENAME_INFORMATION,
SMB2_O_INFO_FILE, 0, data, size);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
}
- if (rc)
+ if (!rc && (!cfile || num_rqst > 1)) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ } else if (rc) {
goto finished;
+ }
num_rqst++;
trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
break;
@@ -438,15 +435,27 @@ replay_again:
rqst[num_rqst].rq_iov = vars->io_iov;
rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
- rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
- COMPOUND_FID, COMPOUND_FID,
- FSCTL_SET_REPARSE_POINT,
- in_iov[i].iov_base,
- in_iov[i].iov_len, 0);
- if (rc)
+ if (cfile) {
+ rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ FSCTL_SET_REPARSE_POINT,
+ in_iov[i].iov_base,
+ in_iov[i].iov_len, 0);
+ } else {
+ rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
+ COMPOUND_FID, COMPOUND_FID,
+ FSCTL_SET_REPARSE_POINT,
+ in_iov[i].iov_base,
+ in_iov[i].iov_len, 0);
+ }
+ if (!rc && (!cfile || num_rqst > 1)) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ } else if (rc) {
goto finished;
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst++]);
+ }
+ num_rqst++;
trace_smb3_set_reparse_compound_enter(xid, ses->Suid,
tcon->tid, full_path);
break;
@@ -454,14 +463,25 @@ replay_again:
rqst[num_rqst].rq_iov = vars->io_iov;
rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
- rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
- COMPOUND_FID, COMPOUND_FID,
- FSCTL_GET_REPARSE_POINT,
- NULL, 0, CIFSMaxBufSize);
- if (rc)
+ if (cfile) {
+ rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ FSCTL_GET_REPARSE_POINT,
+ NULL, 0, CIFSMaxBufSize);
+ } else {
+ rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
+ COMPOUND_FID, COMPOUND_FID,
+ FSCTL_GET_REPARSE_POINT,
+ NULL, 0, CIFSMaxBufSize);
+ }
+ if (!rc && (!cfile || num_rqst > 1)) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ } else if (rc) {
goto finished;
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst++]);
+ }
+ num_rqst++;
trace_smb3_get_reparse_compound_enter(xid, ses->Suid,
tcon->tid, full_path);
break;