summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Lee <steves.lee@maximintegrated.com>2020-06-04 14:47:31 +0900
committerMark Brown <broonie@kernel.org>2020-06-04 15:04:30 +0100
commit97ed3e509ee6d098730d137759c627a8d674cf55 (patch)
tree7882c3fd83288bd028efc71061439ddf7d3060e3
parent678916ec54f38406032462dc466fd36cdfea4e3c (diff)
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: Steve Lee <steves.lee@maximintegrated.com> Link: https://lore.kernel.org/r/20200604054731.21140-1-steves.lee@maximintegrated.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/max98390.c24
-rw-r--r--sound/soc/codecs/max98390.h3
2 files changed, 22 insertions, 5 deletions
diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c
index be7cd0aeb6a6..0d63ebfbff2f 100644
--- a/sound/soc/codecs/max98390.c
+++ b/sound/soc/codecs/max98390.c
@@ -754,6 +754,7 @@ static struct snd_soc_dai_driver max98390_dai[] = {
static int max98390_dsm_init(struct snd_soc_component *component)
{
int ret;
+ int param_size, param_start_addr;
char filename[128];
const char *vendor, *product;
struct max98390_priv *max98390 =
@@ -780,14 +781,29 @@ static int max98390_dsm_init(struct snd_soc_component *component)
dev_dbg(component->dev,
"max98390: param fw size %zd\n",
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;
+ 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;
- regmap_bulk_write(max98390->regmap, DSM_EQ_BQ1_B0_BYTE0,
- dsm_param,
- fw->size - MAX98390_DSM_PAYLOAD_OFFSET);
- release_firmware(fw);
+ regmap_bulk_write(max98390->regmap, param_start_addr,
+ dsm_param, param_size);
regmap_write(max98390->regmap, MAX98390_R23E1_DSP_GLOBAL_EN, 0x01);
+err_alloc:
+ release_firmware(fw);
err:
return ret;
}
diff --git a/sound/soc/codecs/max98390.h b/sound/soc/codecs/max98390.h
index f59cb114d957..5f444e7779b0 100644
--- a/sound/soc/codecs/max98390.h
+++ b/sound/soc/codecs/max98390.h
@@ -650,7 +650,8 @@
/* DSM register offset */
#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 regmap *regmap;