Skip to content

Commit

Permalink
firmware: cs_dsp: Validate payload length before processing block
Browse files Browse the repository at this point in the history
[ Upstream commit 6598afa9320b6ab13041616950ca5f8f938c0cf1 ]

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: f6bc909 ("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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
(cherry picked from commit 3a9cd924aec1288d675df721f244da4dd7e16cff)
  • Loading branch information
rfvirgil authored and opsiff committed Jul 29, 2024
1 parent 63b8f52 commit a635b7f
Showing 1 changed file with 15 additions and 21 deletions.
36 changes: 15 additions & 21 deletions drivers/firmware/cirrus/cs_dsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,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;
Expand Down Expand Up @@ -1454,16 +1460,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);
Expand Down Expand Up @@ -2093,6 +2089,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;
Expand Down Expand Up @@ -2189,17 +2190,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);
Expand Down Expand Up @@ -2239,6 +2229,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;
}

Expand Down

0 comments on commit a635b7f

Please sign in to comment.