Commit 97ed3e50 authored by Steve Lee's avatar Steve Lee Committed by Mark Brown

ASoC: max98390: Fix potential crash during param fw loading

 malformed firmware file can cause out-of-bound access and crash
 during dsm_param bin loading.
  - add MIN/MAX param size to avoid out-of-bound access.
  - read start addr and size of param and check bound.
  - add condition that fw->size > param_size + _PAYLOAD_OFFSET
    to confirm enough data.
Signed-off-by: default avatarSteve Lee <steves.lee@maximintegrated.com>
Link: https://lore.kernel.org/r/20200604054731.21140-1-steves.lee@maximintegrated.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 678916ec
...@@ -754,6 +754,7 @@ static struct snd_soc_dai_driver max98390_dai[] = { ...@@ -754,6 +754,7 @@ static struct snd_soc_dai_driver max98390_dai[] = {
static int max98390_dsm_init(struct snd_soc_component *component) static int max98390_dsm_init(struct snd_soc_component *component)
{ {
int ret; int ret;
int param_size, param_start_addr;
char filename[128]; char filename[128];
const char *vendor, *product; const char *vendor, *product;
struct max98390_priv *max98390 = struct max98390_priv *max98390 =
...@@ -780,14 +781,29 @@ static int max98390_dsm_init(struct snd_soc_component *component) ...@@ -780,14 +781,29 @@ static int max98390_dsm_init(struct snd_soc_component *component)
dev_dbg(component->dev, dev_dbg(component->dev,
"max98390: param fw size %zd\n", "max98390: param fw size %zd\n",
fw->size); fw->size);
if (fw->size < MAX98390_DSM_PARAM_MIN_SIZE) {
dev_err(component->dev,
"param fw is invalid.\n");
goto err_alloc;
}
dsm_param = (char *)fw->data; dsm_param = (char *)fw->data;
param_start_addr = (dsm_param[0] & 0xff) | (dsm_param[1] & 0xff) << 8;
param_size = (dsm_param[2] & 0xff) | (dsm_param[3] & 0xff) << 8;
if (param_size > MAX98390_DSM_PARAM_MAX_SIZE ||
param_start_addr < DSM_STBASS_HPF_B0_BYTE0 ||
fw->size < param_size + MAX98390_DSM_PAYLOAD_OFFSET) {
dev_err(component->dev,
"param fw is invalid.\n");
goto err_alloc;
}
regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80);
dsm_param += MAX98390_DSM_PAYLOAD_OFFSET; dsm_param += MAX98390_DSM_PAYLOAD_OFFSET;
regmap_bulk_write(max98390->regmap, DSM_EQ_BQ1_B0_BYTE0, regmap_bulk_write(max98390->regmap, param_start_addr,
dsm_param, dsm_param, param_size);
fw->size - MAX98390_DSM_PAYLOAD_OFFSET);
release_firmware(fw);
regmap_write(max98390->regmap, MAX98390_R23E1_DSP_GLOBAL_EN, 0x01); regmap_write(max98390->regmap, MAX98390_R23E1_DSP_GLOBAL_EN, 0x01);
err_alloc:
release_firmware(fw);
err: err:
return ret; return ret;
} }
......
...@@ -650,7 +650,8 @@ ...@@ -650,7 +650,8 @@
/* DSM register offset */ /* DSM register offset */
#define MAX98390_DSM_PAYLOAD_OFFSET 16 #define MAX98390_DSM_PAYLOAD_OFFSET 16
#define MAX98390_DSM_PAYLOAD_OFFSET_2 495 #define MAX98390_DSM_PARAM_MAX_SIZE 770
#define MAX98390_DSM_PARAM_MIN_SIZE 670
struct max98390_priv { struct max98390_priv {
struct regmap *regmap; struct regmap *regmap;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment