Commit 6914d288 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French
Browse files

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: default avatarPaulo Alcantara <pc@manguebit.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent c520ba75
Loading
Loading
Loading
Loading
+63 −43
Original line number Diff line number Diff line
@@ -223,14 +223,13 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
							  SMB2_O_INFO_FILE, 0,
							  sizeof(struct smb2_file_all_info) +
							  PATH_MAX * 2, 0, NULL);
				if (!rc) {
			}
			if (!rc && (!cfile || num_rqst > 1)) {
				smb2_set_next_command(tcon, &rqst[num_rqst]);
				smb2_set_related(&rqst[num_rqst]);
				}
			}

			if (rc)
			} else if (rc) {
				goto finished;
			}
			num_rqst++;
			trace_smb3_query_info_compound_enter(xid, ses->Suid,
							     tcon->tid, full_path);
@@ -260,14 +259,13 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
							  sizeof(struct smb311_posix_qinfo *) +
							  (PATH_MAX * 2) +
							  (sizeof(struct cifs_sid) * 2), 0, NULL);
				if (!rc) {
			}
			if (!rc && (!cfile || num_rqst > 1)) {
				smb2_set_next_command(tcon, &rqst[num_rqst]);
				smb2_set_related(&rqst[num_rqst]);
				}
			}

			if (rc)
			} 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 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
							FILE_END_OF_FILE_INFORMATION,
							SMB2_O_INFO_FILE, 0,
							data, size);
				if (!rc) {
			}
			if (!rc && (!cfile || num_rqst > 1)) {
				smb2_set_next_command(tcon, &rqst[num_rqst]);
				smb2_set_related(&rqst[num_rqst]);
				}
			}
			if (rc)
			} else if (rc) {
				goto finished;
			}
			num_rqst++;
			trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
			break;
@@ -356,14 +354,13 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
							COMPOUND_FID, current->tgid,
							FILE_BASIC_INFORMATION,
							SMB2_O_INFO_FILE, 0, data, size);
				if (!rc) {
			}
			if (!rc && (!cfile || num_rqst > 1)) {
				smb2_set_next_command(tcon, &rqst[num_rqst]);
				smb2_set_related(&rqst[num_rqst]);
				}
			}

			if (rc)
			} else if (rc) {
				goto finished;
			}
			num_rqst++;
			trace_smb3_set_info_compound_enter(xid, ses->Suid,
							   tcon->tid, full_path);
@@ -397,13 +394,13 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
							COMPOUND_FID, COMPOUND_FID,
							current->tgid, FILE_RENAME_INFORMATION,
							SMB2_O_INFO_FILE, 0, data, size);
				if (!rc) {
			}
			if (!rc && (!cfile || num_rqst > 1)) {
				smb2_set_next_command(tcon, &rqst[num_rqst]);
				smb2_set_related(&rqst[num_rqst]);
				}
			}
			if (rc)
			} else if (rc) {
				goto finished;
			}
			num_rqst++;
			trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
			break;
@@ -438,15 +435,27 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
			rqst[num_rqst].rq_iov = vars->io_iov;
			rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);

			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)
				goto finished;
			}
			if (!rc && (!cfile || num_rqst > 1)) {
				smb2_set_next_command(tcon, &rqst[num_rqst]);
			smb2_set_related(&rqst[num_rqst++]);
				smb2_set_related(&rqst[num_rqst]);
			} else if (rc) {
				goto finished;
			}
			num_rqst++;
			trace_smb3_set_reparse_compound_enter(xid, ses->Suid,
							      tcon->tid, full_path);
			break;
@@ -454,14 +463,25 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
			rqst[num_rqst].rq_iov = vars->io_iov;
			rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);

			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)
				goto finished;
			}
			if (!rc && (!cfile || num_rqst > 1)) {
				smb2_set_next_command(tcon, &rqst[num_rqst]);
			smb2_set_related(&rqst[num_rqst++]);
				smb2_set_related(&rqst[num_rqst]);
			} else if (rc) {
				goto finished;
			}
			num_rqst++;
			trace_smb3_get_reparse_compound_enter(xid, ses->Suid,
							      tcon->tid, full_path);
			break;