| From 50dd2ea8ef67a1617e0c0658bcbec4b9fb03b936 Mon Sep 17 00:00:00 2001 |
| From: Ben Hutchings <ben.hutchings@codethink.co.uk> |
| Date: Fri, 8 Dec 2017 16:15:20 +0000 |
| Subject: ASoC: wm_adsp: Fix validation of firmware and coeff lengths |
| |
| From: Ben Hutchings <ben.hutchings@codethink.co.uk> |
| |
| commit 50dd2ea8ef67a1617e0c0658bcbec4b9fb03b936 upstream. |
| |
| 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: Ben Hutchings <ben.hutchings@codethink.co.uk> |
| Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com> |
| Tested-by: Charles Keepax <ckeepax@opensource.cirrus.com> |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| sound/soc/codecs/wm_adsp.c | 12 ++++++------ |
| 1 file changed, 6 insertions(+), 6 deletions(-) |
| |
| --- a/sound/soc/codecs/wm_adsp.c |
| +++ b/sound/soc/codecs/wm_adsp.c |
| @@ -1465,7 +1465,7 @@ static int wm_adsp_load(struct wm_adsp * |
| le64_to_cpu(footer->timestamp)); |
| |
| while (pos < firmware->size && |
| - pos - firmware->size > sizeof(*region)) { |
| + sizeof(*region) < firmware->size - pos) { |
| region = (void *)&(firmware->data[pos]); |
| region_name = "Unknown"; |
| reg = 0; |
| @@ -1526,8 +1526,8 @@ static int wm_adsp_load(struct wm_adsp * |
| regions, le32_to_cpu(region->len), offset, |
| region_name); |
| |
| - if ((pos + le32_to_cpu(region->len) + sizeof(*region)) > |
| - firmware->size) { |
| + if (le32_to_cpu(region->len) > |
| + firmware->size - pos - sizeof(*region)) { |
| adsp_err(dsp, |
| "%s.%d: %s region len %d bytes exceeds file length %zu\n", |
| file, regions, region_name, |
| @@ -1992,7 +1992,7 @@ static int wm_adsp_load_coeff(struct wm_ |
| |
| blocks = 0; |
| while (pos < firmware->size && |
| - pos - firmware->size > sizeof(*blk)) { |
| + sizeof(*blk) < firmware->size - pos) { |
| blk = (void *)(&firmware->data[pos]); |
| |
| type = le16_to_cpu(blk->type); |
| @@ -2066,8 +2066,8 @@ static int wm_adsp_load_coeff(struct wm_ |
| } |
| |
| if (reg) { |
| - if ((pos + le32_to_cpu(blk->len) + sizeof(*blk)) > |
| - firmware->size) { |
| + if (le32_to_cpu(blk->len) > |
| + firmware->size - pos - sizeof(*blk)) { |
| adsp_err(dsp, |
| "%s.%d: %s region len %d bytes exceeds file length %zu\n", |
| file, blocks, region_name, |