diff options
author | Ronnie Sahlberg <lsahlber@redhat.com> | 2019-07-15 20:41:46 -0400 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2019-07-15 22:20:09 -0400 |
commit | 88a92c913cef09e70b1744a8877d177aa6cb2189 (patch) | |
tree | 963990acacc7764fd1d094cba922547489d866b1 /fs/cifs | |
parent | ce465bf94b70f03136171a62b607864f00093b19 (diff) |
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: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/smb2inode.c | 12 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 11 |
2 files changed, 22 insertions, 1 deletions
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 278405d26c47..d8d9cdfa30b6 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c | |||
@@ -120,6 +120,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, | |||
120 | SMB2_O_INFO_FILE, 0, | 120 | SMB2_O_INFO_FILE, 0, |
121 | sizeof(struct smb2_file_all_info) + | 121 | sizeof(struct smb2_file_all_info) + |
122 | PATH_MAX * 2, 0, NULL); | 122 | PATH_MAX * 2, 0, NULL); |
123 | if (rc) | ||
124 | goto finished; | ||
123 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 125 | smb2_set_next_command(tcon, &rqst[num_rqst]); |
124 | smb2_set_related(&rqst[num_rqst++]); | 126 | smb2_set_related(&rqst[num_rqst++]); |
125 | trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid, | 127 | 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, | |||
147 | COMPOUND_FID, current->tgid, | 149 | COMPOUND_FID, current->tgid, |
148 | FILE_DISPOSITION_INFORMATION, | 150 | FILE_DISPOSITION_INFORMATION, |
149 | SMB2_O_INFO_FILE, 0, data, size); | 151 | SMB2_O_INFO_FILE, 0, data, size); |
152 | if (rc) | ||
153 | goto finished; | ||
150 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 154 | smb2_set_next_command(tcon, &rqst[num_rqst]); |
151 | smb2_set_related(&rqst[num_rqst++]); | 155 | smb2_set_related(&rqst[num_rqst++]); |
152 | trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path); | 156 | 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, | |||
163 | COMPOUND_FID, current->tgid, | 167 | COMPOUND_FID, current->tgid, |
164 | FILE_END_OF_FILE_INFORMATION, | 168 | FILE_END_OF_FILE_INFORMATION, |
165 | SMB2_O_INFO_FILE, 0, data, size); | 169 | SMB2_O_INFO_FILE, 0, data, size); |
170 | if (rc) | ||
171 | goto finished; | ||
166 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 172 | smb2_set_next_command(tcon, &rqst[num_rqst]); |
167 | smb2_set_related(&rqst[num_rqst++]); | 173 | smb2_set_related(&rqst[num_rqst++]); |
168 | trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path); | 174 | 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, | |||
180 | COMPOUND_FID, current->tgid, | 186 | COMPOUND_FID, current->tgid, |
181 | FILE_BASIC_INFORMATION, | 187 | FILE_BASIC_INFORMATION, |
182 | SMB2_O_INFO_FILE, 0, data, size); | 188 | SMB2_O_INFO_FILE, 0, data, size); |
189 | if (rc) | ||
190 | goto finished; | ||
183 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 191 | smb2_set_next_command(tcon, &rqst[num_rqst]); |
184 | smb2_set_related(&rqst[num_rqst++]); | 192 | smb2_set_related(&rqst[num_rqst++]); |
185 | trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid, | 193 | 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, | |||
206 | COMPOUND_FID, current->tgid, | 214 | COMPOUND_FID, current->tgid, |
207 | FILE_RENAME_INFORMATION, | 215 | FILE_RENAME_INFORMATION, |
208 | SMB2_O_INFO_FILE, 0, data, size); | 216 | SMB2_O_INFO_FILE, 0, data, size); |
217 | if (rc) | ||
218 | goto finished; | ||
209 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 219 | smb2_set_next_command(tcon, &rqst[num_rqst]); |
210 | smb2_set_related(&rqst[num_rqst++]); | 220 | smb2_set_related(&rqst[num_rqst++]); |
211 | trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path); | 221 | 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, | |||
231 | COMPOUND_FID, current->tgid, | 241 | COMPOUND_FID, current->tgid, |
232 | FILE_LINK_INFORMATION, | 242 | FILE_LINK_INFORMATION, |
233 | SMB2_O_INFO_FILE, 0, data, size); | 243 | SMB2_O_INFO_FILE, 0, data, size); |
244 | if (rc) | ||
245 | goto finished; | ||
234 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 246 | smb2_set_next_command(tcon, &rqst[num_rqst]); |
235 | smb2_set_related(&rqst[num_rqst++]); | 247 | smb2_set_related(&rqst[num_rqst++]); |
236 | trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path); | 248 | trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path); |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index e704e04891fb..0cdc4e47ca87 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -2027,6 +2027,10 @@ smb2_set_related(struct smb_rqst *rqst) | |||
2027 | struct smb2_sync_hdr *shdr; | 2027 | struct smb2_sync_hdr *shdr; |
2028 | 2028 | ||
2029 | shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base); | 2029 | shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base); |
2030 | if (shdr == NULL) { | ||
2031 | cifs_dbg(FYI, "shdr NULL in smb2_set_related\n"); | ||
2032 | return; | ||
2033 | } | ||
2030 | shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS; | 2034 | shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS; |
2031 | } | 2035 | } |
2032 | 2036 | ||
@@ -2041,6 +2045,12 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst) | |||
2041 | unsigned long len = smb_rqst_len(server, rqst); | 2045 | unsigned long len = smb_rqst_len(server, rqst); |
2042 | int i, num_padding; | 2046 | int i, num_padding; |
2043 | 2047 | ||
2048 | shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base); | ||
2049 | if (shdr == NULL) { | ||
2050 | cifs_dbg(FYI, "shdr NULL in smb2_set_next_command\n"); | ||
2051 | return; | ||
2052 | } | ||
2053 | |||
2044 | /* SMB headers in a compound are 8 byte aligned. */ | 2054 | /* SMB headers in a compound are 8 byte aligned. */ |
2045 | 2055 | ||
2046 | /* No padding needed */ | 2056 | /* No padding needed */ |
@@ -2080,7 +2090,6 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst) | |||
2080 | } | 2090 | } |
2081 | 2091 | ||
2082 | finished: | 2092 | finished: |
2083 | shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base); | ||
2084 | shdr->NextCommand = cpu_to_le32(len); | 2093 | shdr->NextCommand = cpu_to_le32(len); |
2085 | } | 2094 | } |
2086 | 2095 | ||