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

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

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
Loading
Loading
Loading
Loading
+17 −12
Original line number Diff line number Diff line
@@ -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;
@@ -4103,15 +4102,12 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
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;