Skip to content

Commit ae4a088

Browse files
geertuSudeep Holla
authored andcommitted
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 <geert+renesas@glider.be> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com> Tested-by: Florian Fainelli <florian.fainelli@broadcom.com> Link: https://patch.msgid.link/20260508153300.2224715-12-cristian.marussi@arm.com Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
1 parent 4848d07 commit ae4a088

1 file changed

Lines changed: 7 additions & 2 deletions

File tree

drivers/firmware/arm_scmi/driver.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,7 @@ static int __scmi_iterator_run(void *iter, unsigned int *start, unsigned int *en
18201820
const struct scmi_protocol_handle *ph;
18211821
struct scmi_iterator_state *st;
18221822
struct scmi_iterator *i;
1823+
unsigned int n;
18231824

18241825
if (!iter)
18251826
return -EINVAL;
@@ -1852,13 +1853,17 @@ static int __scmi_iterator_run(void *iter, unsigned int *start, unsigned int *en
18521853
return -EINVAL;
18531854
}
18541855

1855-
for (st->loop_idx = 0; st->loop_idx < st->num_returned; st->loop_idx++) {
1856+
if (end)
1857+
n = min(st->num_returned, *end - st->desc_index + 1);
1858+
else
1859+
n = st->num_returned;
1860+
for (st->loop_idx = 0; st->loop_idx < n; st->loop_idx++) {
18561861
ret = iops->process_response(ph, i->resp, st, i->priv);
18571862
if (ret)
18581863
return ret;
18591864
}
18601865

1861-
st->desc_index += st->num_returned;
1866+
st->desc_index += n;
18621867
ph->xops->reset_rx_to_maxsz(ph, i->t);
18631868
/*
18641869
* check for both returned and remaining to avoid infinite

0 commit comments

Comments
 (0)