mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-02-10 05:15:57 +00:00
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: Richard Fitzgerald <rf@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
fb4587da5b
commit
1cab2a84f4
@ -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)
|
|||||||
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 @@ out_fw:
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user