Skip to content

Commit 9614b1a

Browse files
committed
mctpd: fix endpoint peer iteration on interface delete
We currently scan through ctx->peers while deleting an interface, removing pertinent peers. However, the removal will shift the indices (and possibly realloc ctx->peers). So, adjust our handling of the loop counter to suit. Fixes: #97 Reported-by: Faizan Ali <[email protected]> Signed-off-by: Jeremy Kerr <[email protected]>
1 parent d7e57ed commit 9614b1a

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## [Unreleased]
88

9+
## Fixed
10+
11+
1. mctpd: fixed an issue where endpoints may persist when their dependent
12+
interface is deleted
13+
914
## [2.2] - 2025-07-28
1015

1116
### Fixed

src/mctpd.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3388,13 +3388,26 @@ static int del_interface(struct link *link)
33883388
if (ctx->verbose) {
33893389
fprintf(stderr, "Deleting interface #%d\n", ifindex);
33903390
}
3391-
for (size_t i = 0; i < ctx->num_peers; i++) {
3391+
for (size_t i = 0; i < ctx->num_peers;) {
33923392
struct peer *p = ctx->peers[i];
3393+
33933394
if (p->state == REMOTE && p->phys.ifindex == ifindex) {
3394-
// Linux removes routes to deleted links, so no need to request removal.
3395+
int rc;
3396+
3397+
// Linux removes routes to deleted links, so no need
3398+
// to request removal.
33953399
p->have_neigh = false;
33963400
p->have_route = false;
3397-
remove_peer(p);
3401+
rc = remove_peer(p);
3402+
if (rc) {
3403+
bug_warn("Error removing peer on interface "
3404+
"deletion, inconsistent state");
3405+
break;
3406+
}
3407+
} else {
3408+
// Removal will shift indices down, only increment
3409+
// while skipping.
3410+
i++;
33983411
}
33993412
}
34003413

tests/test_mctpd.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,44 @@ async def test_del_interface_last(dbus, mctpd):
748748
with pytest.raises(asyncdbus.errors.DBusError):
749749
await mctpd_mctp_network_obj(dbus, iface.net)
750750

751+
""" Delete an interface with peers attached, ensure all are gone """
752+
async def test_del_interface_with_peers(dbus, mctpd):
753+
net = mctpd.system.interfaces[0].net
754+
iface = mctpd.system.Interface(
755+
'mctp1', 2, net, bytes([0x10]), 68, 254, True,
756+
)
757+
await mctpd.system.add_interface(iface)
758+
759+
eps = [
760+
Endpoint(iface, bytes([0x11])),
761+
Endpoint(iface, bytes([0x12])),
762+
Endpoint(iface, bytes([0x13])),
763+
]
764+
765+
mctp = await mctpd_mctp_iface_obj(dbus, iface)
766+
767+
paths = []
768+
for ep in eps:
769+
mctpd.network.add_endpoint(ep)
770+
(eid, _, path, _) = await mctp.call_setup_endpoint(ep.lladdr)
771+
assert eid == ep.eid
772+
paths.append(path)
773+
774+
await mctpd.system.del_interface(iface)
775+
776+
# interface should be gone
777+
with pytest.raises(asyncdbus.errors.DBusError):
778+
await mctpd_mctp_iface_obj(dbus, iface)
779+
780+
# .. but the network should remain, as the default interface is still
781+
# present
782+
_ = await mctpd_mctp_network_obj(dbus, net)
783+
784+
for path in paths:
785+
with pytest.raises(asyncdbus.errors.DBusError) as ex:
786+
ep = await mctpd_mctp_endpoint_common_obj(dbus, path)
787+
assert str(ex.value).startswith("Unknown object")
788+
751789
""" Remove and re-add an interface """
752790
async def test_add_interface(dbus, mctpd):
753791
net = 1

0 commit comments

Comments
 (0)