summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorGuangguan Wang <guangguan.wang@linux.alibaba.com>2024-12-11 17:21:18 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-12-27 13:58:47 +0100
commit91a7c27c1444ed4677b83fd5308d2cf03f5f0851 (patch)
tree88874028c9ff3e2793b0ecb13f289d7195566c3b /net
parent2e0786b3006e8c872320e86393920d580b7fba23 (diff)
downloadlinux-91a7c27c1444ed4677b83fd5308d2cf03f5f0851.tar.gz
linux-91a7c27c1444ed4677b83fd5308d2cf03f5f0851.tar.bz2
linux-91a7c27c1444ed4677b83fd5308d2cf03f5f0851.zip
net/smc: check iparea_offset and ipv6_prefixes_cnt when receiving proposal msg
[ 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: e7b7a64a8493 ("smc: support variable CLC proposal messages") Signed-off-by: Guangguan Wang <guangguan.wang@linux.alibaba.com> Reviewed-by: Wen Gu <guwen@linux.alibaba.com> Reviewed-by: D. Wythe <alibuda@linux.alibaba.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/smc/af_smc.c6
-rw-r--r--net/smc/smc_clc.c4
-rw-r--r--net/smc/smc_clc.h6
3 files changed, 14 insertions, 2 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 06d607e676f6..8551e097ad33 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -2039,6 +2039,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;
@@ -2228,7 +2230,9 @@ static void smc_find_ism_v1_device_serv(struct smc_sock *new_smc,
int rc = 0;
/* 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].gid = ntohll(pclc_smcd->ism.gid);
diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
index 0084960a203d..b8fd64392209 100644
--- a/net/smc/smc_clc.c
+++ b/net/smc/smc_clc.c
@@ -354,6 +354,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;
diff --git a/net/smc/smc_clc.h b/net/smc/smc_clc.h
index c8d6282ec9c0..eb843907c9d0 100644
--- a/net/smc/smc_clc.h
+++ b/net/smc/smc_clc.h
@@ -320,8 +320,12 @@ struct smc_clc_msg_decline_v2 { /* 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)