Skip to content

Commit 7731015

Browse files
committed
audio: crossover: Improve robustness for invalid configuration
crossover_validate_config() was only run on the initial blob in crossover_prepare(). Runtime IPC updates fetched in crossover_process_audio_stream() were applied without revalidation, so a bad blob could drive crossover_setup() with an out-of-range num_sinks. Validate the new blob before crossover_setup() runs. Also extend the validator to cross-check config->size against the size reported by the framework and to require enough payload for the LR4 biquads that crossover_init_coef_ch() reads (1 pair for 2-way, 3 pairs for 3-way and 4-way). Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent 0d9b5ec commit 7731015

1 file changed

Lines changed: 31 additions & 5 deletions

File tree

src/audio/crossover/crossover.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -350,16 +350,24 @@ static int crossover_free(struct processing_module *mod)
350350
* \brief Verifies that the config is formatted correctly.
351351
*
352352
* The function can only be called after the buffers have been initialized.
353+
*
354+
* \param[in] mod Processing module owning the configuration.
355+
* \param[in] config Configuration blob to validate.
356+
* \param[in] new_size Size in bytes reported by the framework for \p config;
357+
* must match the size field embedded in the blob header.
358+
* \return 0 on success, negative errno on invalid configuration.
353359
*/
354360
static int crossover_validate_config(struct processing_module *mod,
355-
struct sof_crossover_config *config)
361+
struct sof_crossover_config *config, size_t new_size)
356362
{
357363
struct comp_dev *dev = mod->dev;
358364
uint32_t size = config->size;
365+
size_t required_size;
359366
int32_t num_assigned_sinks;
367+
int32_t num_lr4s;
360368

361-
if (size > SOF_CROSSOVER_MAX_SIZE || !size) {
362-
comp_err(dev, "size %d is invalid", size);
369+
if (size > SOF_CROSSOVER_MAX_SIZE || !size || size != new_size) {
370+
comp_err(dev, "size %u is invalid", size);
363371
return -EINVAL;
364372
}
365373

@@ -370,6 +378,18 @@ static int crossover_validate_config(struct processing_module *mod,
370378
return -EINVAL;
371379
}
372380

381+
/* Each channel reads 2 * num_lr4s biquads from config->coef[]; the
382+
* runtime uses 1 LR4 pair for 2-way and 3 LR4 pairs otherwise.
383+
* See tune/sof_crossover_generate_config.m script.
384+
*/
385+
num_lr4s = (config->num_sinks == CROSSOVER_2WAY_NUM_SINKS) ? 1 : 3;
386+
required_size = sizeof(*config) + (size_t)num_lr4s * 2 * sizeof(struct sof_eq_iir_biquad);
387+
if (size < required_size) {
388+
comp_err(dev, "size %u too small for num_sinks %u, need at least %zu",
389+
size, config->num_sinks, required_size);
390+
return -EINVAL;
391+
}
392+
373393
/* Align the crossover's sinks, to their respective configuration in
374394
* the config.
375395
*/
@@ -448,14 +468,20 @@ static int crossover_process_audio_stream(struct processing_module *mod,
448468
uint32_t frames = input_buffers[0].size;
449469
uint32_t frame_bytes = audio_stream_frame_bytes(input_buffers[0].data);
450470
uint32_t processed_bytes;
471+
size_t cfg_size;
451472
int ret;
452473
int i;
453474

454475
comp_dbg(dev, "entry");
455476

456477
/* Check for changed configuration */
457478
if (comp_is_new_data_blob_available(cd->model_handler)) {
458-
cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL);
479+
cd->config = comp_get_data_blob(cd->model_handler, &cfg_size, NULL);
480+
if (!cd->config || !cfg_size ||
481+
crossover_validate_config(mod, cd->config, cfg_size) < 0) {
482+
comp_err(dev, "invalid runtime config blob");
483+
return -EINVAL;
484+
}
459485
ret = crossover_setup(mod, audio_stream_get_channels(source));
460486
if (ret < 0) {
461487
comp_err(dev, "failed Crossover setup");
@@ -547,7 +573,7 @@ static int crossover_prepare(struct processing_module *mod,
547573

548574
/* Initialize Crossover */
549575
if (cd->config &&
550-
(!data_size || crossover_validate_config(mod, cd->config) < 0)) {
576+
(!data_size || crossover_validate_config(mod, cd->config, data_size) < 0)) {
551577
/* If the configuration is invalid fail the prepare */
552578
comp_err(dev, "invalid binary config format");
553579
return -EINVAL;

0 commit comments

Comments
 (0)