* [PATCH 1/3] firmware: arm_scmi: Fix OOB in scmi_clock_describe_rates_get_lazy()
2026-03-23 16:56 [PATCH 0/3] firmware: arm_scmi: Lazy clock rates and bound iterator fixes Geert Uytterhoeven
@ 2026-03-23 16:56 ` Geert Uytterhoeven
2026-03-23 16:56 ` [PATCH 2/3] firmware: arm_scmi: Fix bound iterators returning too many items Geert Uytterhoeven
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Geert Uytterhoeven @ 2026-03-23 16:56 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Marek Vasut
Cc: arm-scmi, linux-arm-kernel, linux-renesas-soc, linux-kernel,
Geert Uytterhoeven
Lazy discovery of discrete rates works as follows:
A. Grab the first three rates,
B. Grab the last rate, if there are more than three rates.
It is up to the SCMI provider implementation to decide how many rates
are returned in response to a single CLOCK_DESCRIBE_RATES command. Each
rate received is stored in the scmi_clock_rates.rates[] array, and
.num_rates is updated accordingly.
When more than 3 rates have been received after step A, the last rate
may have been received already, and stored in scmi_clock_rates.rates[]
(which has space for scmi_clock_desc.tot_rates entries). Hence grabbing
the last rate again will store it a second time, beyond the end of the
array.
Fix this by only grabbing the last rate when we don't already have it.
Fixes: a78da552c6f3bff5 ("firmware: arm_scmi: Use bound iterators to minimize discovered rates")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
This bug caused random "kernel BUG at drivers/base/devres.c:135!"
crashes during boot on R-Car X5H.
Example for a clock with 8 rates, which are all returned in response to
a single CLOCK_DESCRIBE_RATES command:
scmi_clock_describe_rates_get_lazy: Grabbing rates 0..2
iter_clk_describe_update_state: Returned 8 remaining 0
iter_clk_describe_update_state: Allocating 8 rates
iter_clk_describe_process_response: rates[0] = 33333333
iter_clk_describe_process_response: rates[1] = 66666666
iter_clk_describe_process_response: rates[2] = 133333333
iter_clk_describe_process_response: rates[3] = 266666666
iter_clk_describe_process_response: rates[4] = 355555555
iter_clk_describe_process_response: rates[5] = 533333333
iter_clk_describe_process_response: rates[6] = 711111111
iter_clk_describe_process_response: rates[7] = 1066666666
^^^^^^^^^^
scmi_clock_describe_rates_get_lazy: Grabbing rates 7..7
iter_clk_describe_update_state: Returned 1 remaining 0
iter_clk_describe_process_response: rates[8] = 1066666666
^ ^^^^^^^^^^
Out of bounds access! ------------------------+ |
Same value as [7] ---------------------------------+
drivers/firmware/arm_scmi/clock.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index 0e7e341171aad829..623dbc2f1e09303d 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -593,8 +593,11 @@ scmi_clock_describe_rates_get_lazy(const struct scmi_protocol_handle *ph,
if (ret)
goto out;
- /* If discrete grab the last value, which should be the max */
- if (clkd->r.rate_discrete && clkd->tot_rates > 3) {
+ /*
+ * If discrete and we don't already have it, grab the last value, which
+ * should be the max
+ */
+ if (clkd->r.rate_discrete && clkd->tot_rates > clkd->r.num_rates) {
first = clkd->tot_rates - 1;
last = clkd->tot_rates - 1;
ret = ph->hops->iter_response_run_bound(iter, &first, &last);
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/3] firmware: arm_scmi: Fix bound iterators returning too many items
2026-03-23 16:56 [PATCH 0/3] firmware: arm_scmi: Lazy clock rates and bound iterator fixes Geert Uytterhoeven
2026-03-23 16:56 ` [PATCH 1/3] firmware: arm_scmi: Fix OOB in scmi_clock_describe_rates_get_lazy() Geert Uytterhoeven
@ 2026-03-23 16:56 ` Geert Uytterhoeven
2026-03-23 16:56 ` [PATCH 3/3] firmware: arm_scmi: Use proper iter_response_bound_cleanup() name Geert Uytterhoeven
2026-03-23 18:02 ` [PATCH 0/3] firmware: arm_scmi: Lazy clock rates and bound iterator fixes Cristian Marussi
3 siblings, 0 replies; 5+ messages in thread
From: Geert Uytterhoeven @ 2026-03-23 16:56 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Marek Vasut
Cc: arm-scmi, linux-arm-kernel, linux-renesas-soc, linux-kernel,
Geert Uytterhoeven
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.
Fixes: 13289addf5a52e1f ("firmware: arm_scmi: Add bound iterators support")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
This caused random "kernel BUG at drivers/base/devres.c:135!" crashes
during boot on R-Car X5H, as lazy clock rate discovery does not handle
correctly receiving more rates than expected.
Example for a clock with 8 rates, which are all returned in response to
a single CLOCK_DESCRIBE_RATES command:
scmi_clock_describe_rates_get_lazy: Grabbing rates 0..2
iter_clk_describe_update_state: Returned 8 remaining 0
iter_clk_describe_update_state: Allocating 8 rates
iter_clk_describe_process_response: rates[0] = 33333333
iter_clk_describe_process_response: rates[1] = 66666666
iter_clk_describe_process_response: rates[2] = 133333333
iter_clk_describe_process_response: rates[3] = 266666666
iter_clk_describe_process_response: rates[4] = 355555555
iter_clk_describe_process_response: rates[5] = 533333333
iter_clk_describe_process_response: rates[6] = 711111111
iter_clk_describe_process_response: rates[7] = 1066666666
^^^^^^^^^^
Rates [3] to [7] are received, despite being outside the bound.
scmi_clock_describe_rates_get_lazy: Grabbing rates 7..7
iter_clk_describe_update_state: Returned 1 remaining 0
iter_clk_describe_process_response: rates[8] = 1066666666
^ ^^^^^^^^^^
Out of bounds access! ------------------------+ |
Same value as [7] ---------------------------------+
---
drivers/firmware/arm_scmi/driver.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 2a9183686203b4e7..03fd7caa8b42a12c 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
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/3] firmware: arm_scmi: Use proper iter_response_bound_cleanup() name
2026-03-23 16:56 [PATCH 0/3] firmware: arm_scmi: Lazy clock rates and bound iterator fixes Geert Uytterhoeven
2026-03-23 16:56 ` [PATCH 1/3] firmware: arm_scmi: Fix OOB in scmi_clock_describe_rates_get_lazy() Geert Uytterhoeven
2026-03-23 16:56 ` [PATCH 2/3] firmware: arm_scmi: Fix bound iterators returning too many items Geert Uytterhoeven
@ 2026-03-23 16:56 ` Geert Uytterhoeven
2026-03-23 18:02 ` [PATCH 0/3] firmware: arm_scmi: Lazy clock rates and bound iterator fixes Cristian Marussi
3 siblings, 0 replies; 5+ messages in thread
From: Geert Uytterhoeven @ 2026-03-23 16:56 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Marek Vasut
Cc: arm-scmi, linux-arm-kernel, linux-renesas-soc, linux-kernel,
Geert Uytterhoeven
The documentation speaks of the "iter_response_bound_cleanup()" protocol
helper, while the actual helper is called "iter_response_cleanup()".
Settle on the former name, because the helper is only needed when using
bound-iterators.
Fixes: 13289addf5a52e1f ("firmware: arm_scmi: Add bound iterators support")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/firmware/arm_scmi/clock.c | 2 +-
drivers/firmware/arm_scmi/driver.c | 6 +++---
drivers/firmware/arm_scmi/protocols.h | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index 623dbc2f1e09303d..0205b37d219a88ed 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -604,7 +604,7 @@ scmi_clock_describe_rates_get_lazy(const struct scmi_protocol_handle *ph,
}
out:
- ph->hops->iter_response_cleanup(iter);
+ ph->hops->iter_response_bound_cleanup(iter);
return ret;
}
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 03fd7caa8b42a12c..bfcc3e3c931dc9cc 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1875,7 +1875,7 @@ static int __scmi_iterator_run(void *iter, unsigned int *start, unsigned int *en
return 0;
}
-static void scmi_iterator_cleanup(void *iter)
+static void scmi_iterator_bound_cleanup(void *iter)
{
struct scmi_iterator *i = iter;
@@ -1888,7 +1888,7 @@ static int scmi_iterator_run(void *iter)
int ret;
ret = __scmi_iterator_run(iter, NULL, NULL);
- scmi_iterator_cleanup(iter);
+ scmi_iterator_bound_cleanup(iter);
return ret;
}
@@ -2078,7 +2078,7 @@ static const struct scmi_proto_helpers_ops helpers_ops = {
.iter_response_init = scmi_iterator_init,
.iter_response_run = scmi_iterator_run,
.iter_response_run_bound = scmi_iterator_run_bound,
- .iter_response_cleanup = scmi_iterator_cleanup,
+ .iter_response_bound_cleanup = scmi_iterator_bound_cleanup,
.protocol_msg_check = scmi_protocol_msg_check,
.fastchannel_init = scmi_common_fastchannel_init,
.fastchannel_db_ring = scmi_common_fastchannel_db_ring,
diff --git a/drivers/firmware/arm_scmi/protocols.h b/drivers/firmware/arm_scmi/protocols.h
index e2ef604c16ef6771..15ad5162e37a90ec 100644
--- a/drivers/firmware/arm_scmi/protocols.h
+++ b/drivers/firmware/arm_scmi/protocols.h
@@ -286,7 +286,7 @@ struct scmi_proto_helpers_ops {
int (*iter_response_run)(void *iter);
int (*iter_response_run_bound)(void *iter,
unsigned int *start, unsigned int *end);
- void (*iter_response_cleanup)(void *iter);
+ void (*iter_response_bound_cleanup)(void *iter);
int (*protocol_msg_check)(const struct scmi_protocol_handle *ph,
u32 message_id, u32 *attributes);
void (*fastchannel_init)(const struct scmi_protocol_handle *ph,
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 0/3] firmware: arm_scmi: Lazy clock rates and bound iterator fixes
2026-03-23 16:56 [PATCH 0/3] firmware: arm_scmi: Lazy clock rates and bound iterator fixes Geert Uytterhoeven
` (2 preceding siblings ...)
2026-03-23 16:56 ` [PATCH 3/3] firmware: arm_scmi: Use proper iter_response_bound_cleanup() name Geert Uytterhoeven
@ 2026-03-23 18:02 ` Cristian Marussi
3 siblings, 0 replies; 5+ messages in thread
From: Cristian Marussi @ 2026-03-23 18:02 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Sudeep Holla, Cristian Marussi, Marek Vasut, arm-scmi,
linux-arm-kernel, linux-renesas-soc, linux-kernel
On Mon, Mar 23, 2026 at 05:56:09PM +0100, Geert Uytterhoeven wrote:
> Hi all,
Hi Geert,
>
> This patch series:
> - Fixes an out-of-bound access in lazy clock rate handling,
> - Synchronizes bound-iterator cleanup naming between documentation and
> code.
thanks for this !
I was just chasing down exactly the same issue, since it was flagged by
our CI on a rockchip board (together with some KASAN splat...)...but I had
still to manage to get my hands directly on that board to start
debugging properly ... so ...
... very happy that you beat me at this:P !
While waiting for the board and trying to figure out what could cause
the fatal issue I spotted something more to be rectified in the core of
the iterators, BUT I dont think it would have solved the issue like your
fixes.
In a nutshell, it was the possibility of an integer undeflow due to an
unchecked subtraction between unsigned.
---8<---
commit 65bd4a11333098fbf4c60f3bc59c971be1cd259d (mygitlab/scmi_dev, scmi_dev)
Author: Cristian Marussi <cristian.marussi@arm.com>
Date: Mon Mar 23 08:19:32 2026 +0000
[TODO] FIX Iterator boundary checking
[TODO] FIX Iterator boundary checking
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 8b5f477758a0..562977438e60 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1845,7 +1845,7 @@ static int __scmi_iterator_run(void *iter, unsigned int *start, unsigned int *en
if (ret)
return ret;
- if (st->num_returned > st->max_resources - st->desc_index) {
+ if (st->num_returned + st->desc_index > st->max_resources) {
dev_err(ph->dev,
"No. of resources can't exceed %d\n",
st->max_resources);
---8<----
Anyway, next dsys I will test all of this with your series, but since my
original series indeed was on hold now due to these issues AND because still
lacking clock-MAINTs acks, I am not sure if:
- we'll merge your fixes into my series while maintaining of course your
authorship (instead of applying the series on top)
- Sudeep will still queue any of this for this cycle
Thanks a lot for the debug and fixes to my cr...y stuff :P
Cristian
^ permalink raw reply related [flat|nested] 5+ messages in thread