summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorBen Hutchings <ben.hutchings@codethink.co.uk>2017-12-08 16:15:20 +0000
committerBen Hutchings <ben@decadent.org.uk>2018-03-03 15:51:50 +0000
commitdfb76a1333b7261b8e6baac55b80762b79ba07dd (patch)
treea37029ff3ee3bf4948062c1ebea5db7825e5821a /sound
parent485a1eb9e4a7cb8c78fe67b20a2c503928775e1c (diff)
downloadlinux-stable-dfb76a1333b7261b8e6baac55b80762b79ba07dd.tar.gz
linux-stable-dfb76a1333b7261b8e6baac55b80762b79ba07dd.tar.bz2
linux-stable-dfb76a1333b7261b8e6baac55b80762b79ba07dd.zip
ASoC: wm_adsp: Fix validation of firmware and coeff lengths
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> [bwh: Backported to 3.16: adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/wm_adsp.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index e1215519e4ef..79452f0c8ade 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -622,7 +622,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
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;
@@ -677,8 +677,8 @@ static int wm_adsp_load(struct wm_adsp *dsp)
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,
@@ -1248,7 +1248,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
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);
@@ -1328,8 +1328,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
}
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,