From nobody Fri Apr 3 16:08:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 22B1B3C1979; Mon, 23 Mar 2026 16:56:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774284980; cv=none; b=ch6/vUhYzigrAEiwNF9AtQhPqCkmFpypbQLfGqw7/7DnVjIAT35BZX7u3bs6cmgLQbWVQCBpIEDP5rvMP9cE45nz7RKi8Fx3zUW+Ij1IEplREk4UnrTdvais3oT6s+5idrScnEujGDmgdJRnm4ZxDJFnH97pGiHK9yd0p8bRnIo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774284980; c=relaxed/simple; bh=XCEil2lJ9uatdL21iFJ//WE04pfJLH2pZc1geIn4+gs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NkrsBMkzyxIyY5fc3nrtba0LoZyekFvPAzoBMtrlGcFtAPcm+JbOnyum2pPHIhIa9Z8nWPx0Ex0gX0zeqLj91IOSlKxYPRJi0ZmeO5cZ1j53P6Lhydf8HQ0onvm0P63RGWtBy276F9kQNNxuhOAL7QV1B6ljgxeEooRsPhh8Eig= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 18083C2BC9E; Mon, 23 Mar 2026 16:56:17 +0000 (UTC) From: Geert Uytterhoeven To: Sudeep Holla , Cristian Marussi , Marek Vasut Cc: arm-scmi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Geert Uytterhoeven Subject: [PATCH 1/3] firmware: arm_scmi: Fix OOB in scmi_clock_describe_rates_get_lazy() Date: Mon, 23 Mar 2026 17:56:10 +0100 Message-ID: <9928133be47a09af0c568bcee0f9a987381a1c15.1774283748.git.geert+renesas@glider.be> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 minimi= ze discovered rates") Signed-off-by: Geert Uytterhoeven --- 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] =3D 33333333 iter_clk_describe_process_response: rates[1] =3D 66666666 iter_clk_describe_process_response: rates[2] =3D 133333333 iter_clk_describe_process_response: rates[3] =3D 266666666 iter_clk_describe_process_response: rates[4] =3D 355555555 iter_clk_describe_process_response: rates[5] =3D 533333333 iter_clk_describe_process_response: rates[6] =3D 711111111 iter_clk_describe_process_response: rates[7] =3D 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] =3D 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_p= rotocol_handle *ph, if (ret) goto out; =20 - /* 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 =3D clkd->tot_rates - 1; last =3D clkd->tot_rates - 1; ret =3D ph->hops->iter_response_run_bound(iter, &first, &last); --=20 2.43.0 From nobody Fri Apr 3 16:08:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C69D3C1410; Mon, 23 Mar 2026 16:56:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774284982; cv=none; b=u6DuABwoB5ov4WzXlSsWgHJjDZtP8/OAoU4RgQKOCyLLtn4YLcrhIQ3Z9+YLvuuZ3GWhPLAKGZ+lXfGYiY8yYX43nT2PC/B8+a5i6vFXg/APJZZKjPk8xa7RdJ3+CbzFqlfMwidY033EKMNlWeARARsAbLlbcdlpsXf8xSsrxyw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774284982; c=relaxed/simple; bh=y1/A89083KM2LkOVz+hiOs3Z+ZSJaIXCcI9AB7ibEHc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ilpKDjD0TflVBwghugLBoe2yzGAE3pVX6bcWyVBCqMflRDbF0KN8U7GRp86HDnmS0e4bDmSZXuV0LiOuS9ZlERdjQRESHE1oQLbfcjfAW+Pdp9hPGgCiruwmodgNIbb+x7Y10jcpB2+3MN9lt1+FBg3hx94Ubl0UdPRkYZqweZg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2C011C2BCB0; Mon, 23 Mar 2026 16:56:20 +0000 (UTC) From: Geert Uytterhoeven To: Sudeep Holla , Cristian Marussi , Marek Vasut Cc: arm-scmi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Geert Uytterhoeven Subject: [PATCH 2/3] firmware: arm_scmi: Fix bound iterators returning too many items Date: Mon, 23 Mar 2026 17:56:11 +0100 Message-ID: <8d9f0630e7ef2e3415df9800b6d9459063034977.1774283748.git.geert+renesas@glider.be> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- 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] =3D 33333333 iter_clk_describe_process_response: rates[1] =3D 66666666 iter_clk_describe_process_response: rates[2] =3D 133333333 iter_clk_describe_process_response: rates[3] =3D 266666666 iter_clk_describe_process_response: rates[4] =3D 355555555 iter_clk_describe_process_response: rates[5] =3D 533333333 iter_clk_describe_process_response: rates[6] =3D 711111111 iter_clk_describe_process_response: rates[7] =3D 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] =3D 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 i= nt *start, unsigned int *en const struct scmi_protocol_handle *ph; struct scmi_iterator_state *st; struct scmi_iterator *i; + unsigned int n; =20 if (!iter) return -EINVAL; @@ -1852,13 +1853,17 @@ static int __scmi_iterator_run(void *iter, unsigned= int *start, unsigned int *en return -EINVAL; } =20 - for (st->loop_idx =3D 0; st->loop_idx < st->num_returned; st->loop_idx++= ) { + if (end) + n =3D min(st->num_returned, *end - st->desc_index + 1); + else + n =3D st->num_returned; + for (st->loop_idx =3D 0; st->loop_idx < n; st->loop_idx++) { ret =3D iops->process_response(ph, i->resp, st, i->priv); if (ret) return ret; } =20 - st->desc_index +=3D st->num_returned; + st->desc_index +=3D n; ph->xops->reset_rx_to_maxsz(ph, i->t); /* * check for both returned and remaining to avoid infinite --=20 2.43.0 From nobody Fri Apr 3 16:08:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 313BA3C140D; Mon, 23 Mar 2026 16:56:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774284984; cv=none; b=r1l3SBEjvDSNLCKw5AV01MGZM6jufHrWJbak5WMJ0crVSygSZ8/PXxWX3ETqGKreg/9/Uh4zSUjTt7MHoqzYtpz4AKp8PxvMrLjkRMJKKL4tzU9Fcj8nUhW4U2bDzld1gw8GePR7wYGyDAhKSApIxxtZ2ihE0CBh53zceqxmLnE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774284984; c=relaxed/simple; bh=DlrDh0sXfpGleGJNkZAVP/G29Qv4UHj2GZJhraYhhAU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=h1XkJ6UByA19cfSXOLmIBU/caHuLCueygOn+rloB+S8JhXC830pSmTthJ7ofDHxKxwir0IE33hAkWl/XnQk7fFPdCkfiW9wMNLztz3VDQVnS0Bpt4OVHdYLcNQwHz9JC7C4M0aSBHEscnDrb7IUql26cDQLuj0mMo0NZI38aSTs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3FFF9C2BC9E; Mon, 23 Mar 2026 16:56:22 +0000 (UTC) From: Geert Uytterhoeven To: Sudeep Holla , Cristian Marussi , Marek Vasut Cc: arm-scmi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Geert Uytterhoeven Subject: [PATCH 3/3] firmware: arm_scmi: Use proper iter_response_bound_cleanup() name Date: Mon, 23 Mar 2026 17:56:12 +0100 Message-ID: X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- 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_pr= otocol_handle *ph, } =20 out: - ph->hops->iter_response_cleanup(iter); + ph->hops->iter_response_bound_cleanup(iter); =20 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 i= nt *start, unsigned int *en return 0; } =20 -static void scmi_iterator_cleanup(void *iter) +static void scmi_iterator_bound_cleanup(void *iter) { struct scmi_iterator *i =3D iter; =20 @@ -1888,7 +1888,7 @@ static int scmi_iterator_run(void *iter) int ret; =20 ret =3D __scmi_iterator_run(iter, NULL, NULL); - scmi_iterator_cleanup(iter); + scmi_iterator_bound_cleanup(iter); =20 return ret; } @@ -2078,7 +2078,7 @@ static const struct scmi_proto_helpers_ops helpers_op= s =3D { .iter_response_init =3D scmi_iterator_init, .iter_response_run =3D scmi_iterator_run, .iter_response_run_bound =3D scmi_iterator_run_bound, - .iter_response_cleanup =3D scmi_iterator_cleanup, + .iter_response_bound_cleanup =3D scmi_iterator_bound_cleanup, .protocol_msg_check =3D scmi_protocol_msg_check, .fastchannel_init =3D scmi_common_fastchannel_init, .fastchannel_db_ring =3D scmi_common_fastchannel_db_ring, diff --git a/drivers/firmware/arm_scmi/protocols.h b/drivers/firmware/arm_s= cmi/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, --=20 2.43.0