summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-12-19 14:00:30 +0000
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-08 20:47:32 +0000
commitd62f4bc665f3efd2a3d20134f874608b8afce7a1 (patch)
tree5a1bcd9b6c8b1d735f93891016a1d44e96f0e9c5 /sound
parent45b9ee72d0e70c11a01152ef4bec92718b55906b (diff)
downloadlinux-d62f4bc665f3efd2a3d20134f874608b8afce7a1.tar.bz2
ASoC: wm_asdp: Validate sanity of algorithm count
If we run into I/O problems the algorithm count may be crazy, validate it before we proceed and dump the read data for diagnostic purposes. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/wm_adsp.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index bcc0d0ffe72e..017d5101e789 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -377,10 +377,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
struct wmfw_adsp2_id_hdr adsp2_id;
struct wmfw_adsp1_alg_hdr *adsp1_alg;
struct wmfw_adsp2_alg_hdr *adsp2_alg;
- void *alg;
+ void *alg, *buf;
const struct wm_adsp_region *mem;
unsigned int pos, term;
- size_t algs;
+ size_t algs, buf_size;
__be32 val;
int i, ret;
@@ -411,6 +411,9 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
return ret;
}
+ buf = &adsp1_id;
+ buf_size = sizeof(adsp1_id);
+
algs = be32_to_cpu(adsp1_id.algs);
adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
be32_to_cpu(adsp1_id.fw.id),
@@ -432,6 +435,9 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
return ret;
}
+ buf = &adsp2_id;
+ buf_size = sizeof(adsp2_id);
+
algs = be32_to_cpu(adsp2_id.algs);
adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
be32_to_cpu(adsp2_id.fw.id),
@@ -454,6 +460,13 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
return -EINVAL;
}
+ if (algs > 1024) {
+ adsp_err(dsp, "Algorithm count %zx excessive\n", algs);
+ print_hex_dump_bytes(dev_name(dsp->dev), DUMP_PREFIX_OFFSET,
+ buf, buf_size);
+ return -EINVAL;
+ }
+
/* Read the terminator first to validate the length */
ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val));
if (ret != 0) {