@@ -72,12 +72,13 @@ static void eq_fir_free_delaylines(struct processing_module *mod)
7272}
7373
7474static int eq_fir_init_coef (struct comp_dev * dev , struct sof_eq_fir_config * config ,
75- struct fir_state_32x16 * fir , int nch )
75+ size_t config_size , struct fir_state_32x16 * fir , int nch )
7676{
7777 struct sof_fir_coef_data * lookup [SOF_EQ_FIR_MAX_RESPONSES ];
7878 struct sof_fir_coef_data * eq ;
7979 int16_t * assign_response ;
8080 int16_t * coef_data ;
81+ size_t coef_words_max ;
8182 size_t size_sum = 0 ;
8283 int resp = 0 ;
8384 int i ;
@@ -101,6 +102,11 @@ static int eq_fir_init_coef(struct comp_dev *dev, struct sof_eq_fir_config *conf
101102 config -> number_of_responses , config -> channels_in_config , nch );
102103
103104 /* Sanity checks */
105+ if (config -> size != config_size ) {
106+ comp_err (dev , "Incorrect configuration blob size" );
107+ return - EINVAL ;
108+ }
109+
104110 if (nch > PLATFORM_MAX_CHANNELS ||
105111 config -> channels_in_config > PLATFORM_MAX_CHANNELS ||
106112 !config -> channels_in_config ) {
@@ -112,16 +118,45 @@ static int eq_fir_init_coef(struct comp_dev *dev, struct sof_eq_fir_config *conf
112118 return - EINVAL ;
113119 }
114120
121+ /* Compute the size of the coefficient area in int16_t words from the
122+ * blob's self-declared size. The blob layout is:
123+ * sizeof(*config) header bytes
124+ * channels_in_config int16_t assign_response[]
125+ * coefficient data[]
126+ */
127+ if (config -> size < sizeof (* config ) ||
128+ config -> size - sizeof (* config ) <
129+ (size_t )config -> channels_in_config * sizeof (int16_t )) {
130+ comp_err (dev , "config size %u too small" , config -> size );
131+ return - EINVAL ;
132+ }
133+ coef_words_max = (config -> size - sizeof (* config )) / sizeof (int16_t ) -
134+ config -> channels_in_config ;
135+
115136 /* Collect index of response start positions in all_coefficients[] */
116137 j = 0 ;
117138 assign_response = ASSUME_ALIGNED (& config -> data [0 ], 4 );
118- coef_data = ASSUME_ALIGNED (& config -> data [config -> channels_in_config ],
119- 4 );
139+ coef_data = ASSUME_ALIGNED (& config -> data [config -> channels_in_config ], 4 );
120140 for (i = 0 ; i < SOF_EQ_FIR_MAX_RESPONSES ; i ++ ) {
121141 if (i < config -> number_of_responses ) {
142+ /* Header must fit before reading length */
143+ if (j + SOF_FIR_COEF_NHEADER > coef_words_max ) {
144+ comp_err (dev , "response %d header out of bounds" , i );
145+ return - EINVAL ;
146+ }
122147 eq = (struct sof_fir_coef_data * )& coef_data [j ];
148+ /* Bound length so it is valid and the coefficient data
149+ * stays within the blob.
150+ */
151+ if (eq -> length <= 0 || eq -> length > SOF_FIR_MAX_LENGTH ||
152+ (eq -> length & 0x3 ) ||
153+ j + SOF_FIR_COEF_NHEADER + eq -> length > coef_words_max ) {
154+ comp_err (dev , "response %d length %d out of bounds" ,
155+ i , eq -> length );
156+ return - EINVAL ;
157+ }
123158 lookup [i ] = eq ;
124- j += SOF_FIR_COEF_NHEADER + coef_data [ j ] ;
159+ j += SOF_FIR_COEF_NHEADER + eq -> length ;
125160 } else {
126161 lookup [i ] = NULL ;
127162 }
@@ -209,7 +244,7 @@ static int eq_fir_setup(struct processing_module *mod, int nch)
209244 cd -> nch = nch ;
210245
211246 /* Set coefficients for each channel EQ from coefficient blob */
212- delay_size = eq_fir_init_coef (dev , cd -> config , cd -> fir , nch );
247+ delay_size = eq_fir_init_coef (dev , cd -> config , cd -> config_size , cd -> fir , nch );
213248 if (delay_size < 0 )
214249 return delay_size ; /* Contains error code */
215250
@@ -234,9 +269,25 @@ static int eq_fir_setup(struct processing_module *mod, int nch)
234269 return 0 ;
235270}
236271
272+ static int eq_fir_check_blob_size (struct comp_dev * dev , size_t size )
273+ {
274+ if (size < sizeof (struct sof_eq_fir_config ) || size > SOF_EQ_FIR_MAX_SIZE ) {
275+ comp_err (dev , "invalid configuration blob, size %zu" , size );
276+ return - EINVAL ;
277+ }
278+
279+ return 0 ;
280+ }
281+
237282static int eq_fir_validator (struct comp_dev * dev , void * new_data , uint32_t new_data_size )
238283{
239- return eq_fir_init_coef (dev , new_data , NULL , -1 );
284+ int ret ;
285+
286+ ret = eq_fir_check_blob_size (dev , new_data_size );
287+ if (ret < 0 )
288+ return ret ;
289+
290+ return eq_fir_init_coef (dev , new_data , new_data_size , NULL , -1 );
240291}
241292
242293/*
@@ -332,7 +383,9 @@ static int eq_fir_process(struct processing_module *mod,
332383
333384 /* Check for changed configuration */
334385 if (comp_is_new_data_blob_available (cd -> model_handler )) {
335- cd -> config = comp_get_data_blob (cd -> model_handler , NULL , NULL );
386+ cd -> config = comp_get_data_blob (cd -> model_handler , & cd -> config_size , NULL );
387+ if (!cd -> config || eq_fir_check_blob_size (mod -> dev , cd -> config_size ) < 0 )
388+ return - EINVAL ;
336389 ret = eq_fir_setup (mod , audio_stream_get_channels (source ));
337390 if (ret < 0 ) {
338391 comp_err (mod -> dev , "failed FIR setup" );
@@ -384,7 +437,6 @@ static int eq_fir_prepare(struct processing_module *mod,
384437 int channels ;
385438 enum sof_ipc_frame frame_fmt ;
386439 int ret = 0 ;
387- size_t data_size ;
388440
389441 comp_dbg (dev , "entry" );
390442
@@ -407,8 +459,11 @@ static int eq_fir_prepare(struct processing_module *mod,
407459 frame_fmt = audio_stream_get_frm_fmt (& sourceb -> stream );
408460
409461 cd -> eq_fir_func = eq_fir_passthrough ;
410- cd -> config = comp_get_data_blob (cd -> model_handler , & data_size , NULL );
411- if (cd -> config && data_size > 0 ) {
462+ cd -> config = comp_get_data_blob (cd -> model_handler , & cd -> config_size , NULL );
463+ if (cd -> config ) {
464+ if (eq_fir_check_blob_size (dev , cd -> config_size ) < 0 )
465+ return - EINVAL ;
466+
412467 ret = eq_fir_setup (mod , channels );
413468 if (ret < 0 )
414469 comp_err (dev , "eq_fir_setup failed." );
0 commit comments