mctpd: improve handling of out-of-spec Set EID responses

Tested: Manually
Google-Bug-Id: 425989631
Change-Id: I14e1a26cc0325c1d7dbaf0bdd6f382f7d1ad027c
Signed-off-by: Muhammad Usama <muhammadusama@google.com>
diff --git a/recipes-connectivity/mctp/mctp/0002-mctpd-improve-handling-for-out-of-spec-Set-Endpoint.patch b/recipes-connectivity/mctp/mctp/0002-mctpd-improve-handling-for-out-of-spec-Set-Endpoint.patch
new file mode 100644
index 0000000..96f4fb8
--- /dev/null
+++ b/recipes-connectivity/mctp/mctp/0002-mctpd-improve-handling-for-out-of-spec-Set-Endpoint.patch
@@ -0,0 +1,148 @@
+From b81c31dc1c3f137c1c8c27deba5ecf11dfddde6b Mon Sep 17 00:00:00 2001
+From: Muhammad Usama <muhammadusama@google.com>
+Date: Thu, 26 Jun 2025 18:18:21 +0000
+Subject: [PATCH] mctpd: improve handling for out-of-spec Set Endpoint ID
+ responses
+
+We may have endpoints reporting strange EID values in their set endpoint
+ID response, even when reporting that the assignement was accepted.
+Particularly, if the EID is in the invalid range, we will still attempt
+to add neighour and route entries for this invalid EID.
+
+We still want to accommodate valid IDs that were not the same as the one
+assigned, but ensure the EID is valid before processing.
+
+Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
+
+Patch Tracking Bug: b/294943849
+Upstream info / review: https://github.com/CodeConstruct/mctp/commit/2948041a02776e93b84510ed6d310bcce2f2c28e
+Upstream-Status: Submitted
+Justification: Improves stack
+---
+ CHANGELOG.md    |  3 +++
+ src/mctp-util.c |  5 +++++
+ src/mctp-util.h |  4 ++++
+ src/mctpd.c     | 32 +++++++++++++++++++++++++++-----
+ 4 files changed, 39 insertions(+), 5 deletions(-)
+
+diff --git a/CHANGELOG.md b/CHANGELOG.md
+index ac03224..b9a4de3 100644
+--- a/CHANGELOG.md
++++ b/CHANGELOG.md
+@@ -12,6 +12,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+ 2. mctpd: Allow recovery of devices reporting a nil UUID for development
+ 3. mctpd: Allow configuring .Connectivity as writable for development
+ 4. mctpd: Add AssignEndpointStatic for static EID allocations
++5. mctpd: Better handling of strange cases of Set Endpoint ID responses,Add commentMore actions
++   where the reported endpoint EID may either be different from expected,
++   or invalid
+ 
+ ### Changed
+ 
+diff --git a/src/mctp-util.c b/src/mctp-util.c
+index 5226718..4964a7c 100644
+--- a/src/mctp-util.c
++++ b/src/mctp-util.c
+@@ -156,3 +156,8 @@ char* bytes_to_uuid(const uint8_t u[16])
+ 		u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15]);
+ 	return buf;
+ }
++
++bool mctp_eid_is_valid_unicast(mctp_eid_t eid)
++{
++	return eid >= 8 && eid < 0xff;
++}
+\ No newline at end of file
+diff --git a/src/mctp-util.h b/src/mctp-util.h
+index 3089299..7423965 100644
+--- a/src/mctp-util.h
++++ b/src/mctp-util.h
+@@ -1,5 +1,8 @@
++#include <stdbool.h>
+ #include <stdint.h>
+ 
++#include "mctp.h"
++
+ void mctp_hexdump(const void *b, int len, const char *indent);
+ void print_hex_addr(const uint8_t *data, size_t len);
+ int write_hex_addr(const uint8_t *data, size_t len, char* dest, size_t dest_len);
+@@ -8,3 +11,4 @@ int parse_uint32(const char *str, uint32_t *out);
+ int parse_int32(const char *str, int32_t *out);
+ /* Returns a malloced pointer */
+ char* bytes_to_uuid(const uint8_t u[16]);
++bool mctp_eid_is_valid_unicast(mctp_eid_t eid);
+diff --git a/src/mctpd.c b/src/mctpd.c
+index 978f2b8..3cee0a3 100644
+--- a/src/mctpd.c
++++ b/src/mctpd.c
+@@ -1090,7 +1090,7 @@ static int endpoint_query_phys(ctx *ctx, const dest_phys *dest,
+ }
+ 
+ /* returns -ECONNREFUSED if the endpoint returns failure. */
+-static int endpoint_send_set_endpoint_id(const peer *peer, mctp_eid_t *new_eid)
++static int endpoint_send_set_endpoint_id(const peer *peer, mctp_eid_t *new_eidp)
+ {
+ 	struct sockaddr_mctp_ext addr;
+ 	struct mctp_ctrl_cmd_set_eid req = {0};
+@@ -1100,6 +1100,7 @@ static int endpoint_send_set_endpoint_id(const peer *peer, mctp_eid_t *new_eid)
+ 	size_t buf_size;
+ 	uint8_t stat, alloc;
+ 	const dest_phys *dest = &peer->phys;
++	mctp_eid_t new_eid;
+ 
+ 	rc = -1;
+ 
+@@ -1129,18 +1130,36 @@ static int endpoint_send_set_endpoint_id(const peer *peer, mctp_eid_t *new_eid)
+ 	}
+ 
+ 	stat = resp->status >> 4 & 0x3;
++	new_eid = resp->eid_set;
++
++	// For both accepted and rejected cases, we learn the new EID of the
++	// endpoint. If this is a valid ID, we are likely to be able to handle
++	// this, as the caller may be able to change_peer_eid() to the
++	// newly-reported eid
++
+ 	if (stat == 0x01) {
+ 		// changed eid
++			if (!mctp_eid_is_valid_unicast(new_eid)) {
++			warnx("%s rejected assignment eid %d, and reported invalid eid %d",
++				dest_phys_tostr(dest), peer->eid, new_eid);
++			rc = -ECONNREFUSED;
++			goto out;
++		}
+ 	} else if (stat == 0x00) {
+-		if (resp->eid_set != peer->eid) {
++		if (!mctp_eid_is_valid_unicast(new_eid)) {
++			warnx("%s eid %d replied with invalid eid %d, but 'accepted'",
++				dest_phys_tostr(dest), peer->eid, new_eid);
++			rc = -ECONNREFUSED;
++			goto out;
++		} else if (new_eid != peer->eid) {
+ 			warnx("%s eid %d replied with different eid %d, but 'accepted'",
+-				dest_phys_tostr(dest), peer->eid, resp->eid_set);
+-		}
++				dest_phys_tostr(dest), peer->eid, new_eid);
++			}
+ 	} else {
+ 		warnx("%s unexpected status 0x%02x",
+ 			dest_phys_tostr(dest), resp->status);
+ 	}
+-	*new_eid = resp->eid_set;
++	*new_eidp = new_eid;
+ 
+ 	alloc = resp->status & 0x3;
+ 	if (alloc != 0) {
+@@ -1300,6 +1319,9 @@ static int remove_peer(peer *peer)
+ static int change_peer_eid(peer *peer, mctp_eid_t new_eid) {
+ 	net_det *n = NULL;
+ 
++	if (!mctp_eid_is_valid_unicast(new_eid))
++		return -EINVAL;
++
+ 	n = lookup_net(peer->ctx, peer->net);
+ 	if (!n) {
+ 		warnx("BUG: %s: Bad net %d", __func__, peer->net);
+-- 
+2.50.0.727.gbf7dc18ff4-goog
+
diff --git a/recipes-connectivity/mctp/mctp_%.bbappend b/recipes-connectivity/mctp/mctp_%.bbappend
index 7a0234e..1ec7dbe 100644
--- a/recipes-connectivity/mctp/mctp_%.bbappend
+++ b/recipes-connectivity/mctp/mctp_%.bbappend
@@ -3,6 +3,7 @@
 SRCREV:gbmc = "d791d1de4ad5ddb71acf896c65e0a6c18a87b5ca"
 SRC_URI:append:gbmc = " \
   file://0001-mctpd-Set-initial-route-MTU-to-minimum.patch \
+  file://0002-mctpd-improve-handling-for-out-of-spec-Set-Endpoint.patch \
   file://mctp-i2c.service \
   file://init-mctp-i2c-endpoint.sh \
   file://service-override.conf \