mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-16 18:26:42 +00:00
SMB3: Fix potential memory leak when processing compound chain
When a reconnect happens in the middle of processing a compound chain the code leaks a buffer from the memory pool. Fix this by properly checking for a return code and freeing buffers in case of error. Also maintain a buf variable to be equal to either smallbuf or bigbuf depending on a response buffer size while parsing a chain and when returning to the caller. Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com> Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
e99c63e4d8
commit
3edeb4a414
@ -4070,7 +4070,6 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
|
||||
{
|
||||
int ret, length;
|
||||
char *buf = server->smallbuf;
|
||||
char *tmpbuf;
|
||||
struct smb2_sync_hdr *shdr;
|
||||
unsigned int pdu_length = server->pdu_size;
|
||||
unsigned int buf_size;
|
||||
@ -4100,18 +4099,15 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
|
||||
return length;
|
||||
|
||||
next_is_large = server->large_buf;
|
||||
one_more:
|
||||
one_more:
|
||||
shdr = (struct smb2_sync_hdr *)buf;
|
||||
if (shdr->NextCommand) {
|
||||
if (next_is_large) {
|
||||
tmpbuf = server->bigbuf;
|
||||
if (next_is_large)
|
||||
next_buffer = (char *)cifs_buf_get();
|
||||
} else {
|
||||
tmpbuf = server->smallbuf;
|
||||
else
|
||||
next_buffer = (char *)cifs_small_buf_get();
|
||||
}
|
||||
memcpy(next_buffer,
|
||||
tmpbuf + le32_to_cpu(shdr->NextCommand),
|
||||
buf + le32_to_cpu(shdr->NextCommand),
|
||||
pdu_length - le32_to_cpu(shdr->NextCommand));
|
||||
}
|
||||
|
||||
@ -4140,12 +4136,21 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
|
||||
pdu_length -= le32_to_cpu(shdr->NextCommand);
|
||||
server->large_buf = next_is_large;
|
||||
if (next_is_large)
|
||||
server->bigbuf = next_buffer;
|
||||
server->bigbuf = buf = next_buffer;
|
||||
else
|
||||
server->smallbuf = next_buffer;
|
||||
|
||||
buf += le32_to_cpu(shdr->NextCommand);
|
||||
server->smallbuf = buf = next_buffer;
|
||||
goto one_more;
|
||||
} else if (ret != 0) {
|
||||
/*
|
||||
* ret != 0 here means that we didn't get to handle_mid() thus
|
||||
* server->smallbuf and server->bigbuf are still valid. We need
|
||||
* to free next_buffer because it is not going to be used
|
||||
* anywhere.
|
||||
*/
|
||||
if (next_is_large)
|
||||
free_rsp_buf(CIFS_LARGE_BUFFER, next_buffer);
|
||||
else
|
||||
free_rsp_buf(CIFS_SMALL_BUFFER, next_buffer);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
Loading…
x
Reference in New Issue
Block a user