Commit 84ec4610 authored by Namjae Jeon's avatar Namjae Jeon Committed by ZhaoLong Wang
Browse files

ksmbd: fix out of bounds in init_smb2_rsp_hdr()

stable inclusion
from stable-v5.15.145
commit 5c0df9d30c289d6b9d7d44e2a450de2f8e3cf40b
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I92OOJ
CVE: CVE-2023-52441

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=5c0df9d30c289d6b9d7d44e2a450de2f8e3cf40b



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

[ Upstream commit 536bb492 ]

If client send smb2 negotiate request and then send smb1 negotiate
request, init_smb2_rsp_hdr is called for smb1 negotiate request since
need_neg is set to false. This patch ignore smb1 packets after ->need_neg
is set to false.

Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-21541
Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarZhaoLong Wang <wangzhaolong1@huawei.com>
parent ba138450
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -286,6 +286,7 @@ static void handle_ksmbd_work(struct work_struct *wk)
static int queue_ksmbd_work(struct ksmbd_conn *conn)
{
	struct ksmbd_work *work;
	int err;

	work = ksmbd_alloc_work_struct();
	if (!work) {
@@ -297,7 +298,11 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
	work->request_buf = conn->request_buf;
	conn->request_buf = NULL;

	ksmbd_init_smb_server(work);
	err = ksmbd_init_smb_server(work);
	if (err) {
		ksmbd_free_work_struct(work);
		return 0;
	}

	ksmbd_conn_enqueue_request(work);
	atomic_inc(&conn->r_count);
+11 −8
Original line number Diff line number Diff line
@@ -386,26 +386,29 @@ static struct smb_version_cmds smb1_server_cmds[1] = {
	[SMB_COM_NEGOTIATE_EX]	= { .proc = smb1_negotiate, },
};

static void init_smb1_server(struct ksmbd_conn *conn)
static int init_smb1_server(struct ksmbd_conn *conn)
{
	conn->ops = &smb1_server_ops;
	conn->cmds = smb1_server_cmds;
	conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
	return 0;
}

void ksmbd_init_smb_server(struct ksmbd_work *work)
int ksmbd_init_smb_server(struct ksmbd_work *work)
{
	struct ksmbd_conn *conn = work->conn;
	__le32 proto;

	if (conn->need_neg == false)
		return;

	proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
	if (conn->need_neg == false) {
		if (proto == SMB1_PROTO_NUMBER)
		init_smb1_server(conn);
	else
		init_smb3_11_server(conn);
			return -EINVAL;
		return 0;
	}

	if (proto == SMB1_PROTO_NUMBER)
		return init_smb1_server(conn);
	return init_smb3_11_server(conn);
}

int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
+1 −1
Original line number Diff line number Diff line
@@ -474,7 +474,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);

int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);

void ksmbd_init_smb_server(struct ksmbd_work *work);
int ksmbd_init_smb_server(struct ksmbd_work *work);

struct ksmbd_kstat;
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,