mirror of https://github.com/thesofproject/sof.git
testbench: check array size in component parsing
There may be a situation where size of all elements of the snd_tplg_vendor_array is greater than the private data size. If we take a look at array structure struct snd_soc_tplg_vendor_array { __le32 size; /* size in bytes of the array, including all elements */ __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */ __le32 num_elems; /* number of elements in array */ union { struct snd_soc_tplg_vendor_uuid_elem uuid[0]; struct snd_soc_tplg_vendor_value_elem value[0]; struct snd_soc_tplg_vendor_string_elem string[0]; }; } __attribute__((packed)); and assume of private data size is size. If num_elems * sizeof(..._elem) > size occurs, this is bad because, we first try to allocate _size_ bytes via malloc to array pointer. Since the num_elems * sizeof(..._elem) is greater than size, we get a segmentation fault when we try to memcpy the remaining size in the subsequent functions (read tplg_read_array()). We fix this problem by checking for whether array size falls within the bounds of private data size. Signed-off-by: Mohana Datta Yelugoti <ymdatta.work@gmail.com>
This commit is contained in:
parent
9f2a1abdda
commit
c9e090ccf3
|
@ -10,6 +10,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
@ -60,6 +61,40 @@ static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type)
|
|||
return SOF_COMP_NONE;
|
||||
}
|
||||
|
||||
static bool is_valid_priv_size(size_t size_read, size_t priv_size,
|
||||
struct snd_soc_tplg_vendor_array *array)
|
||||
{
|
||||
size_t arr_size, elem_size, arr_elems_size;
|
||||
|
||||
arr_size = sizeof(struct snd_soc_tplg_vendor_array);
|
||||
|
||||
switch (array->type) {
|
||||
case SND_SOC_TPLG_TUPLE_TYPE_UUID:
|
||||
elem_size = sizeof(struct snd_soc_tplg_vendor_uuid_elem);
|
||||
break;
|
||||
case SND_SOC_TPLG_TUPLE_TYPE_STRING:
|
||||
elem_size = sizeof(struct snd_soc_tplg_vendor_string_elem);
|
||||
break;
|
||||
case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
|
||||
case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
|
||||
case SND_SOC_TPLG_TUPLE_TYPE_WORD:
|
||||
case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
|
||||
elem_size = sizeof(struct snd_soc_tplg_vendor_value_elem);
|
||||
break;
|
||||
default:
|
||||
/* This is handled in the further calls */
|
||||
return true;
|
||||
}
|
||||
|
||||
arr_elems_size = array->num_elems * elem_size;
|
||||
|
||||
/*
|
||||
* check if size of data to be read from widget's private data
|
||||
* doesn't exceed private data's size.
|
||||
*/
|
||||
return size_read + arr_size + arr_elems_size <= priv_size;
|
||||
}
|
||||
|
||||
/* read vendor tuples array from topology */
|
||||
int tplg_read_array(struct snd_soc_tplg_vendor_array *array, FILE *file)
|
||||
{
|
||||
|
@ -339,6 +374,13 @@ int tplg_load_pga(int comp_id, int pipeline_id, int size,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check for array size mismatch */
|
||||
if (!is_valid_priv_size(total_array_size, size, array)) {
|
||||
fprintf(stderr, "error: pga array size mismatch\n");
|
||||
free(array);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = tplg_read_array(array, file);
|
||||
if (ret) {
|
||||
fprintf(stderr, "error: read array fail\n");
|
||||
|
|
Loading…
Reference in New Issue