diff options
Diffstat (limited to 'drivers/soc/qcom/smem.c')
-rw-r--r-- | drivers/soc/qcom/smem.c | 62 |
1 files changed, 24 insertions, 38 deletions
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 817e2dfae12d..4958b65ec935 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -86,17 +86,6 @@ /* Max number of processors/hosts in a system */ #define SMEM_HOST_COUNT 9 -/* Entry range check - * ptr >= start : Checks if ptr is greater than the start of access region - * ptr + size >= ptr: Check for integer overflow (On 32bit system where ptr - * and size are 32bits, ptr + size can wrap around to be a small integer) - * ptr + size <= end: Checks if ptr+size is less than the end of access region - */ -#define IN_PARTITION_RANGE(ptr, size, start, end) \ - (((void *)(ptr) >= (void *)(start)) && \ - (((void *)(ptr) + (size)) >= (void *)(ptr)) && \ - (((void *)(ptr) + (size)) <= (void *)(end))) - /** * struct smem_proc_comm - proc_comm communication struct (legacy) * @command: current command to be executed @@ -326,8 +315,7 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem, end = phdr_to_last_private_entry(phdr); cached = phdr_to_first_cached_entry(phdr); - if (WARN_ON(!IN_PARTITION_RANGE(end, 0, phdr, cached) || - cached > p_end)) + if (WARN_ON((void *)end > p_end || (void *)cached > p_end)) return -EINVAL; while (hdr < end) { @@ -496,9 +484,8 @@ static void *qcom_smem_get_private(struct qcom_smem *smem, unsigned item, size_t *size) { - struct smem_partition_header *phdr; - struct smem_private_entry *e, *uncached_end, *cached_end; + struct smem_private_entry *e, *end; void *item_ptr, *p_end; u32 partition_size; u32 padding_data; @@ -509,36 +496,35 @@ static void *qcom_smem_get_private(struct qcom_smem *smem, p_end = (void *)phdr + partition_size; e = phdr_to_first_private_entry(phdr); - uncached_end = phdr_to_last_private_entry(phdr); - cached_end = phdr_to_first_cached_entry(phdr); + end = phdr_to_last_private_entry(phdr); - if (WARN_ON(!IN_PARTITION_RANGE(uncached_end, 0, phdr, uncached_end) - || (void *)cached_end > p_end)) + if (WARN_ON((void *)end > p_end)) return ERR_PTR(-EINVAL); - - while ((e < uncached_end) && ((e + 1) < uncached_end)) { - if (e->canary != SMEM_PRIVATE_CANARY) - goto invalid_canary; + while (e < end) { + if (e->canary != SMEM_PRIVATE_CANARY) { + dev_err(smem->dev, + "Found invalid canary in host %d:%d partition\n", + phdr->host0, phdr->host1); + return ERR_PTR(-EINVAL); + } if (le16_to_cpu(e->item) == item) { - e_size = le32_to_cpu(e->size); - padding_data = le16_to_cpu(e->padding_data); - - if (e_size < partition_size && padding_data < e_size) - entry_size = e_size - padding_data; - else + if (size != NULL) { + e_size = le32_to_cpu(e->size); + padding_data = le16_to_cpu(e->padding_data); + + if (e_size < partition_size + && padding_data < e_size) + *size = e_size - padding_data; + else + return ERR_PTR(-EINVAL); + } + + item_ptr = entry_to_item(e); + if (WARN_ON(item_ptr > p_end)) return ERR_PTR(-EINVAL); - item_ptr = entry_to_item(e); - - 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; } |