Commit ac9ef820 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by ZhaoLong Wang
Browse files

smb: client: fix OOB in receive_encrypted_standard()

mainline inclusion
from mainline-v6.7-rc6
commit eec04ea119691e65227a97ce53c0da6b9b74b0b7
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8WEOK
CVE: CVE-2024-0565

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=eec04ea119691e65227a97ce53c0da6b9b74b0b7



--------------------------------

Fix potential OOB in receive_encrypted_standard() if server returned a
large shdr->NextCommand that would end up writing off the end of
@next_buffer.

Fixes: b24df3e3 ("cifs: update receive_encrypted_standard to handle compounded responses")
Cc: stable@vger.kernel.org
Reported-by: default avatarRobert Morris <rtm@csail.mit.edu>
Signed-off-by: default avatarPaulo Alcantara (SUSE) <pc@manguebit.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>

Conflicts:
	fs/cifs/smb2ops.c

Signed-off-by: default avatarZhaoLong Wang <wangzhaolong1@huawei.com>
parent 7be0499d
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -4886,6 +4886,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
	struct smb2_sync_hdr *shdr;
	unsigned int pdu_length = server->pdu_size;
	unsigned int buf_size;
	unsigned int next_cmd;
	struct mid_q_entry *mid_entry;
	int next_is_large;
	char *next_buffer = NULL;
@@ -4914,14 +4915,15 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
	next_is_large = server->large_buf;
one_more:
	shdr = (struct smb2_sync_hdr *)buf;
	if (shdr->NextCommand) {
	next_cmd = le32_to_cpu(shdr->NextCommand);
	if (next_cmd) {
		if (WARN_ON_ONCE(next_cmd > pdu_length))
			return -1;
		if (next_is_large)
			next_buffer = (char *)cifs_buf_get();
		else
			next_buffer = (char *)cifs_small_buf_get();
		memcpy(next_buffer,
		       buf + le32_to_cpu(shdr->NextCommand),
		       pdu_length - le32_to_cpu(shdr->NextCommand));
		memcpy(next_buffer, buf + next_cmd, pdu_length - next_cmd);
	}

	mid_entry = smb2_find_mid(server, buf);
@@ -4945,8 +4947,8 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
	else
		ret = cifs_handle_standard(server, mid_entry);

	if (ret == 0 && shdr->NextCommand) {
		pdu_length -= le32_to_cpu(shdr->NextCommand);
	if (ret == 0 && next_cmd) {
		pdu_length -= next_cmd;
		server->large_buf = next_is_large;
		if (next_is_large)
			server->bigbuf = buf = next_buffer;