Commit 3edeb4a4 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French

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: default avatarPavel Shilovsky <pshilov@microsoft.com>
Reviewed-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent e99c63e4
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment