Skip to content

Commit 4849b84

Browse files
committed
audio: eq_iir: Improve robustness for invalid configuration
Harden the EQ IIR setup path against malformed IPC configuration blobs. The blob length returned by comp_get_data_blob() is now stored and checked against the expected range every time a new blob is taken, and the blob's self-declared size is cross-checked against it before use. The per-response walk that previously trusted num_sections from the blob now bounds the header and biquad data against the blob, so a bad length can no longer push the lookup pointer past the allocation. The df1 and df2t delay-size helpers also gained a range check on num_sections_in_series, which strides the delay line and was previously unchecked. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent bd296e4 commit 4849b84

5 files changed

Lines changed: 63 additions & 9 deletions

File tree

src/audio/eq_iir/eq_iir.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,13 @@ static int eq_iir_process(struct processing_module *mod,
119119

120120
/* Check for changed configuration */
121121
if (comp_is_new_data_blob_available(cd->model_handler)) {
122-
cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL);
122+
cd->config = comp_get_data_blob(cd->model_handler, &cd->config_size, NULL);
123+
if (!cd->config || cd->config_size < sizeof(*cd->config) ||
124+
cd->config_size > SOF_EQ_IIR_MAX_SIZE) {
125+
comp_err(mod->dev, "invalid configuration blob, size %zu",
126+
cd->config_size);
127+
return -EINVAL;
128+
}
123129
ret = eq_iir_new_blob(mod, audio_stream_get_frm_fmt(source),
124130
audio_stream_get_frm_fmt(sink),
125131
audio_stream_get_channels(source));
@@ -158,7 +164,6 @@ static int eq_iir_prepare(struct processing_module *mod,
158164
struct comp_dev *dev = mod->dev;
159165
enum sof_ipc_frame source_format;
160166
enum sof_ipc_frame sink_format;
161-
size_t data_size;
162167
int channels;
163168
int ret = 0;
164169

@@ -183,7 +188,7 @@ static int eq_iir_prepare(struct processing_module *mod,
183188
source_format = audio_stream_get_frm_fmt(&sourceb->stream);
184189
sink_format = audio_stream_get_frm_fmt(&sinkb->stream);
185190

186-
cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL);
191+
cd->config = comp_get_data_blob(cd->model_handler, &cd->config_size, NULL);
187192

188193
/* Initialize EQ */
189194
comp_info(dev, "source_format=%d, sink_format=%d",
@@ -192,7 +197,13 @@ static int eq_iir_prepare(struct processing_module *mod,
192197
eq_iir_set_passthrough_func(cd, source_format, sink_format);
193198

194199
/* Initialize EQ */
195-
if (cd->config && data_size > 0) {
200+
if (cd->config) {
201+
if (cd->config_size < sizeof(*cd->config) ||
202+
cd->config_size > SOF_EQ_IIR_MAX_SIZE) {
203+
comp_err(dev, "invalid configuration blob, size %zu",
204+
cd->config_size);
205+
return -EINVAL;
206+
}
196207
ret = eq_iir_new_blob(mod, source_format, sink_format, channels);
197208
if (ret)
198209
return ret;

src/audio/eq_iir/eq_iir.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct comp_data {
3939
struct comp_data_blob_handler *model_handler;
4040
struct sof_eq_iir_config *config;
4141
int32_t *iir_delay; /**< pointer to allocated RAM */
42+
size_t config_size; /**< configuration size */
4243
size_t iir_delay_size; /**< allocated size */
4344
eq_iir_func eq_iir_func; /**< processing function */
4445
};

src/audio/eq_iir/eq_iir_generic.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ static int eq_iir_init_coef(struct processing_module *mod, int nch)
187187
struct iir_state_df1 *iir = cd->iir;
188188
struct sof_eq_iir_header *lookup[SOF_EQ_IIR_MAX_RESPONSES];
189189
struct sof_eq_iir_header *eq;
190+
int32_t coef_words_max;
190191
int32_t *assign_response;
191192
int32_t *coef_data;
192193
int size_sum = 0;
@@ -210,17 +211,43 @@ static int eq_iir_init_coef(struct processing_module *mod, int nch)
210211
return -EINVAL;
211212
}
212213

214+
/* Compute the size of the coefficient area in int32_t words from the
215+
* blob's self-declared size. The blob layout is:
216+
* sizeof(*config) header bytes
217+
* channels_in_config int32_t assign_response[]
218+
* coefficient data[]
219+
*/
220+
if (config->size < sizeof(*config) ||
221+
config->size - sizeof(*config) < config->channels_in_config * sizeof(int32_t)) {
222+
comp_err(mod->dev, "config size %u too small", config->size);
223+
return -EINVAL;
224+
}
225+
coef_words_max = (config->size - sizeof(*config)) / sizeof(int32_t) -
226+
config->channels_in_config;
227+
213228
/* Collect index of response start positions in all_coefficients[] */
214229
j = 0;
215230
assign_response = ASSUME_ALIGNED(&config->data[0], 4);
216-
coef_data = ASSUME_ALIGNED(&config->data[config->channels_in_config],
217-
4);
231+
coef_data = ASSUME_ALIGNED(&config->data[config->channels_in_config], 4);
218232
for (i = 0; i < SOF_EQ_IIR_MAX_RESPONSES; i++) {
219233
if (i < config->number_of_responses) {
234+
/* Header must fit before reading num_sections */
235+
if (j + SOF_EQ_IIR_NHEADER > coef_words_max) {
236+
comp_err(mod->dev, "response %d header out of bounds", i);
237+
return -EINVAL;
238+
}
220239
eq = (struct sof_eq_iir_header *)&coef_data[j];
240+
/* Bound num_sections so the multiply cannot overflow
241+
* and the section data stays within the blob.
242+
*/
243+
if (eq->num_sections > SOF_EQ_IIR_BIQUADS_MAX || j + SOF_EQ_IIR_NHEADER +
244+
SOF_EQ_IIR_NBIQUAD * eq->num_sections > coef_words_max) {
245+
comp_err(mod->dev, "response %d num_sections %u out of bounds",
246+
i, eq->num_sections);
247+
return -EINVAL;
248+
}
221249
lookup[i] = eq;
222-
j += SOF_EQ_IIR_NHEADER
223-
+ SOF_EQ_IIR_NBIQUAD * eq->num_sections;
250+
j += SOF_EQ_IIR_NHEADER + SOF_EQ_IIR_NBIQUAD * eq->num_sections;
224251
} else {
225252
lookup[i] = NULL;
226253
}
@@ -315,6 +342,11 @@ int eq_iir_setup(struct processing_module *mod, int nch)
315342
struct comp_data *cd = module_get_private_data(mod);
316343
int delay_size;
317344

345+
if (cd->config->size != cd->config_size) {
346+
comp_err(mod->dev, "Incorrect configuration blob size");
347+
return -EINVAL;
348+
}
349+
318350
/* Free existing IIR channels data if it was allocated */
319351
eq_iir_free_delaylines(mod);
320352

src/math/iir_df1.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@
1616

1717
int iir_delay_size_df1(struct sof_eq_iir_header *config)
1818
{
19-
int n = config->num_sections; /* One section uses two unit delays */
19+
int n = config->num_sections; /* One section uses four unit delays */
2020

2121
if (n > SOF_EQ_IIR_BIQUADS_MAX || n < 1)
2222
return -EINVAL;
2323

24+
if (config->num_sections_in_series > SOF_EQ_IIR_BIQUADS_MAX ||
25+
config->num_sections_in_series < 1 ||
26+
config->num_sections_in_series > n)
27+
return -EINVAL;
28+
2429
return 4 * n * sizeof(int32_t);
2530
}
2631
EXPORT_SYMBOL(iir_delay_size_df1);

src/math/iir_df2t.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ int iir_delay_size_df2t(struct sof_eq_iir_header *config)
2121
if (n > SOF_EQ_IIR_BIQUADS_MAX || n < 1)
2222
return -EINVAL;
2323

24+
if (config->num_sections_in_series > SOF_EQ_IIR_BIQUADS_MAX ||
25+
config->num_sections_in_series < 1 ||
26+
config->num_sections_in_series > n)
27+
return -EINVAL;
28+
2429
return 2 * n * sizeof(int64_t);
2530
}
2631

0 commit comments

Comments
 (0)