diff options
author | Richard Fitzgerald <rf@opensource.cirrus.com> | 2024-06-27 15:14:30 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2024-07-01 14:10:23 +0100 |
commit | 959fe01e85b7241e3ec305d657febbe82da16a02 (patch) | |
tree | a57a164bd4565969259a9a59b9bfbc4835a018d4 | |
parent | 3019b86bce16fbb5bc1964f3544d0ce7d0137278 (diff) |
firmware: cs_dsp: Return error if block header overflows file
Return an error from cs_dsp_power_up() if a block header is longer
than the amount of data left in the file.
The previous code in cs_dsp_load() and cs_dsp_load_coeff() would loop
while there was enough data left in the file for a valid region. This
protected against overrunning the end of the file data, but it didn't
abort the file processing with an error.
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Fixes: f6bc909e7673 ("firmware: cs_dsp: add driver to support firmware loading on Cirrus Logic DSPs")
Link: https://patch.msgid.link/20240627141432.93056-3-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/firmware/cirrus/cs_dsp.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c index 6eca62d31e20..47cf91be99a1 100644 --- a/drivers/firmware/cirrus/cs_dsp.c +++ b/drivers/firmware/cirrus/cs_dsp.c @@ -1444,8 +1444,13 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file, le64_to_cpu(footer->timestamp)); - while (pos < firmware->size && - sizeof(*region) < firmware->size - pos) { + while (pos < firmware->size) { + /* Is there enough data for a complete block header? */ + if (sizeof(*region) > firmware->size - pos) { + ret = -EOVERFLOW; + goto out_fw; + } + region = (void *)&(firmware->data[pos]); region_name = "Unknown"; reg = 0; @@ -2133,8 +2138,13 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware pos = le32_to_cpu(hdr->len); blocks = 0; - while (pos < firmware->size && - sizeof(*blk) < firmware->size - pos) { + while (pos < firmware->size) { + /* Is there enough data for a complete block header? */ + if (sizeof(*blk) > firmware->size - pos) { + ret = -EOVERFLOW; + goto out_fw; + } + blk = (void *)(&firmware->data[pos]); type = le16_to_cpu(blk->type); |