drivers/media/tuners/si2157.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
The Si2157 firmware loader treats the firmware blob as fixed 17-byte
records. Each record starts with a command length byte and has only
16 bytes remaining for command data.
The existing check compares the command length only with
SI2157_ARGLEN. That protects the local destination array, but not the
source span of the current firmware record. A length from 17 through
SI2157_ARGLEN therefore makes the memcpy() read into the next record,
or past the final record at the end of the firmware blob.
Name the record and payload sizes, and require the command length to
fit both the current record payload and the destination array before
copying it.
Fixes: a828d72df216 ("[media] si2157: Bounds check firmware")
Cc: stable@vger.kernel.org
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
drivers/media/tuners/si2157.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index d517a91e6fbc..126703e9d92f 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -13,6 +13,9 @@ static int tuner_lock_debug;
module_param(tuner_lock_debug, int, 0644);
MODULE_PARM_DESC(tuner_lock_debug, "if set, signal lock is briefly waited on after setting params");
+#define SI2157_FIRMWARE_RECORD_SIZE 17
+#define SI2157_FIRMWARE_RECORD_PAYLOAD_SIZE (SI2157_FIRMWARE_RECORD_SIZE - 1)
+
/* execute firmware command */
static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)
{
@@ -103,7 +106,7 @@ static int si2157_load_firmware(struct dvb_frontend *fe,
return ret;
/* firmware should be n chunks of 17 bytes */
- if (fw->size % 17 != 0) {
+ if (fw->size % SI2157_FIRMWARE_RECORD_SIZE != 0) {
dev_err(&client->dev, "firmware file '%s' is invalid\n",
fw_name);
ret = -EINVAL;
@@ -113,9 +116,11 @@ static int si2157_load_firmware(struct dvb_frontend *fe,
dev_info(&client->dev, "downloading firmware from file '%s'\n",
fw_name);
- for (remaining = fw->size; remaining > 0; remaining -= 17) {
+ for (remaining = fw->size; remaining > 0;
+ remaining -= SI2157_FIRMWARE_RECORD_SIZE) {
len = fw->data[fw->size - remaining];
- if (len > SI2157_ARGLEN) {
+ if (len > SI2157_FIRMWARE_RECORD_PAYLOAD_SIZE ||
+ len > SI2157_ARGLEN) {
dev_err(&client->dev, "Bad firmware length\n");
ret = -EINVAL;
goto err_release_firmware;
--
2.43.0
© 2016 - 2026 Red Hat, Inc.