Skip to content

Commit b836ad7

Browse files
committed
firmware: cs_dsp: Fix overflow checking of wmfw header
jira LE-3201 cve CVE-2024-41039 Rebuild_History Non-Buildable kernel-rt-4.18.0-553.22.1.rt7.363.el8_10 commit-author Richard Fitzgerald <rf@opensource.cirrus.com> commit 3019b86 Fix the checking that firmware file buffer is large enough for the wmfw header, to prevent overrunning the buffer. The original code tested that the firmware data buffer contained enough bytes for the sums of the size of the structs wmfw_header + wmfw_adsp1_sizes + wmfw_footer But wmfw_adsp1_sizes is only used on ADSP1 firmware. For ADSP2 and Halo Core the equivalent struct is wmfw_adsp2_sizes, which is 4 bytes longer. So the length check didn't guarantee that there are enough bytes in the firmware buffer for a header with wmfw_adsp2_sizes. This patch splits the length check into three separate parts. Each of the wmfw_header, wmfw_adsp?_sizes and wmfw_footer are checked separately before they are used. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Fixes: f6bc909 ("firmware: cs_dsp: add driver to support firmware loading on Cirrus Logic DSPs") Link: https://patch.msgid.link/20240627141432.93056-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org> (cherry picked from commit 3019b86) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent fe8bc31 commit b836ad7

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

drivers/firmware/cirrus/cs_dsp.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,10 @@ static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp,
13491349
const struct wmfw_adsp1_sizes *adsp1_sizes;
13501350

13511351
adsp1_sizes = (void *)&firmware->data[pos];
1352+
if (sizeof(*adsp1_sizes) > firmware->size - pos) {
1353+
cs_dsp_err(dsp, "%s: file truncated\n", file);
1354+
return 0;
1355+
}
13521356

13531357
cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
13541358
le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
@@ -1365,6 +1369,10 @@ static unsigned int cs_dsp_adsp2_parse_sizes(struct cs_dsp *dsp,
13651369
const struct wmfw_adsp2_sizes *adsp2_sizes;
13661370

13671371
adsp2_sizes = (void *)&firmware->data[pos];
1372+
if (sizeof(*adsp2_sizes) > firmware->size - pos) {
1373+
cs_dsp_err(dsp, "%s: file truncated\n", file);
1374+
return 0;
1375+
}
13681376

13691377
cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
13701378
le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
@@ -1404,7 +1412,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
14041412
struct regmap *regmap = dsp->regmap;
14051413
unsigned int pos = 0;
14061414
const struct wmfw_header *header;
1407-
const struct wmfw_adsp1_sizes *adsp1_sizes;
14081415
const struct wmfw_footer *footer;
14091416
const struct wmfw_region *region;
14101417
const struct cs_dsp_region *mem;
@@ -1420,10 +1427,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
14201427

14211428
ret = -EINVAL;
14221429

1423-
pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1424-
if (pos >= firmware->size) {
1425-
cs_dsp_err(dsp, "%s: file too short, %zu bytes\n",
1426-
file, firmware->size);
1430+
if (sizeof(*header) >= firmware->size) {
1431+
ret = -EOVERFLOW;
14271432
goto out_fw;
14281433
}
14291434

@@ -1451,13 +1456,16 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
14511456

14521457
pos = sizeof(*header);
14531458
pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
1459+
if ((pos == 0) || (sizeof(*footer) > firmware->size - pos)) {
1460+
ret = -EOVERFLOW;
1461+
goto out_fw;
1462+
}
14541463

14551464
footer = (void *)&firmware->data[pos];
14561465
pos += sizeof(*footer);
14571466

14581467
if (le32_to_cpu(header->len) != pos) {
1459-
cs_dsp_err(dsp, "%s: unexpected header length %d\n",
1460-
file, le32_to_cpu(header->len));
1468+
ret = -EOVERFLOW;
14611469
goto out_fw;
14621470
}
14631471

@@ -1583,6 +1591,9 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
15831591
cs_dsp_buf_free(&buf_list);
15841592
kfree(text);
15851593

1594+
if (ret == -EOVERFLOW)
1595+
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
1596+
15861597
return ret;
15871598
}
15881599

0 commit comments

Comments
 (0)