public inbox for linux-rdma@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net] net/smc: fix mismatch between CLC header and proposal extensions
@ 2025-10-31  3:18 D. Wythe
  2025-11-03  8:28 ` Alexandra Winter
  0 siblings, 1 reply; 5+ messages in thread
From: D. Wythe @ 2025-10-31  3:18 UTC (permalink / raw)
  To: mjambigi, wenjia, wintera, dust.li, tonylu, guwen
  Cc: kuba, davem, netdev, linux-s390, linux-rdma, pabeni, edumazet,
	sidraya, jaka

The current CLC proposal message construction uses a mix of
`ini->smc_type_v1/v2` and `pclc_base->hdr.typev1/v2` to decide whether
to include optional extensions (IPv6 prefix extension for v1, and v2
extension). This leads to a critical inconsistency: when
`smc_clc_prfx_set()` fails - for example, in IPv6-only environments with
only link-local addresses, or when the local IP address and the outgoing
interface’s network address are not in the same subnet.

As a result, the proposal message is assembled using the stale
`ini->smc_type_v1` value—causing the IPv6 prefix extension to be
included even though the header indicates v1 is not supported.
The peer then receives a malformed CLC proposal where the header type
does not match the payload, and immediately resets the connection.

Fix this by consistently using `pclc_base->hdr.typev1` and
`pclc_base->hdr.typev2`—the authoritative fields that reflect the
actual capabilities advertised in the CLC header—when deciding whether
to include optional extensions, as required by the SMC-R v2
specification ("V1 IP Subnet Extension and V2 Extension only present if
applicable").

Fixes: 8c3dca341aea ("net/smc: build and send V2 CLC proposal")
Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
---
 net/smc/smc_clc.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
index 157aace169d4..d9ff5f433720 100644
--- a/net/smc/smc_clc.c
+++ b/net/smc/smc_clc.c
@@ -922,7 +922,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 				htons(smc_ism_get_chid(ini->ism_dev[0]));
 		}
 	}
-	if (ini->smc_type_v2 == SMC_TYPE_N) {
+	if (pclc_base->hdr.typev2 == SMC_TYPE_N) {
 		pclc_smcd->v2_ext_offset = 0;
 	} else {
 		struct smc_clc_eid_entry *ueident;
@@ -931,7 +931,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 		v2_ext->hdr.flag.release = SMC_RELEASE;
 		v2_ext_offset = sizeof(*pclc_smcd) -
 			offsetofend(struct smc_clc_msg_smcd, v2_ext_offset);
-		if (ini->smc_type_v1 != SMC_TYPE_N)
+		if (pclc_base->hdr.typev1 != SMC_TYPE_N)
 			v2_ext_offset += sizeof(*pclc_prfx) +
 						pclc_prfx->ipv6_prefixes_cnt *
 						sizeof(ipv6_prfx[0]);
@@ -949,7 +949,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 		}
 		read_unlock(&smc_clc_eid_table.lock);
 	}
-	if (smcd_indicated(ini->smc_type_v2)) {
+	if (smcd_indicated(pclc_base->hdr.typev2)) {
 		struct smcd_gid smcd_gid;
 		u8 *eid = NULL;
 		int entry = 0;
@@ -987,7 +987,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 		}
 		v2_ext->hdr.ism_gid_cnt = entry;
 	}
-	if (smcr_indicated(ini->smc_type_v2)) {
+	if (smcr_indicated(pclc_base->hdr.typev2)) {
 		memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE);
 		v2_ext->max_conns = net->smc.sysctl_max_conns_per_lgr;
 		v2_ext->max_links = net->smc.sysctl_max_links_per_lgr;
@@ -1003,7 +1003,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 	vec[i++].iov_len = sizeof(*pclc_base);
 	vec[i].iov_base = pclc_smcd;
 	vec[i++].iov_len = sizeof(*pclc_smcd);
-	if (ini->smc_type_v1 != SMC_TYPE_N) {
+	if (pclc_base->hdr.typev1 != SMC_TYPE_N) {
 		vec[i].iov_base = pclc_prfx;
 		vec[i++].iov_len = sizeof(*pclc_prfx);
 		if (pclc_prfx->ipv6_prefixes_cnt > 0) {
@@ -1012,11 +1012,11 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 					   sizeof(ipv6_prfx[0]);
 		}
 	}
-	if (ini->smc_type_v2 != SMC_TYPE_N) {
+	if (pclc_base->hdr.typev2 != SMC_TYPE_N) {
 		vec[i].iov_base = v2_ext;
 		vec[i++].iov_len = sizeof(*v2_ext) +
 				   (v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN);
-		if (smcd_indicated(ini->smc_type_v2)) {
+		if (smcd_indicated(pclc_base->hdr.typev2)) {
 			vec[i].iov_base = smcd_v2_ext;
 			vec[i++].iov_len = sizeof(*smcd_v2_ext);
 			if (ini->ism_offered_cnt) {
-- 
2.45.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-11-05  7:12 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-31  3:18 [PATCH net] net/smc: fix mismatch between CLC header and proposal extensions D. Wythe
2025-11-03  8:28 ` Alexandra Winter
2025-11-04  7:08   ` D. Wythe
2025-11-04  8:51     ` Alexandra Winter
2025-11-05  7:12       ` D. Wythe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox