On Thu, Jun 25, 2026 at 09:00:56PM +0800, Maoyi Xie wrote: > cros_typec_register_partner_pdos() copies the partner PDOs from the EC > TYPEC_STATUS response into the fixed caps_desc.pdo[PDO_MAX_OBJECTS] array. > > memcpy(caps_desc.pdo, resp->source_cap_pdos, > sizeof(u32) * resp->source_cap_count); > ... > memcpy(caps_desc.pdo, resp->sink_cap_pdos, > sizeof(u32) * resp->sink_cap_count); > > PDO_MAX_OBJECTS is 7. source_cap_count and sink_cap_count are u8 fields > from the EC. The only check is that they are not both zero. If either is > larger than 7, the memcpy writes past the end of the array on the stack. > A count of 255 overflows it by about 1 KB. The EC source arrays are only > seven entries wide. A larger count reads past them too. > > The ChromeOS EC firmware caps these counts today, so a compliant setup > does not hit this. The kernel should still validate these values rather > than trust them. > > Validate the counts in cros_typec_register_partner_pdos() next to the > memcpy. Skip the PDO registration if either count is above PDO_MAX_OBJECTS. > The rest of cros_typec_handle_status() still runs so events are handled > and cleared. > > Fixes: 348a2e8c93d3 ("platform/chrome: cros_ec_typec: Register partner PDOs") > Suggested-by: Tzung-Bi Shih > Suggested-by: Andrei Kuchynski > Co-developed-by: Kaixuan Li > Signed-off-by: Kaixuan Li > Signed-off-by: Maoyi Xie Reviewed-by: Benson Leung > --- > v2: Move the check into cros_typec_register_partner_pdos() next to the > memcpy it guards. v1 put it at the top of cros_typec_handle_status() > and returned early. That skipped the rest of the status handling and > left events uncleared. > > v1: https://lore.kernel.org/r/178229037114.3009621.14045345257767446805@maoyixie.com > > drivers/platform/chrome/cros_ec_typec.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c > index c0806c562bb9..50a68819ceb7 100644 > --- a/drivers/platform/chrome/cros_ec_typec.c > +++ b/drivers/platform/chrome/cros_ec_typec.c > @@ -1119,6 +1119,12 @@ static void cros_typec_register_partner_pdos(struct cros_typec_data *typec, > if (!resp->source_cap_count && !resp->sink_cap_count) > return; > > + if (resp->source_cap_count > PDO_MAX_OBJECTS || > + resp->sink_cap_count > PDO_MAX_OBJECTS) { > + dev_warn(typec->dev, "Invalid PDO count from EC, port: %d\n", port_num); > + return; > + } > + > port->partner_pd = typec_partner_usb_power_delivery_register(port->partner, &desc); > if (IS_ERR(port->partner_pd)) { > dev_warn(typec->dev, "Failed to register partner PD device, port: %d\n", port_num);