Commit 50dd2ea8 authored by Ben Hutchings's avatar Ben Hutchings Committed by Mark Brown

ASoC: wm_adsp: Fix validation of firmware and coeff lengths

The checks for whether another region/block header could be present
are subtracting the size from the current offset.  Obviously we should
instead subtract the offset from the size.

The checks for whether the region/block data fit in the file are
adding the data size to the current offset and header size, without
checking for integer overflow.  Rearrange these so that overflow is
impossible.
Signed-off-by: default avatarBen Hutchings <ben.hutchings@codethink.co.uk>
Acked-by: default avatarCharles Keepax <ckeepax@opensource.cirrus.com>
Tested-by: default avatarCharles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org
parent 4fbd8d19
...@@ -1733,7 +1733,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) ...@@ -1733,7 +1733,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
le64_to_cpu(footer->timestamp)); le64_to_cpu(footer->timestamp));
while (pos < firmware->size && while (pos < firmware->size &&
pos - firmware->size > sizeof(*region)) { sizeof(*region) < firmware->size - pos) {
region = (void *)&(firmware->data[pos]); region = (void *)&(firmware->data[pos]);
region_name = "Unknown"; region_name = "Unknown";
reg = 0; reg = 0;
...@@ -1782,8 +1782,8 @@ static int wm_adsp_load(struct wm_adsp *dsp) ...@@ -1782,8 +1782,8 @@ 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)) > if (le32_to_cpu(region->len) >
firmware->size) { firmware->size - pos - sizeof(*region)) {
adsp_err(dsp, adsp_err(dsp,
"%s.%d: %s region len %d bytes exceeds file length %zu\n", "%s.%d: %s region len %d bytes exceeds file length %zu\n",
file, regions, region_name, file, regions, region_name,
...@@ -2253,7 +2253,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) ...@@ -2253,7 +2253,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
blocks = 0; blocks = 0;
while (pos < firmware->size && while (pos < firmware->size &&
pos - firmware->size > sizeof(*blk)) { sizeof(*blk) < firmware->size - pos) {
blk = (void *)(&firmware->data[pos]); blk = (void *)(&firmware->data[pos]);
type = le16_to_cpu(blk->type); type = le16_to_cpu(blk->type);
...@@ -2327,8 +2327,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) ...@@ -2327,8 +2327,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
} }
if (reg) { if (reg) {
if ((pos + le32_to_cpu(blk->len) + sizeof(*blk)) > if (le32_to_cpu(blk->len) >
firmware->size) { firmware->size - pos - sizeof(*blk)) {
adsp_err(dsp, adsp_err(dsp,
"%s.%d: %s region len %d bytes exceeds file length %zu\n", "%s.%d: %s region len %d bytes exceeds file length %zu\n",
file, blocks, region_name, file, blocks, region_name,
......
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