]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ASoC: wm_asdp: Validate sanity of algorithm count
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 19 Dec 2012 14:00:30 +0000 (14:00 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Tue, 8 Jan 2013 20:47:32 +0000 (20:47 +0000)
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>
sound/soc/codecs/wm_adsp.c

index bcc0d0ffe72ecfce9a4a0db0de15b1c606f9cd54..017d5101e7897e3ffddd5f918204c1030cf9c5eb 100644 (file)
@@ -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) {