* [PATCH] ASoC: tas2781: bound firmware description string parsing
@ 2026-07-01 5:32 Pengpeng Hou
2026-07-02 18:33 ` Mark Brown
0 siblings, 1 reply; 2+ messages in thread
From: Pengpeng Hou @ 2026-07-01 5:32 UTC (permalink / raw)
To: Shenghao Ding, Kevin Lu, Baojun Xu, Liam Girdwood, Mark Brown,
Jaroslav Kysela, Takashi Iwai
Cc: Pengpeng Hou, linux-sound, linux-kernel
The TAS2781 firmware parser reads several variable-length description
strings with strlen() before checking that the string terminator is
present inside the firmware blob. A malformed firmware image without a
NUL terminator can therefore make the parser walk past the end of the
firmware buffer before the later size checks run.
Add a small bounded string-length helper and use it for all description
fields that are parsed from the firmware buffer. Keep the existing size
checks for the fixed bytes that follow each string.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
sound/soc/codecs/tas2781-fmwlib.c | 55 ++++++++++++++++++++++++++++++++++---
1 file changed, 50 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index 885e0b6f..4ef9ad86 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -12,6 +12,7 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/limits.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
@@ -1099,13 +1100,37 @@ static int tasdevice_load_block_kernel(
return 0;
}
+static int tasdevice_fw_strnlen(const struct firmware *fmw, int offset)
+{
+ size_t remaining;
+ size_t len;
+
+ if (offset < 0 || offset >= fmw->size)
+ return -EINVAL;
+
+ remaining = fmw->size - offset;
+ len = strnlen((const char *)fmw->data + offset, remaining);
+ if (len == remaining)
+ return -EINVAL;
+ if (len > INT_MAX)
+ return -EOVERFLOW;
+
+ return len;
+}
+
static int fw_parse_variable_hdr(struct tasdevice_priv
*tas_priv, struct tasdevice_dspfw_hdr *fw_hdr,
const struct firmware *fmw, int offset)
{
const unsigned char *buf = fmw->data;
- int len = strlen((char *)&buf[offset]);
+ int len;
+ len = tasdevice_fw_strnlen(fmw, offset);
+ if (len < 0) {
+ dev_err(tas_priv->dev, "%s: Description error\n", __func__);
+ offset = len;
+ goto out;
+ }
len++;
if (offset + len + 8 > fmw->size) {
@@ -1237,7 +1262,12 @@ static int fw_parse_data(struct tasdevice_fw *tas_fmw,
memcpy(img_data->name, &data[offset], 64);
offset += 64;
- n = strlen((char *)&data[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
+ offset = n;
+ goto out;
+ }
n++;
if (offset + n + 2 > fmw->size) {
dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
@@ -1308,7 +1338,12 @@ static int fw_parse_program_data(struct tasdevice_priv *tas_priv,
}
offset += 64;
- n = strlen((char *)&buf[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_priv->dev, "Description err\n");
+ offset = n;
+ goto out;
+ }
/* skip '\0' and 5 unused bytes */
n += 6;
if (offset + n > fmw->size) {
@@ -1371,7 +1406,12 @@ static int fw_parse_configuration_data(
memcpy(config->name, &data[offset], 64);
offset += 64;
- n = strlen((char *)&data[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_priv->dev, "Description err\n");
+ offset = n;
+ goto out;
+ }
n += 15;
if (offset + n > fmw->size) {
dev_err(tas_priv->dev, "Description err\n");
@@ -2165,7 +2205,12 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv,
calibration = &(tas_fmw->calibrations[i]);
offset += 64;
- n = strlen((char *)&data[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_priv->dev, "Description err\n");
+ offset = n;
+ goto out;
+ }
/* skip '\0' and 2 unused bytes */
n += 3;
if (offset + n > fmw->size) {
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] ASoC: tas2781: bound firmware description string parsing
2026-07-01 5:32 [PATCH] ASoC: tas2781: bound firmware description string parsing Pengpeng Hou
@ 2026-07-02 18:33 ` Mark Brown
0 siblings, 0 replies; 2+ messages in thread
From: Mark Brown @ 2026-07-02 18:33 UTC (permalink / raw)
To: Pengpeng Hou
Cc: Shenghao Ding, Kevin Lu, Baojun Xu, Liam Girdwood,
Jaroslav Kysela, Takashi Iwai, linux-sound, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 511 bytes --]
On Wed, Jul 01, 2026 at 01:32:55PM +0800, Pengpeng Hou wrote:
> @@ -2165,7 +2205,12 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv,
> calibration = &(tas_fmw->calibrations[i]);
> offset += 64;
>
> - n = strlen((char *)&data[offset]);
> + n = tasdevice_fw_strnlen(fmw, offset);
> + if (n < 0) {
> + dev_err(tas_priv->dev, "Description err\n");
> + offset = n;
> + goto out;
> + }
In this case n is an unsigned number so the error check is broken here.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-02 18:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-01 5:32 [PATCH] ASoC: tas2781: bound firmware description string parsing Pengpeng Hou
2026-07-02 18:33 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox