[PATCH v3 3/4] soc: qcom: smem: validate private item payloads
From: Albert Esteve
Date: Thu Sep 24 2026 - 09:17:38 EST
From: Sarannya S <quic_sarannya@xxxxxxxxxxxxxxxx>
Validate a matching entry's size and padding even when the caller does
not request the length, and check that the payload stays inside the
same region as the header.
Signed-off-by: Sarannya S <quic_sarannya@xxxxxxxxxxxxxxxx>
Signed-off-by: Pranav Mahesh Phansalkar <quic_pphansal@xxxxxxxxxxxxxxxx>
Signed-off-by: Sudeepgoud Patil <quic_sudeepgo@xxxxxxxxxxxxxxxx>
Signed-off-by: Albert Esteve <aesteve@xxxxxxxxxx>
---
drivers/soc/qcom/smem.c | 39 +++++++++++++++++++++------------------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 9bf0ec32c9f1..393257cbe5e1 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -615,6 +615,7 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
struct smem_private_entry *next_e;
struct smem_partition_header *phdr;
void *item_ptr, *p_end;
+ size_t entry_size = 0;
u32 padding_data;
u32 e_size;
@@ -634,20 +635,21 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
goto invalid_canary;
if (le16_to_cpu(e->item) == item) {
- if (size != NULL) {
- e_size = le32_to_cpu(e->size);
- padding_data = le16_to_cpu(e->padding_data);
+ e_size = le32_to_cpu(e->size);
+ padding_data = le16_to_cpu(e->padding_data);
- if (WARN_ON(e_size > part->size || padding_data > e_size))
- return ERR_PTR(-EINVAL);
-
- *size = e_size - padding_data;
- }
+ if (e_size < part->size && padding_data < e_size)
+ entry_size = e_size - padding_data;
+ else
+ return ERR_PTR(-EINVAL);
item_ptr = uncached_entry_to_item(e);
- if (WARN_ON(item_ptr > p_end))
+ if (WARN_ON(!IN_PARTITION_RANGE(item_ptr, entry_size, e, uncached_end)))
return ERR_PTR(-EINVAL);
+ if (size != NULL)
+ *size = entry_size;
+
return item_ptr;
}
@@ -677,20 +679,21 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
goto invalid_canary;
if (le16_to_cpu(e->item) == item) {
- if (size != NULL) {
- e_size = le32_to_cpu(e->size);
- padding_data = le16_to_cpu(e->padding_data);
+ e_size = le32_to_cpu(e->size);
+ padding_data = le16_to_cpu(e->padding_data);
- if (WARN_ON(e_size > part->size || padding_data > e_size))
- return ERR_PTR(-EINVAL);
-
- *size = e_size - padding_data;
- }
+ if (e_size < part->size && padding_data < e_size)
+ entry_size = e_size - padding_data;
+ else
+ return ERR_PTR(-EINVAL);
item_ptr = cached_entry_to_item(e);
- if (WARN_ON(item_ptr < (void *)phdr))
+ if (WARN_ON(!IN_PARTITION_RANGE(item_ptr, entry_size, cached_end, e)))
return ERR_PTR(-EINVAL);
+ if (size != NULL)
+ *size = entry_size;
+
return item_ptr;
}
--
2.55.0