]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.18.85/asoc-wm_adsp-don-t-overrun-firmware-file-buffer-when-reading-region-data.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.18.85 / asoc-wm_adsp-don-t-overrun-firmware-file-buffer-when-reading-region-data.patch
1 From foo@baz Tue Nov 28 10:58:31 CET 2017
2 From: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
3 Date: Tue, 20 Dec 2016 10:29:12 +0000
4 Subject: ASoC: wm_adsp: Don't overrun firmware file buffer when reading region data
5
6 From: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
7
8
9 [ Upstream commit 1cab2a84f470e15ecc8e5143bfe9398c6e888032 ]
10
11 Protect against corrupt firmware files by ensuring that the length we
12 get for the data in a region actually lies within the available firmware
13 file data buffer.
14
15 Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
16 Signed-off-by: Mark Brown <broonie@kernel.org>
17 Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
18 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
19 ---
20 sound/soc/codecs/wm_adsp.c | 25 ++++++++++++++++++++++++-
21 1 file changed, 24 insertions(+), 1 deletion(-)
22
23 --- a/sound/soc/codecs/wm_adsp.c
24 +++ b/sound/soc/codecs/wm_adsp.c
25 @@ -532,7 +532,7 @@ static int wm_adsp_load(struct wm_adsp *
26 const struct wmfw_region *region;
27 const struct wm_adsp_region *mem;
28 const char *region_name;
29 - char *file, *text;
30 + char *file, *text = NULL;
31 struct wm_adsp_buf *buf;
32 unsigned int reg;
33 int regions = 0;
34 @@ -677,10 +677,21 @@ static int wm_adsp_load(struct wm_adsp *
35 regions, le32_to_cpu(region->len), offset,
36 region_name);
37
38 + if ((pos + le32_to_cpu(region->len) + sizeof(*region)) >
39 + firmware->size) {
40 + adsp_err(dsp,
41 + "%s.%d: %s region len %d bytes exceeds file length %zu\n",
42 + file, regions, region_name,
43 + le32_to_cpu(region->len), firmware->size);
44 + ret = -EINVAL;
45 + goto out_fw;
46 + }
47 +
48 if (text) {
49 memcpy(text, region->data, le32_to_cpu(region->len));
50 adsp_info(dsp, "%s: %s\n", file, text);
51 kfree(text);
52 + text = NULL;
53 }
54
55 if (reg) {
56 @@ -737,6 +748,7 @@ out_fw:
57 regmap_async_complete(regmap);
58 wm_adsp_buf_free(&buf_list);
59 release_firmware(firmware);
60 + kfree(text);
61 out:
62 kfree(file);
63
64 @@ -1316,6 +1328,17 @@ static int wm_adsp_load_coeff(struct wm_
65 }
66
67 if (reg) {
68 + if ((pos + le32_to_cpu(blk->len) + sizeof(*blk)) >
69 + firmware->size) {
70 + adsp_err(dsp,
71 + "%s.%d: %s region len %d bytes exceeds file length %zu\n",
72 + file, blocks, region_name,
73 + le32_to_cpu(blk->len),
74 + firmware->size);
75 + ret = -EINVAL;
76 + goto out_fw;
77 + }
78 +
79 buf = wm_adsp_buf_alloc(blk->data,
80 le32_to_cpu(blk->len),
81 &buf_list);