Commit f7c0e5d4 authored by Guangguan Wang's avatar Guangguan Wang Committed by Wang Liang
Browse files

net/smc: check iparea_offset and ipv6_prefixes_cnt when receiving proposal msg

stable inclusion
from stable-v5.10.233
commit 846bada23bfcdeb83621b045ed85dc06c7833ff0
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBJC74
CVE: CVE-2024-49571

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



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

[ Upstream commit a29e220d3c8edbf0e1beb0f028878a4a85966556 ]

When receiving proposal msg in server, the field iparea_offset
and the field ipv6_prefixes_cnt in proposal msg are from the
remote client and can not be fully trusted. Especially the
field iparea_offset, once exceed the max value, there has the
chance to access wrong address, and crash may happen.

This patch checks iparea_offset and ipv6_prefixes_cnt before using them.

Fixes: e7b7a64a ("smc: support variable CLC proposal messages")
Signed-off-by: default avatarGuangguan Wang <guangguan.wang@linux.alibaba.com>
Reviewed-by: default avatarWen Gu <guwen@linux.alibaba.com>
Reviewed-by: default avatarD. Wythe <alibuda@linux.alibaba.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarWang Liang <wangliang74@huawei.com>
parent 0dfa6b9e
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -1761,6 +1761,8 @@ static int smc_listen_prfx_check(struct smc_sock *new_smc,
	if (pclc->hdr.typev1 == SMC_TYPE_N)
		return 0;
	pclc_prfx = smc_clc_proposal_get_prefix(pclc);
	if (!pclc_prfx)
		return -EPROTO;
	if (smc_clc_prfx_match(newclcsock, pclc_prfx))
		return SMC_CLC_DECL_DIFFPREFIX;

@@ -1917,7 +1919,9 @@ static void smc_find_ism_v1_device_serv(struct smc_sock *new_smc,
	struct smc_clc_msg_smcd *pclc_smcd = smc_get_clc_msg_smcd(pclc);

	/* check if ISM V1 is available */
	if (!(ini->smcd_version & SMC_V1) || !smcd_indicated(ini->smc_type_v1))
	if (!(ini->smcd_version & SMC_V1) ||
	    !smcd_indicated(ini->smc_type_v1) ||
	    !pclc_smcd)
		goto not_found;
	ini->is_smcd = true; /* prepare ISM check */
	ini->ism_peer_gid[0] = ntohll(pclc_smcd->ism.gid);
+4 −0
Original line number Diff line number Diff line
@@ -49,6 +49,10 @@ static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc)

	v2_ext = smc_get_clc_v2_ext(pclc);
	pclc_prfx = smc_clc_proposal_get_prefix(pclc);
	if (!pclc_prfx ||
	    pclc_prfx->ipv6_prefixes_cnt > SMC_CLC_MAX_V6_PREFIX)
		return false;

	if (hdr->version == SMC_V1) {
		if (hdr->typev1 == SMC_TYPE_N)
			return false;
+5 −1
Original line number Diff line number Diff line
@@ -259,8 +259,12 @@ struct smc_clc_msg_decline { /* clc decline message */
static inline struct smc_clc_msg_proposal_prefix *
smc_clc_proposal_get_prefix(struct smc_clc_msg_proposal *pclc)
{
	u16 offset = ntohs(pclc->iparea_offset);

	if (offset > sizeof(struct smc_clc_msg_smcd))
		return NULL;
	return (struct smc_clc_msg_proposal_prefix *)
	       ((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset));
	       ((u8 *)pclc + sizeof(*pclc) + offset);
}

static inline bool smcr_indicated(int smc_type)