Skip to content

Commit 6598afa

Browse files
rfvirgilbroonie
authored andcommitted
firmware: cs_dsp: Validate payload length before processing block
Move the payload length check in cs_dsp_load() and cs_dsp_coeff_load() to be done before the block is processed. The check that the length of a block payload does not exceed the number of remaining bytes in the firwmware file buffer was being done near the end of the loop iteration. However, some code before that check used the length field without validating it. Signed-off-by: Richard Fitzgerald <[email protected]> Fixes: f6bc909 ("firmware: cs_dsp: add driver to support firmware loading on Cirrus Logic DSPs") Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 959fe01 commit 6598afa

File tree

1 file changed

+15
-21
lines changed

1 file changed

+15
-21
lines changed

drivers/firmware/cirrus/cs_dsp.c

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,12 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
14521452
}
14531453

14541454
region = (void *)&(firmware->data[pos]);
1455+
1456+
if (le32_to_cpu(region->len) > firmware->size - pos - sizeof(*region)) {
1457+
ret = -EOVERFLOW;
1458+
goto out_fw;
1459+
}
1460+
14551461
region_name = "Unknown";
14561462
reg = 0;
14571463
text = NULL;
@@ -1508,16 +1514,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
15081514
regions, le32_to_cpu(region->len), offset,
15091515
region_name);
15101516

1511-
if (le32_to_cpu(region->len) >
1512-
firmware->size - pos - sizeof(*region)) {
1513-
cs_dsp_err(dsp,
1514-
"%s.%d: %s region len %d bytes exceeds file length %zu\n",
1515-
file, regions, region_name,
1516-
le32_to_cpu(region->len), firmware->size);
1517-
ret = -EINVAL;
1518-
goto out_fw;
1519-
}
1520-
15211517
if (text) {
15221518
memcpy(text, region->data, le32_to_cpu(region->len));
15231519
cs_dsp_info(dsp, "%s: %s\n", file, text);
@@ -2147,6 +2143,11 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
21472143

21482144
blk = (void *)(&firmware->data[pos]);
21492145

2146+
if (le32_to_cpu(blk->len) > firmware->size - pos - sizeof(*blk)) {
2147+
ret = -EOVERFLOW;
2148+
goto out_fw;
2149+
}
2150+
21502151
type = le16_to_cpu(blk->type);
21512152
offset = le16_to_cpu(blk->offset);
21522153
version = le32_to_cpu(blk->ver) >> 8;
@@ -2243,17 +2244,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
22432244
}
22442245

22452246
if (reg) {
2246-
if (le32_to_cpu(blk->len) >
2247-
firmware->size - pos - sizeof(*blk)) {
2248-
cs_dsp_err(dsp,
2249-
"%s.%d: %s region len %d bytes exceeds file length %zu\n",
2250-
file, blocks, region_name,
2251-
le32_to_cpu(blk->len),
2252-
firmware->size);
2253-
ret = -EINVAL;
2254-
goto out_fw;
2255-
}
2256-
22572247
buf = cs_dsp_buf_alloc(blk->data,
22582248
le32_to_cpu(blk->len),
22592249
&buf_list);
@@ -2293,6 +2283,10 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
22932283
regmap_async_complete(regmap);
22942284
cs_dsp_buf_free(&buf_list);
22952285
kfree(text);
2286+
2287+
if (ret == -EOVERFLOW)
2288+
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
2289+
22962290
return ret;
22972291
}
22982292

0 commit comments

Comments
 (0)