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>
This commit is contained in:
parent
678916ec54
commit
97ed3e509e
2 changed files with 22 additions and 5 deletions
|
@ -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)
|
||||||
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 @@
|
||||||
|
|
||||||
/* 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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue