Skip to content

Commit 569e54f

Browse files
singalsulgirdwood
authored andcommitted
audio: tdfb: Improve robustness for invalid configuration
Add validity checks against malformed configuration blobs and IPC control payloads: - Bound the blob length reported by comp_get_data_blob() to [sizeof(*cd->config), SOF_TDFB_MAX_SIZE] in both tdfb_prepare and the runtime new-blob path; store it in cd->config_size and require config->size to match in tdfb_init_coef. - Bump SOF_TDFB_MAX_SIZE 4096 -> 16384 to match the topology budget. - Tie SOF_TDFB_MAX_MICROPHONES to PLATFORM_MAX_CHANNELS so num_mic_locations cannot exceed the per-channel direction state arrays in tdfb_comp.h. - Reject num_angles == 0, angle_enum_mult == 0, negative or out-of-range filter_index, and negative input_channel_select[]. - Check cdata->num_elems vs. SOF_IPC_MAX_CHANNELS in the IPC3 GET handler. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent 7920b65 commit 569e54f

5 files changed

Lines changed: 44 additions & 18 deletions

File tree

src/audio/tdfb/tdfb.c

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ static int tdfb_init_coef(struct processing_module *mod, int source_nch,
323323
int i;
324324

325325
/* Sanity checks */
326+
if (config->size != cd->config_size) {
327+
comp_err(dev, "Incorrect configuration blob size");
328+
return -EINVAL;
329+
}
330+
326331
if (config->num_output_channels > PLATFORM_MAX_CHANNELS ||
327332
!config->num_output_channels) {
328333
comp_err(dev, "invalid num_output_channels %d",
@@ -342,12 +347,21 @@ static int tdfb_init_coef(struct processing_module *mod, int source_nch,
342347
return -EINVAL;
343348
}
344349

345-
if (config->num_angles > SOF_TDFB_MAX_ANGLES) {
350+
/* In SOF v1.6 - 1.8 based beamformer topologies the multiple angles, mic locations,
351+
* and beam on/off switch were not defined. A most basic supported blob has num_angles
352+
* equal to 1. Mic locations data is optional.
353+
*/
354+
if (config->num_angles == 0 || config->num_angles > SOF_TDFB_MAX_ANGLES) {
346355
comp_err(dev, "invalid num_angles %d",
347356
config->num_angles);
348357
return -EINVAL;
349358
}
350359

360+
if (!config->angle_enum_mult) {
361+
comp_err(dev, "invalid angle_enum_mult");
362+
return -EINVAL;
363+
}
364+
351365
if (config->beam_off_defined > 1) {
352366
comp_err(dev, "invalid beam_off_defined %d",
353367
config->beam_off_defined);
@@ -360,15 +374,6 @@ static int tdfb_init_coef(struct processing_module *mod, int source_nch,
360374
return -EINVAL;
361375
}
362376

363-
/* In SOF v1.6 - 1.8 based beamformer topologies the multiple angles, mic locations,
364-
* and beam on/off switch were not defined. Return error if such configuration is seen.
365-
* A most basic blob has num_angles equals 1. Mic locations data is optional.
366-
*/
367-
if (config->num_angles == 0 && config->num_mic_locations == 0) {
368-
comp_err(dev, "ABI version less than 3.19.1 is not supported.");
369-
return -EINVAL;
370-
}
371-
372377
/* Skip filter coefficients */
373378
num_filters = config->num_filters * (config->num_angles + config->beam_off_defined);
374379
coefp = tdfb_filter_seek(config, num_filters);
@@ -423,6 +428,12 @@ static int tdfb_init_coef(struct processing_module *mod, int source_nch,
423428
cd->filter_angles[min_delta_idx].azimuth, idx);
424429
}
425430

431+
if (idx < 0 || idx + (int)config->num_filters > num_filters) {
432+
comp_err(dev, "invalid filter_index %d for angle %d",
433+
idx, cd->filter_angles[min_delta_idx].azimuth);
434+
return -EINVAL;
435+
}
436+
426437
/* Seek to proper filter for requested angle or beam off configuration */
427438
coefp = tdfb_filter_seek(config, idx);
428439

@@ -451,6 +462,11 @@ static int tdfb_init_coef(struct processing_module *mod, int source_nch,
451462
for (i = 0; i < config->num_filters; i++) {
452463
if (cd->input_channel_select[i] > max_ch)
453464
max_ch = cd->input_channel_select[i];
465+
466+
if (cd->input_channel_select[i] < 0) {
467+
comp_err(dev, "invalid channel select for filter %d", i);
468+
return -EINVAL;
469+
}
454470
}
455471

456472
/* The stream must contain at least the number of channels that is
@@ -641,7 +657,12 @@ static int tdfb_process(struct processing_module *mod,
641657

642658
/* Check for changed configuration */
643659
if (comp_is_new_data_blob_available(cd->model_handler)) {
644-
cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL);
660+
cd->config = comp_get_data_blob(cd->model_handler, &cd->config_size, NULL);
661+
if (!cd->config || cd->config_size < sizeof(*cd->config) ||
662+
cd->config_size > SOF_TDFB_MAX_SIZE) {
663+
comp_err(dev, "invalid configuration blob, size %zu", cd->config_size);
664+
return -EINVAL;
665+
}
645666
ret = tdfb_setup(mod, audio_stream_get_channels(source),
646667
audio_stream_get_channels(sink),
647668
audio_stream_get_frm_fmt(source));
@@ -705,7 +726,6 @@ static int tdfb_prepare(struct processing_module *mod,
705726
struct comp_buffer *sourceb, *sinkb;
706727
struct comp_dev *dev = mod->dev;
707728
enum sof_ipc_frame frame_fmt;
708-
size_t data_size;
709729
int source_channels;
710730
int sink_channels;
711731
int rate;
@@ -735,9 +755,10 @@ static int tdfb_prepare(struct processing_module *mod,
735755
rate = audio_stream_get_rate(&sourceb->stream);
736756

737757
/* Initialize filter */
738-
cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL);
739-
if (!cd->config || !data_size) {
740-
comp_err(dev, "Missing a configuration blob.");
758+
cd->config = comp_get_data_blob(cd->model_handler, &cd->config_size, NULL);
759+
if (!cd->config || cd->config_size < sizeof(*cd->config) ||
760+
cd->config_size > SOF_TDFB_MAX_SIZE) {
761+
comp_err(dev, "invalid configuration blob, size %zu", cd->config_size);
741762
ret = -EINVAL;
742763
goto out;
743764
}

src/audio/tdfb/tdfb.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@
88
#ifndef __USER_TDFB_H__
99
#define __USER_TDFB_H__
1010

11+
#include <sof/platform.h>
1112
#include <stdint.h>
1213

1314
#define SOF_TDFB_NUM_INPUT_PINS 1 /* One source */
1415
#define SOF_TDFB_NUM_OUTPUT_PINS 1 /* One sink */
15-
#define SOF_TDFB_MAX_SIZE 4096 /* Max size for coef data in bytes */
16+
#define SOF_TDFB_MAX_SIZE 16384 /* Max size for coef data in bytes */
1617
#define SOF_TDFB_FIR_MAX_LENGTH 256 /* Max length for individual filter */
1718
#define SOF_TDFB_FIR_MAX_COUNT 16 /* A blob can define max 16 FIR EQs */
1819
#define SOF_TDFB_MAX_STREAMS 8 /* Support 1..8 sinks */
1920
#define SOF_TDFB_MAX_ANGLES 360 /* Up to 1 degree precision for 360 degrees coverage */
20-
#define SOF_TDFB_MAX_MICROPHONES 16 /* Up to 16 microphone locations */
21+
#define SOF_TDFB_MAX_MICROPHONES PLATFORM_MAX_CHANNELS /* Bounded by direction state arrays */
2122

2223
/* The driver assigns running numbers for control index. If there's single control of
2324
* type switch, enum, binary they all have index 0.

src/audio/tdfb/tdfb_comp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct tdfb_comp_data {
8888
int16_t *output_stream_mix; /**< for each FIR define stream */
8989
int16_t az_value; /**< beam steer azimuth as in control enum */
9090
int16_t az_value_estimate; /**< beam steer azimuth as in control enum */
91+
size_t config_size; /**< size of the configuration blob */
9192
size_t fir_delay_size; /**< allocated size */
9293
unsigned int max_frames; /**< max frames to process */
9394
bool direction_updates:1; /**< set true if direction angle control is updated */

src/audio/tdfb/tdfb_direction.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ static int16_t distance_from_source(struct tdfb_comp_data *cd, int mic_n,
386386

387387
static void theoretical_time_differences(struct tdfb_comp_data *cd, int16_t az)
388388
{
389-
int16_t d[PLATFORM_MAX_CHANNELS];
389+
int16_t d[SOF_TDFB_MAX_MICROPHONES];
390390
int16_t src_x;
391391
int16_t src_y;
392392
int16_t sin_az;

src/audio/tdfb/tdfb_ipc3.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ static int tdfb_cmd_get_value(struct processing_module *mod, struct sof_ipc_ctrl
112112
{
113113
struct tdfb_comp_data *cd = module_get_private_data(mod);
114114

115+
if (cdata->num_elems == 0 || cdata->num_elems > SOF_IPC_MAX_CHANNELS)
116+
return -EINVAL;
117+
115118
switch (cdata->cmd) {
116119
case SOF_CTRL_CMD_ENUM:
117120
comp_dbg(mod->dev, "SOF_CTRL_CMD_ENUM index=%d",

0 commit comments

Comments
 (0)