Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88a92c91 authored by Ronnie Sahlberg's avatar Ronnie Sahlberg Committed by Steve French
Browse files

cifs: fix crash in smb2_compound_op()/smb2_set_next_command()



RHBZ: 1722704

In low memory situations the various SMB2_*_init() functions can fail
to allocate a request PDU and thus leave the request iovector as NULL.

If we don't check the return code for failure we end up calling
smb2_set_next_command() with a NULL iovector causing a crash when it tries
to dereference it.

CC: Stable <stable@vger.kernel.org>
Signed-off-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent ce465bf9
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ 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)
			goto finished;
		smb2_set_next_command(tcon, &rqst[num_rqst]);
		smb2_set_related(&rqst[num_rqst++]);
		trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
@@ -147,6 +149,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
					COMPOUND_FID, current->tgid,
					FILE_DISPOSITION_INFORMATION,
					SMB2_O_INFO_FILE, 0, data, size);
		if (rc)
			goto finished;
		smb2_set_next_command(tcon, &rqst[num_rqst]);
		smb2_set_related(&rqst[num_rqst++]);
		trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path);
@@ -163,6 +167,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
					COMPOUND_FID, current->tgid,
					FILE_END_OF_FILE_INFORMATION,
					SMB2_O_INFO_FILE, 0, data, size);
		if (rc)
			goto finished;
		smb2_set_next_command(tcon, &rqst[num_rqst]);
		smb2_set_related(&rqst[num_rqst++]);
		trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
@@ -180,6 +186,8 @@ 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)
			goto finished;
		smb2_set_next_command(tcon, &rqst[num_rqst]);
		smb2_set_related(&rqst[num_rqst++]);
		trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid,
@@ -206,6 +214,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
					COMPOUND_FID, current->tgid,
					FILE_RENAME_INFORMATION,
					SMB2_O_INFO_FILE, 0, data, size);
		if (rc)
			goto finished;
		smb2_set_next_command(tcon, &rqst[num_rqst]);
		smb2_set_related(&rqst[num_rqst++]);
		trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
@@ -231,6 +241,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
					COMPOUND_FID, current->tgid,
					FILE_LINK_INFORMATION,
					SMB2_O_INFO_FILE, 0, data, size);
		if (rc)
			goto finished;
		smb2_set_next_command(tcon, &rqst[num_rqst]);
		smb2_set_related(&rqst[num_rqst++]);
		trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path);
+10 −1
Original line number Diff line number Diff line
@@ -2027,6 +2027,10 @@ smb2_set_related(struct smb_rqst *rqst)
	struct smb2_sync_hdr *shdr;

	shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base);
	if (shdr == NULL) {
		cifs_dbg(FYI, "shdr NULL in smb2_set_related\n");
		return;
	}
	shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
}

@@ -2041,6 +2045,12 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
	unsigned long len = smb_rqst_len(server, rqst);
	int i, num_padding;

	shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base);
	if (shdr == NULL) {
		cifs_dbg(FYI, "shdr NULL in smb2_set_next_command\n");
		return;
	}

	/* SMB headers in a compound are 8 byte aligned. */

	/* No padding needed */
@@ -2080,7 +2090,6 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
	}

 finished:
	shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base);
	shdr->NextCommand = cpu_to_le32(len);
}