* [PATCH v2 1/3] soc: qcom: smp2p: Fix use-after-free of irq domain on removal
@ 2026-11-02 13:35 Krzysztof Kozlowski
2026-11-02 13:35 ` [PATCH v2 2/3] soc: qcom: smp2p: Fix out-of-bounds with incorrect DTB of too many outbound entries Krzysztof Kozlowski
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Krzysztof Kozlowski @ 2026-11-02 13:35 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Abel Vesa, Andy Gross, Chris Lew,
Deepak Kumar Singh, linux-arm-msm, linux-kernel
Cc: Krzysztof Kozlowski, Sashiko, stable
The SMP2P interrupt is requested with devm_request_threaded_irq(), so it
is freed only after qcom_smp2p_remove() returns or, in the probe error
path, after probe returns. Both paths, however, explicitly remove the
inbound irq domains, unregister outbound SMEM states and free the
mailbox channel before that.
If the interrupt is triggered in this window, the interrupt handler
would use previously freed data. Mixing manual probe() cleanup
and resource-managed devm leads to such races, thus just convert
as much as possible to devm to fix the issue and make code simpler.
Note that for_each_available_child_of_node_scoped() loop, before
registering qcom_smp2p_unwind_interfaces_action() cleanup action, still
uses manual unwind, because it allocates the "entry" memory which is
used by the action itself.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/bug/linux-02cea59a-8c4a-460c-aeed-69002ab3e72d
Fixes: 50e99641413e ("soc: qcom: smp2p: Qualcomm Shared Memory Point to Point")
Cc: stable@vger.kernel.org
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
Changes in v2:
1. Register devm_add_action_or_reset() action for unwinding interfaces
later, to fix use-after-free
---
drivers/soc/qcom/smp2p.c | 79 ++++++++++++++++++++--------------------
1 file changed, 39 insertions(+), 40 deletions(-)
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index 01b8580c9f27..9b6e0627ed0f 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -619,6 +619,31 @@ static int smp2p_parse_ipc(struct qcom_smp2p *smp2p)
return 0;
}
+static void qcom_smp2p_release_mbox(void *data)
+{
+ struct qcom_smp2p *smp2p = data;
+
+ mbox_free_channel(smp2p->mbox_chan);
+}
+
+static void qcom_smp2p_unwind_interfaces(struct qcom_smp2p *smp2p)
+{
+ struct smp2p_entry *entry;
+
+ list_for_each_entry(entry, &smp2p->inbound, node)
+ irq_domain_remove(entry->domain);
+
+ list_for_each_entry(entry, &smp2p->outbound, node)
+ qcom_smem_state_unregister(entry->state);
+
+ smp2p->out->valid_entries = 0;
+}
+
+static void qcom_smp2p_unwind_interfaces_action(void *data)
+{
+ qcom_smp2p_unwind_interfaces(data);
+}
+
static int qcom_smp2p_probe(struct platform_device *pdev)
{
struct smp2p_entry *entry;
@@ -671,9 +696,13 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
return ret;
}
+ ret = devm_add_action_or_reset(&pdev->dev, qcom_smp2p_release_mbox, smp2p);
+ if (ret)
+ return ret;
+
ret = qcom_smp2p_alloc_outbound_item(smp2p);
if (ret < 0)
- goto release_mbox;
+ return ret;
for_each_available_child_of_node_scoped(pdev->dev.of_node, node) {
entry = devm_kzalloc(&pdev->dev, sizeof(*entry), GFP_KERNEL);
@@ -704,6 +733,12 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
}
}
+ ret = devm_add_action_or_reset(&pdev->dev,
+ qcom_smp2p_unwind_interfaces_action,
+ smp2p);
+ if (ret)
+ return ret;
+
/* Check inbound entries in the case of early boot processor */
qcom_smp2p_start_in(smp2p);
@@ -715,7 +750,7 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
IRQF_ONESHOT,
NULL, (void *)smp2p);
if (ret)
- goto unwind_interfaces;
+ return ret;
/*
* Treat smp2p interrupt as wakeup source, but keep it disabled
@@ -728,27 +763,10 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
*/
device_set_wakeup_capable(&pdev->dev, true);
- ret = dev_pm_set_wake_irq(&pdev->dev, irq);
- if (ret)
- goto set_wake_irq_fail;
-
- return 0;
-
-set_wake_irq_fail:
- dev_pm_clear_wake_irq(&pdev->dev);
+ return devm_pm_set_wake_irq(&pdev->dev, irq);
unwind_interfaces:
- list_for_each_entry(entry, &smp2p->inbound, node)
- irq_domain_remove(entry->domain);
-
- list_for_each_entry(entry, &smp2p->outbound, node)
- qcom_smem_state_unregister(entry->state);
-
- smp2p->out->valid_entries = 0;
-
-release_mbox:
- mbox_free_channel(smp2p->mbox_chan);
-
+ qcom_smp2p_unwind_interfaces(smp2p);
return ret;
report_read_failure:
@@ -756,24 +774,6 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
return -EINVAL;
}
-static void qcom_smp2p_remove(struct platform_device *pdev)
-{
- struct qcom_smp2p *smp2p = platform_get_drvdata(pdev);
- struct smp2p_entry *entry;
-
- dev_pm_clear_wake_irq(&pdev->dev);
-
- list_for_each_entry(entry, &smp2p->inbound, node)
- irq_domain_remove(entry->domain);
-
- list_for_each_entry(entry, &smp2p->outbound, node)
- qcom_smem_state_unregister(entry->state);
-
- mbox_free_channel(smp2p->mbox_chan);
-
- smp2p->out->valid_entries = 0;
-}
-
static const struct of_device_id qcom_smp2p_of_match[] = {
{ .compatible = "qcom,smp2p" },
{}
@@ -782,7 +782,6 @@ MODULE_DEVICE_TABLE(of, qcom_smp2p_of_match);
static struct platform_driver qcom_smp2p_driver = {
.probe = qcom_smp2p_probe,
- .remove = qcom_smp2p_remove,
.driver = {
.name = "qcom_smp2p",
.of_match_table = qcom_smp2p_of_match,
--
2.53.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 2/3] soc: qcom: smp2p: Fix out-of-bounds with incorrect DTB of too many outbound entries
2026-11-02 13:35 [PATCH v2 1/3] soc: qcom: smp2p: Fix use-after-free of irq domain on removal Krzysztof Kozlowski
@ 2026-11-02 13:35 ` Krzysztof Kozlowski
2026-11-02 14:27 ` Konrad Dybcio
2026-11-02 13:35 ` [PATCH v2 3/3] soc: qcom: smp2p: Fix possible out-of-bounds read with too many inbound entries Krzysztof Kozlowski
2026-11-02 14:27 ` [PATCH v2 1/3] soc: qcom: smp2p: Fix use-after-free of irq domain on removal Konrad Dybcio
2 siblings, 1 reply; 6+ messages in thread
From: Krzysztof Kozlowski @ 2026-11-02 13:35 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Abel Vesa, Andy Gross, Chris Lew,
Deepak Kumar Singh, linux-arm-msm, linux-kernel
Cc: Krzysztof Kozlowski, Sashiko, stable
The outbound SMEM item has a fixed array of SMP2P_MAX_ENTRY (16)
entries, thus driver should be sure that DTB does not have more of
these, otherwise such incorrect DTB would cause out-of-bounds writes.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/bug/linux-eaf9beb4-cc0d-4d8e-be28-4c12b039b3c8
Fixes: 50e99641413e ("soc: qcom: smp2p: Qualcomm Shared Memory Point to Point")
Cc: stable@vger.kernel.org
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
Changes in v2:
1. None (Sashiko comment looks like duplicate of previous patch issue)
---
drivers/soc/qcom/smp2p.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index 9b6e0627ed0f..49fb738d02a9 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -517,6 +517,11 @@ static int qcom_smp2p_outbound_entry(struct qcom_smp2p *smp2p,
struct smp2p_smem_item *out = smp2p->out;
char buf[SMP2P_MAX_ENTRY_NAME] = {};
+ if (out->valid_entries >= SMP2P_MAX_ENTRY) {
+ dev_err(smp2p->dev, "too many outbound entries\n");
+ return -EINVAL;
+ }
+
/* Allocate an entry from the smem item */
strscpy(buf, entry->name, SMP2P_MAX_ENTRY_NAME);
memcpy(out->entries[out->valid_entries].name, buf, SMP2P_MAX_ENTRY_NAME);
--
2.53.0
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH v2 2/3] soc: qcom: smp2p: Fix out-of-bounds with incorrect DTB of too many outbound entries
2026-11-02 13:35 ` [PATCH v2 2/3] soc: qcom: smp2p: Fix out-of-bounds with incorrect DTB of too many outbound entries Krzysztof Kozlowski
@ 2026-11-02 14:27 ` Konrad Dybcio
0 siblings, 0 replies; 6+ messages in thread
From: Konrad Dybcio @ 2026-11-02 14:27 UTC (permalink / raw)
To: Krzysztof Kozlowski, Bjorn Andersson, Konrad Dybcio, Abel Vesa,
Andy Gross, Chris Lew, Deepak Kumar Singh, linux-arm-msm,
linux-kernel
Cc: Sashiko, stable
On 11/2/26 2:35 PM, Krzysztof Kozlowski wrote:
> The outbound SMEM item has a fixed array of SMP2P_MAX_ENTRY (16)
> entries, thus driver should be sure that DTB does not have more of
> these, otherwise such incorrect DTB would cause out-of-bounds writes.
>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://sashiko.dev/#/bug/linux-eaf9beb4-cc0d-4d8e-be28-4c12b039b3c8
> Fixes: 50e99641413e ("soc: qcom: smp2p: Qualcomm Shared Memory Point to Point")
> Cc: stable@vger.kernel.org
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 3/3] soc: qcom: smp2p: Fix possible out-of-bounds read with too many inbound entries
2026-11-02 13:35 [PATCH v2 1/3] soc: qcom: smp2p: Fix use-after-free of irq domain on removal Krzysztof Kozlowski
2026-11-02 13:35 ` [PATCH v2 2/3] soc: qcom: smp2p: Fix out-of-bounds with incorrect DTB of too many outbound entries Krzysztof Kozlowski
@ 2026-11-02 13:35 ` Krzysztof Kozlowski
2026-11-02 13:40 ` Krzysztof Kozlowski
2026-11-02 14:27 ` [PATCH v2 1/3] soc: qcom: smp2p: Fix use-after-free of irq domain on removal Konrad Dybcio
2 siblings, 1 reply; 6+ messages in thread
From: Krzysztof Kozlowski @ 2026-11-02 13:35 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Abel Vesa, Andy Gross, Chris Lew,
Deepak Kumar Singh, linux-arm-msm, linux-kernel
Cc: Krzysztof Kozlowski, Sashiko, stable
The inbound SMEM item is populated by the remote processor, so its
contents, including number of entries, should be validated by the
kernel. Number of inbound entries is directly used when iterating over
inbound data structure, so if it is higher than actual count of elements
in the data, kernel would read memory out-of-bounds.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/bug/linux-b79427c9-5d22-4b48-8ee7-1d7808101e52
Fixes: 8a9a7b9d14c2 ("soc: qcom: smp2p: Add irqchip state support")
Fixes: 50e99641413e ("soc: qcom: smp2p: Qualcomm Shared Memory Point to Point")
Cc: stable@vger.kernel.org
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
Changes in v2:
1. None
---
drivers/soc/qcom/smp2p.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index 49fb738d02a9..9af5004620ff 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -252,6 +252,21 @@ static int qcom_smp2p_in_version(struct qcom_smp2p *smp2p)
return in->version;
}
+static unsigned int qcom_smp2p_in_valid_entries(struct qcom_smp2p *smp2p)
+{
+ unsigned int valid_entries = smp2p->in->valid_entries;
+
+ /* Remote side controls the value, so do not trust it */
+ if (valid_entries > SMP2P_MAX_ENTRY) {
+ dev_err_ratelimited(smp2p->dev,
+ "too many inbound entries: %u\n",
+ valid_entries);
+ return SMP2P_MAX_ENTRY;
+ }
+
+ return valid_entries;
+}
+
static void qcom_smp2p_start_in(struct qcom_smp2p *smp2p)
{
unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND];
@@ -259,6 +274,7 @@ static void qcom_smp2p_start_in(struct qcom_smp2p *smp2p)
char buf[SMP2P_MAX_ENTRY_NAME];
struct smp2p_smem_item *in;
struct smp2p_entry *entry;
+ unsigned int valid_entries;
size_t size;
int i;
@@ -272,7 +288,8 @@ static void qcom_smp2p_start_in(struct qcom_smp2p *smp2p)
if (in->version == 0)
return;
- for (i = smp2p->valid_entries; i < in->valid_entries; i++) {
+ valid_entries = qcom_smp2p_in_valid_entries(smp2p);
+ for (i = smp2p->valid_entries; i < valid_entries; i++) {
list_for_each_entry(entry, &smp2p->inbound, node) {
memcpy(buf, in->entries[i].name, sizeof(buf));
if (!strcmp(buf, entry->name)) {
@@ -292,13 +309,15 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p)
int irq_pin;
u32 status;
char buf[SMP2P_MAX_ENTRY_NAME];
+ unsigned int valid_entries;
u32 val;
int i;
in = smp2p->in;
/* Match newly created entries */
- for (i = smp2p->valid_entries; i < in->valid_entries; i++) {
+ valid_entries = qcom_smp2p_in_valid_entries(smp2p);
+ for (i = smp2p->valid_entries; i < valid_entries; i++) {
list_for_each_entry(entry, &smp2p->inbound, node) {
memcpy(buf, in->entries[i].name, sizeof(buf));
if (!strcmp(buf, entry->name)) {
--
2.53.0
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH v2 3/3] soc: qcom: smp2p: Fix possible out-of-bounds read with too many inbound entries
2026-11-02 13:35 ` [PATCH v2 3/3] soc: qcom: smp2p: Fix possible out-of-bounds read with too many inbound entries Krzysztof Kozlowski
@ 2026-11-02 13:40 ` Krzysztof Kozlowski
0 siblings, 0 replies; 6+ messages in thread
From: Krzysztof Kozlowski @ 2026-11-02 13:40 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Abel Vesa, Andy Gross, Chris Lew,
Deepak Kumar Singh, linux-arm-msm, linux-kernel
Cc: Sashiko, stable
On 02/11/2026 14:35, Krzysztof Kozlowski wrote:
> The inbound SMEM item is populated by the remote processor, so its
> contents, including number of entries, should be validated by the
> kernel. Number of inbound entries is directly used when iterating over
> inbound data structure, so if it is higher than actual count of elements
> in the data, kernel would read memory out-of-bounds.
>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://sashiko.dev/#/bug/linux-b79427c9-5d22-4b48-8ee7-1d7808101e52
> Fixes: 8a9a7b9d14c2 ("soc: qcom: smp2p: Add irqchip state support")
> Fixes: 50e99641413e ("soc: qcom: smp2p: Qualcomm Shared Memory Point to Point")
> Cc: stable@vger.kernel.org
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
I forgot:
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/3] soc: qcom: smp2p: Fix use-after-free of irq domain on removal
2026-11-02 13:35 [PATCH v2 1/3] soc: qcom: smp2p: Fix use-after-free of irq domain on removal Krzysztof Kozlowski
2026-11-02 13:35 ` [PATCH v2 2/3] soc: qcom: smp2p: Fix out-of-bounds with incorrect DTB of too many outbound entries Krzysztof Kozlowski
2026-11-02 13:35 ` [PATCH v2 3/3] soc: qcom: smp2p: Fix possible out-of-bounds read with too many inbound entries Krzysztof Kozlowski
@ 2026-11-02 14:27 ` Konrad Dybcio
2 siblings, 0 replies; 6+ messages in thread
From: Konrad Dybcio @ 2026-11-02 14:27 UTC (permalink / raw)
To: Krzysztof Kozlowski, Bjorn Andersson, Konrad Dybcio, Abel Vesa,
Andy Gross, Chris Lew, Deepak Kumar Singh, linux-arm-msm,
linux-kernel
Cc: Sashiko, stable
On 11/2/26 2:35 PM, Krzysztof Kozlowski wrote:
> The SMP2P interrupt is requested with devm_request_threaded_irq(), so it
> is freed only after qcom_smp2p_remove() returns or, in the probe error
> path, after probe returns. Both paths, however, explicitly remove the
> inbound irq domains, unregister outbound SMEM states and free the
> mailbox channel before that.
>
> If the interrupt is triggered in this window, the interrupt handler
> would use previously freed data. Mixing manual probe() cleanup
> and resource-managed devm leads to such races, thus just convert
> as much as possible to devm to fix the issue and make code simpler.
>
> Note that for_each_available_child_of_node_scoped() loop, before
> registering qcom_smp2p_unwind_interfaces_action() cleanup action, still
> uses manual unwind, because it allocates the "entry" memory which is
> used by the action itself.
>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://sashiko.dev/#/bug/linux-02cea59a-8c4a-460c-aeed-69002ab3e72d
> Fixes: 50e99641413e ("soc: qcom: smp2p: Qualcomm Shared Memory Point to Point")
> Cc: stable@vger.kernel.org
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-11-02 14:27 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-02 13:35 [PATCH v2 1/3] soc: qcom: smp2p: Fix use-after-free of irq domain on removal Krzysztof Kozlowski
2026-11-02 13:35 ` [PATCH v2 2/3] soc: qcom: smp2p: Fix out-of-bounds with incorrect DTB of too many outbound entries Krzysztof Kozlowski
2026-11-02 14:27 ` Konrad Dybcio
2026-11-02 13:35 ` [PATCH v2 3/3] soc: qcom: smp2p: Fix possible out-of-bounds read with too many inbound entries Krzysztof Kozlowski
2026-11-02 13:40 ` Krzysztof Kozlowski
2026-11-02 14:27 ` [PATCH v2 1/3] soc: qcom: smp2p: Fix use-after-free of irq domain on removal Konrad Dybcio
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®