diff --git a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c index bd32e4d1a..cd802cfa2 100644 --- a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c +++ b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c @@ -80,6 +80,13 @@ spmc_shmem_obj_alloc(struct spmc_shmem_obj_state *state, size_t desc_size) return NULL; } + /* Ensure that descriptor size is aligned */ + if (!is_aligned(desc_size, 16)) { + WARN("%s(0x%zx) desc_size not 16-byte aligned\n", + __func__, desc_size); + return NULL; + } + obj_size = spmc_shmem_obj_size(desc_size); /* Ensure the obj size has not overflowed. */ @@ -352,10 +359,10 @@ overlapping_memory_regions(struct ffa_comp_mrd *region1, * * Return: the size required to store the descriptor store in the v1.1 format. */ -static size_t +static uint64_t spmc_shm_get_v1_1_descriptor_size(struct ffa_mtd_v1_0 *orig, size_t desc_size) { - size_t size = 0; + uint64_t size = 0; struct ffa_comp_mrd *mrd; struct ffa_emad_v1_0 *emad_array = orig->emad; @@ -372,11 +379,7 @@ spmc_shm_get_v1_1_descriptor_size(struct ffa_mtd_v1_0 *orig, size_t desc_size) mrd = (struct ffa_comp_mrd *) ((uint8_t *) orig + emad_array[0].comp_mrd_offset); - /* Check the calculated address is within the memory descriptor. */ - if (((uintptr_t) mrd + sizeof(struct ffa_comp_mrd)) > - (uintptr_t)((uint8_t *) orig + desc_size)) { - return 0; - } + /* Add the size of the memory region descriptors. */ size += mrd->address_range_count * sizeof(struct ffa_cons_mrd); return size; @@ -762,8 +765,8 @@ spmc_validate_mtd_start(struct ffa_mtd *desc, uint32_t ffa_version, * @obj: Object containing ffa_memory_region_descriptor. * @ffa_version: FF-A version of the provided descriptor. * - * Return: 0 if object is valid, -EINVAL if constituent_memory_region_descriptor - * offset or count is invalid. + * Return: 0 if object is valid, FFA_ERROR_INVALID_PARAMETER if + * constituent_memory_region_descriptor offset or count is invalid. */ static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj, uint32_t ffa_version) @@ -822,7 +825,7 @@ static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj, if (spmc_get_sp_ctx(ep_id) == NULL) { WARN("%s: Invalid receiver id 0x%x\n", __func__, ep_id); - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } } @@ -837,7 +840,7 @@ static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj, if (comp_mrd_offset != offset) { ERROR("%s: mismatching offsets provided, %u != %u\n", __func__, offset, comp_mrd_offset); - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } continue; /* Remainder only executed on first iteration. */ } @@ -848,7 +851,7 @@ static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj, if (offset < header_emad_size) { WARN("%s: invalid object, offset %u < header + emad %zu\n", __func__, offset, header_emad_size); - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } size = obj->desc_size; @@ -856,14 +859,14 @@ static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj, if (offset > size) { WARN("%s: invalid object, offset %u > total size %zu\n", __func__, offset, obj->desc_size); - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } size -= offset; if (size < sizeof(struct ffa_comp_mrd)) { WARN("%s: invalid object, offset %u, total size %zu, no header space.\n", __func__, offset, obj->desc_size); - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } size -= sizeof(struct ffa_comp_mrd); @@ -873,13 +876,13 @@ static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj, if (comp == NULL) { WARN("%s: invalid comp_mrd offset\n", __func__); - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } if (comp->address_range_count != count) { WARN("%s: invalid object, desc count %u != %zu\n", __func__, comp->address_range_count, count); - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } expected_size = offset + sizeof(*comp) + @@ -888,7 +891,7 @@ static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj, if (expected_size != obj->desc_size) { WARN("%s: invalid object, computed size %zu != size %zu\n", __func__, expected_size, obj->desc_size); - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } total_page_count = 0; @@ -901,7 +904,7 @@ static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj, WARN("%s: invalid object, desc total_page_count %u != %" PRIu64 "\n", __func__, comp->total_page_count, total_page_count); - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } } return 0; @@ -914,7 +917,8 @@ static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj, * the memory is not in a valid state for lending. * @obj: Object containing ffa_memory_region_descriptor. * - * Return: 0 if object is valid, -EINVAL if invalid memory state. + * Return: 0 if object is valid, FFA_ERROR_INVALID_PARAMETER if invalid memory + * state. */ static int spmc_shmem_check_state_obj(struct spmc_shmem_obj *obj, uint32_t ffa_version) @@ -927,7 +931,7 @@ static int spmc_shmem_check_state_obj(struct spmc_shmem_obj *obj, ffa_version); if (requested_mrd == NULL) { - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } inflight_obj = spmc_shmem_obj_get_next(&spmc_shmem_obj_state, @@ -943,11 +947,11 @@ static int spmc_shmem_check_state_obj(struct spmc_shmem_obj *obj, other_mrd = spmc_shmem_obj_get_comp_mrd(inflight_obj, FFA_VERSION_COMPILED); if (other_mrd == NULL) { - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } if (overlapping_memory_regions(requested_mrd, other_mrd)) { - return -EINVAL; + return FFA_ERROR_INVALID_PARAMETER; } } @@ -977,9 +981,10 @@ static long spmc_ffa_fill_desc(struct mailbox *mbox, goto err_arg; } - if (fragment_length > mbox->rxtx_page_count * PAGE_SIZE_4KB) { - WARN("%s: bad fragment size %u > %u buffer size\n", __func__, - fragment_length, mbox->rxtx_page_count * PAGE_SIZE_4KB); + CASSERT(sizeof(mbox->rxtx_page_count) == 4, assert_bogus_page_count); + if (fragment_length > (uint64_t)mbox->rxtx_page_count * PAGE_SIZE_4KB) { + WARN("%s: bad fragment size %u > %" PRIu64 " buffer size\n", __func__, + fragment_length, (uint64_t)mbox->rxtx_page_count * PAGE_SIZE_4KB); ret = FFA_ERROR_INVALID_PARAMETER; goto err_arg; } @@ -1048,7 +1053,6 @@ static long spmc_ffa_fill_desc(struct mailbox *mbox, ret = spmc_shmem_check_obj(obj, ffa_version); if (ret != 0) { - ret = FFA_ERROR_INVALID_PARAMETER; goto err_bad_desc; } @@ -1075,7 +1079,6 @@ static long spmc_ffa_fill_desc(struct mailbox *mbox, ret = spmc_shmem_check_state_obj(obj, ffa_version); if (ret) { ERROR("%s: invalid memory region descriptor.\n", __func__); - ret = FFA_ERROR_INVALID_PARAMETER; goto err_bad_desc; } @@ -1088,19 +1091,18 @@ static long spmc_ffa_fill_desc(struct mailbox *mbox, uint64_t mem_handle; /* Calculate the size that the v1.1 descriptor will required. */ - size_t v1_1_desc_size = + uint64_t v1_1_desc_size = spmc_shm_get_v1_1_descriptor_size((void *) &obj->desc, obj->desc_size); - if (v1_1_desc_size == 0U) { - ERROR("%s: cannot determine size of descriptor.\n", - __func__); + if (v1_1_desc_size > UINT32_MAX) { + ret = FFA_ERROR_NO_MEMORY; goto err_arg; } /* Get a new obj to store the v1.1 descriptor. */ v1_1_obj = - spmc_shmem_obj_alloc(&spmc_shmem_obj_state, v1_1_desc_size); + spmc_shmem_obj_alloc(&spmc_shmem_obj_state, (size_t)v1_1_desc_size); if (!v1_1_obj) { ret = FFA_ERROR_NO_MEMORY; @@ -1108,8 +1110,8 @@ static long spmc_ffa_fill_desc(struct mailbox *mbox, } /* Perform the conversion from v1.0 to v1.1. */ - v1_1_obj->desc_size = v1_1_desc_size; - v1_1_obj->desc_filled = v1_1_desc_size; + v1_1_obj->desc_size = (uint32_t)v1_1_desc_size; + v1_1_obj->desc_filled = (uint32_t)v1_1_desc_size; if (!spmc_shm_convert_shmem_obj_from_v1_0(v1_1_obj, obj)) { ERROR("%s: Could not convert mtd!\n", __func__); spmc_shmem_obj_free(&spmc_shmem_obj_state, v1_1_obj);