[PATCH v4 3/4] soc: qcom: smem: validate private item payloads
From: Albert Esteve
Date: Thu Oct 22 2026 - 05:52:53 EST
From: Sarannya S <sarannya.s@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 <sarannya.s@xxxxxxxxxxxxxxxx>
Signed-off-by: Pranav Mahesh Phansalkar <pranav.phansalkar@xxxxxxxxxxxxxxxx>
Signed-off-by: Sudeepgoud Patil <sudeep.patil@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 a6732832e2c5..f34eaba230ad 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -616,6 +616,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;
@@ -635,20 +636,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;
}
@@ -678,20 +680,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