]>
Commit | Line | Data |
---|---|---|
af98e849 GKH |
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); |