Skip to content

Commit a9acf18

Browse files
committed
mctpd: prevent endless VDM query & allocation
Commit cb182be ("mctpd: Add VendorDefinedMessageTypes property") did not check the returned response selector against anything other than 0xff, so a remote endpoint could cause a repeated allocation of vdm types. Keep track of the selector we requested, and ensure that the response is as expected (ie, either +1 or 0xff). Add a test for a repeated selector behaviour. Fixes: cb182be ("mctpd: Add VendorDefinedMessageTypes property") Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
1 parent cb182be commit a9acf18

2 files changed

Lines changed: 36 additions & 6 deletions

File tree

src/mctpd.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2598,17 +2598,17 @@ static int query_get_peer_vdm_types(struct peer *peer)
25982598
size_t buf_size, expect_size, new_size, num_vdm_types = 0;
25992599
struct mctp_ctrl_resp_get_vdm_support *resp = NULL;
26002600
struct mctp_ctrl_cmd_get_vdm_support req;
2601+
uint8_t selector, iid, fmt, *buf = NULL;
26012602
struct mctp_vdm_pcie_data *vdm_pcie;
26022603
struct mctp_vdm_iana_data *vdm_iana;
26032604
struct sockaddr_mctp_ext addr;
2604-
uint8_t iid, fmt, *buf = NULL;
26052605
int rc;
26062606

26072607
req.ctrl_hdr.command_code = MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT;
2608-
req.vendor_id_set_selector = 0;
26092608

2610-
while (true) {
2609+
for (selector = 0;; selector++) {
26112610
iid = mctp_next_iid(peer->ctx);
2611+
req.vendor_id_set_selector = selector;
26122612

26132613
mctp_ctrl_msg_hdr_init_req(
26142614
&req.ctrl_hdr, iid,
@@ -2681,10 +2681,16 @@ static int query_get_peer_vdm_types(struct peer *peer)
26812681
peer->num_vdm_types = num_vdm_types;
26822682
rc = 0;
26832683
break;
2684+
} else if (resp->vendor_id_set_selector != selector + 1) {
2685+
/* DSP0236 requires set selectors to be monotonically
2686+
* increasing by 1 */
2687+
warnx("peer %s reporting invalid VDM selector 0x%02x, "
2688+
"expected 0x%02x",
2689+
peer_tostr_short(peer),
2690+
resp->vendor_id_set_selector, selector + 1);
2691+
rc = -EPROTO;
2692+
break;
26842693
}
2685-
2686-
/* Use the next selector from the response. 0xFF indicates no more entries */
2687-
req.vendor_id_set_selector = resp->vendor_id_set_selector;
26882694
}
26892695

26902696
free(buf);

tests/test_mctpd.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,30 @@ async def test_query_vdm_types_unsupported(dbus, mctpd):
749749
await _assert_vdm_types_empty(dbus, mctp, ep)
750750

751751

752+
async def test_query_vdm_types_repeating(dbus, mctpd):
753+
"""Test that we need to be increasing the VDM set selector: otherwise
754+
a peer may send infinite VDM types
755+
"""
756+
757+
class RepeatingVDMEndpoint(Endpoint):
758+
async def handle_mctp_control(self, sock, addr, data):
759+
flags, opcode = data[0:2]
760+
if opcode != 0x06:
761+
return await super().handle_mctp_control(sock, addr, data)
762+
iid = flags & 0x1F
763+
raddr = MCTPSockAddr.for_ep_resp(self, addr, sock.addr_ext)
764+
hdr = [iid, opcode]
765+
# always report a next selector of 1
766+
resp = hdr + [0x00, 0x01, 0x00, 0xAA, 0xBB, 0xCC, 0xDD]
767+
await sock.send(raddr, bytes(resp))
768+
769+
iface = mctpd.system.interfaces[0]
770+
mctp = await mctpd_mctp_iface_obj(dbus, iface)
771+
ep = RepeatingVDMEndpoint(iface, bytes([0x21]), eid=18, vdm_msg_types=None)
772+
mctpd.network.add_endpoint(ep)
773+
await _assert_vdm_types_empty(dbus, mctp, ep)
774+
775+
752776
async def test_network_local_eids_single(dbus, mctpd):
753777
"""Network1.LocalEIDs should reflect locally-assigned EID state"""
754778
iface = mctpd.system.interfaces[0]

0 commit comments

Comments
 (0)