From: Geert Uytterhoeven Date: Fri, 8 May 2026 15:32:56 +0000 (+0100) Subject: firmware: arm_scmi: Fix bound iterators returning too many items X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=ae4a088f13debc1d7bbb6a9b265a31d25b60ddd4;p=thirdparty%2Fkernel%2Flinux.git firmware: arm_scmi: Fix bound iterators returning too many items When using a bound-iterator with an upper bound, commands are sent, and responses are received, until the upper bound is reached. However, it is up to the SCMI provider implementation to decide how many rates are returned in response to a single CLOCK_DESCRIBE_RATES command. If the last response contains rates beyond the specified upper bound, they are still passed up for further processing. This may lead to buffer overflows in unprepared callsites. While the imprecise bound handling may have been intentional (it was mentioned in the commit message introducing the code), it is still confusing for users, and may cause hard to debug crashes. Fix this by strictly enforcing the upper bound. Note that this may cause an increase in the number of CLOCK_DESCRIBE_RATES commands issued, as retrieving the last rate may no longer be done inadvertentently, but require its own command. Signed-off-by: Geert Uytterhoeven Signed-off-by: Cristian Marussi Tested-by: Florian Fainelli Link: https://patch.msgid.link/20260508153300.2224715-12-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index a59d8f9219ed1..595ce7b33c612 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1820,6 +1820,7 @@ static int __scmi_iterator_run(void *iter, unsigned int *start, unsigned int *en const struct scmi_protocol_handle *ph; struct scmi_iterator_state *st; struct scmi_iterator *i; + unsigned int n; if (!iter) return -EINVAL; @@ -1852,13 +1853,17 @@ static int __scmi_iterator_run(void *iter, unsigned int *start, unsigned int *en return -EINVAL; } - for (st->loop_idx = 0; st->loop_idx < st->num_returned; st->loop_idx++) { + if (end) + n = min(st->num_returned, *end - st->desc_index + 1); + else + n = st->num_returned; + for (st->loop_idx = 0; st->loop_idx < n; st->loop_idx++) { ret = iops->process_response(ph, i->resp, st, i->priv); if (ret) return ret; } - st->desc_index += st->num_returned; + st->desc_index += n; ph->xops->reset_rx_to_maxsz(ph, i->t); /* * check for both returned and remaining to avoid infinite