mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 23:52:08 +02:00
firmware: cs_dsp: Validate payload length before processing block
Move the payload length check in cs_dsp_load() and cs_dsp_coeff_load()
to be done before the block is processed.
The check that the length of a block payload does not exceed the number
of remaining bytes in the firwmware file buffer was being done near the
end of the loop iteration. However, some code before that check used the
length field without validating it.
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Fixes: f6bc909e76 ("firmware: cs_dsp: add driver to support firmware loading on Cirrus Logic DSPs")
Link: https://patch.msgid.link/20240627141432.93056-4-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
959fe01e85
commit
6598afa932
|
|
@ -1452,6 +1452,12 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
|||
}
|
||||
|
||||
region = (void *)&(firmware->data[pos]);
|
||||
|
||||
if (le32_to_cpu(region->len) > firmware->size - pos - sizeof(*region)) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
region_name = "Unknown";
|
||||
reg = 0;
|
||||
text = NULL;
|
||||
|
|
@ -1508,16 +1514,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
|||
regions, le32_to_cpu(region->len), offset,
|
||||
region_name);
|
||||
|
||||
if (le32_to_cpu(region->len) >
|
||||
firmware->size - pos - sizeof(*region)) {
|
||||
cs_dsp_err(dsp,
|
||||
"%s.%d: %s region len %d bytes exceeds file length %zu\n",
|
||||
file, regions, region_name,
|
||||
le32_to_cpu(region->len), firmware->size);
|
||||
ret = -EINVAL;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
if (text) {
|
||||
memcpy(text, region->data, le32_to_cpu(region->len));
|
||||
cs_dsp_info(dsp, "%s: %s\n", file, text);
|
||||
|
|
@ -2147,6 +2143,11 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
|||
|
||||
blk = (void *)(&firmware->data[pos]);
|
||||
|
||||
if (le32_to_cpu(blk->len) > firmware->size - pos - sizeof(*blk)) {
|
||||
ret = -EOVERFLOW;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
type = le16_to_cpu(blk->type);
|
||||
offset = le16_to_cpu(blk->offset);
|
||||
version = le32_to_cpu(blk->ver) >> 8;
|
||||
|
|
@ -2243,17 +2244,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
|||
}
|
||||
|
||||
if (reg) {
|
||||
if (le32_to_cpu(blk->len) >
|
||||
firmware->size - pos - sizeof(*blk)) {
|
||||
cs_dsp_err(dsp,
|
||||
"%s.%d: %s region len %d bytes exceeds file length %zu\n",
|
||||
file, blocks, region_name,
|
||||
le32_to_cpu(blk->len),
|
||||
firmware->size);
|
||||
ret = -EINVAL;
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
buf = cs_dsp_buf_alloc(blk->data,
|
||||
le32_to_cpu(blk->len),
|
||||
&buf_list);
|
||||
|
|
@ -2293,6 +2283,10 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
|||
regmap_async_complete(regmap);
|
||||
cs_dsp_buf_free(&buf_list);
|
||||
kfree(text);
|
||||
|
||||
if (ret == -EOVERFLOW)
|
||||
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user