Commit 1cab2a84 authored by Richard Fitzgerald's avatar Richard Fitzgerald Committed by Mark Brown

ASoC: wm_adsp: Don't overrun firmware file buffer when reading region data

Protect against corrupt firmware files by ensuring that the length we
get for the data in a region actually lies within the available firmware
file data buffer.
Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent fb4587da
...@@ -1551,7 +1551,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) ...@@ -1551,7 +1551,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
const struct wmfw_region *region; const struct wmfw_region *region;
const struct wm_adsp_region *mem; const struct wm_adsp_region *mem;
const char *region_name; const char *region_name;
char *file, *text; char *file, *text = NULL;
struct wm_adsp_buf *buf; struct wm_adsp_buf *buf;
unsigned int reg; unsigned int reg;
int regions = 0; int regions = 0;
...@@ -1700,10 +1700,21 @@ static int wm_adsp_load(struct wm_adsp *dsp) ...@@ -1700,10 +1700,21 @@ static int wm_adsp_load(struct wm_adsp *dsp)
regions, le32_to_cpu(region->len), offset, regions, le32_to_cpu(region->len), offset,
region_name); region_name);
if ((pos + le32_to_cpu(region->len) + sizeof(*region)) >
firmware->size) {
adsp_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) { if (text) {
memcpy(text, region->data, le32_to_cpu(region->len)); memcpy(text, region->data, le32_to_cpu(region->len));
adsp_info(dsp, "%s: %s\n", file, text); adsp_info(dsp, "%s: %s\n", file, text);
kfree(text); kfree(text);
text = NULL;
} }
if (reg) { if (reg) {
...@@ -1748,6 +1759,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) ...@@ -1748,6 +1759,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
regmap_async_complete(regmap); regmap_async_complete(regmap);
wm_adsp_buf_free(&buf_list); wm_adsp_buf_free(&buf_list);
release_firmware(firmware); release_firmware(firmware);
kfree(text);
out: out:
kfree(file); kfree(file);
...@@ -2233,6 +2245,17 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) ...@@ -2233,6 +2245,17 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
} }
if (reg) { if (reg) {
if ((pos + le32_to_cpu(blk->len) + sizeof(*blk)) >
firmware->size) {
adsp_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 = wm_adsp_buf_alloc(blk->data, buf = wm_adsp_buf_alloc(blk->data,
le32_to_cpu(blk->len), le32_to_cpu(blk->len),
&buf_list); &buf_list);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment