Unverified Commit 8a473c39 authored by Fred Oh's avatar Fred Oh Committed by Mark Brown
Browse files

ASoC: Intel: Boards: cml_rt1011_rt5682: use statically define codec config



When the cml_rt1011_rt5682_dailink[].codecs pointer is overridden by
a quirk with a devm allocated structure and the probe is deferred,
in the next probe we will see an use-after-free condition
(verified with KASAN). This can be avoided by using statically allocated
configurations - which simplifies the code quite a bit as well.

KASAN issue fixed.
[   23.301373] cml_rt1011_rt5682 cml_rt1011_rt5682: sof_rt1011_quirk = f
[   23.301875] ==================================================================
[   23.302018] BUG: KASAN: use-after-free in snd_cml_rt1011_probe+0x23a/0x3d0 [snd_soc_cml_rt1011_rt5682]
[   23.302178] Read of size 8 at addr ffff8881ec6acae0 by task kworker/0:2/105
[   23.302320] CPU: 0 PID: 105 Comm: kworker/0:2 Not tainted 5.7.0-rc7-test+ #3
[   23.302322] Hardware name: Google Helios/Helios, BIOS  01/21/2020
[   23.302329] Workqueue: events deferred_probe_work_func
[   23.302331] Call Trace:
[   23.302339]  dump_stack+0x76/0xa0
[   23.302345]  print_address_description.constprop.0.cold+0xd3/0x43e
[   23.302351]  ? _raw_spin_lock_irqsave+0x7b/0xd0
[   23.302355]  ? _raw_spin_trylock_bh+0xf0/0xf0
[   23.302362]  ? snd_cml_rt1011_probe+0x23a/0x3d0 [snd_soc_cml_rt1011_rt5682]
[   23.302365]  __kasan_report.cold+0x37/0x86
[   23.302371]  ? snd_cml_rt1011_probe+0x23a/0x3d0 [snd_soc_cml_rt1011_rt5682]
[   23.302375]  kasan_report+0x38/0x50
[   23.302382]  snd_cml_rt1011_probe+0x23a/0x3d0 [snd_soc_cml_rt1011_rt5682]
[   23.302389]  platform_drv_probe+0x66/0xc0

Fixes: 629ba12e ("ASoC: Intel: boards: split woofer and tweeter support")
Suggested-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: default avatarFred Oh <fred.oh@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Link: https://lore.kernel.org/r/20200625191308.3322-12-pierre-louis.bossart@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent e1a31c09
Loading
Loading
Loading
Loading
+23 −60
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@
#define SOF_RT1011_SPEAKER_WR		BIT(1)
#define SOF_RT1011_SPEAKER_TL		BIT(2)
#define SOF_RT1011_SPEAKER_TR		BIT(3)
#define SPK_CH 4

/* Default: Woofer speakers  */
static unsigned long sof_rt1011_quirk = SOF_RT1011_SPEAKER_WL |
@@ -383,10 +382,17 @@ SND_SOC_DAILINK_DEF(ssp0_codec,

SND_SOC_DAILINK_DEF(ssp1_pin,
	DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
SND_SOC_DAILINK_DEF(ssp1_codec,
SND_SOC_DAILINK_DEF(ssp1_codec_2spk,
	DAILINK_COMP_ARRAY(
	/* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI),
	/* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI)));
SND_SOC_DAILINK_DEF(ssp1_codec_4spk,
	DAILINK_COMP_ARRAY(
	/* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI),
	/* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI),
	/* TL */ COMP_CODEC("i2c-10EC1011:02", CML_RT1011_CODEC_DAI),
	/* TR */ COMP_CODEC("i2c-10EC1011:03", CML_RT1011_CODEC_DAI)));


SND_SOC_DAILINK_DEF(dmic_pin,
	DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
@@ -483,7 +489,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = {
		.no_pcm = 1,
		.init = cml_rt1011_spk_init,
		.ops = &cml_rt1011_ops,
		SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform),
		SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec_2spk, platform),
	},
};

@@ -496,6 +502,15 @@ static struct snd_soc_codec_conf rt1011_conf[] = {
		.dlc = COMP_CODEC_CONF("i2c-10EC1011:01"),
		.name_prefix = "WR",
	},
	/* single configuration structure for 2 and 4 channels */
	{
		.dlc = COMP_CODEC_CONF("i2c-10EC1011:02"),
		.name_prefix = "TL",
	},
	{
		.dlc = COMP_CODEC_CONF("i2c-10EC1011:03"),
		.name_prefix = "TR",
	},
};

/* Cometlake audio machine driver for RT1011 and RT5682 */
@@ -518,8 +533,6 @@ static struct snd_soc_card snd_soc_card_cml = {

static int snd_cml_rt1011_probe(struct platform_device *pdev)
{
	struct snd_soc_dai_link_component *rt1011_dais_components;
	struct snd_soc_codec_conf *rt1011_dais_confs;
	struct card_private *ctx;
	struct snd_soc_acpi_mach *mach;
	const char *platform_name;
@@ -538,65 +551,15 @@ static int snd_cml_rt1011_probe(struct platform_device *pdev)

	dev_dbg(&pdev->dev, "sof_rt1011_quirk = %lx\n", sof_rt1011_quirk);

	/* when 4 speaker is available, update codec config */
	if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL |
				SOF_RT1011_SPEAKER_TR)) {
		rt1011_dais_confs = devm_kzalloc(&pdev->dev,
					sizeof(struct snd_soc_codec_conf) *
					SPK_CH, GFP_KERNEL);

		if (!rt1011_dais_confs)
			return -ENOMEM;

		rt1011_dais_components = devm_kzalloc(&pdev->dev,
					sizeof(struct snd_soc_dai_link_component) *
					SPK_CH, GFP_KERNEL);

		if (!rt1011_dais_components)
			return -ENOMEM;

		for (i = 0; i < SPK_CH; i++) {
			rt1011_dais_confs[i].dlc.name = devm_kasprintf(&pdev->dev,
								GFP_KERNEL,
								"i2c-10EC1011:0%d",
								i);

			if (!rt1011_dais_confs[i].dlc.name)
				return -ENOMEM;

			switch (i) {
			case 0:
				rt1011_dais_confs[i].name_prefix = "WL";
				break;
			case 1:
				rt1011_dais_confs[i].name_prefix = "WR";
				break;
			case 2:
				rt1011_dais_confs[i].name_prefix = "TL";
				break;
			case 3:
				rt1011_dais_confs[i].name_prefix = "TR";
				break;
			default:
				return -EINVAL;
			}
			rt1011_dais_components[i].name = devm_kasprintf(&pdev->dev,
								GFP_KERNEL,
								"i2c-10EC1011:0%d",
								i);
			if (!rt1011_dais_components[i].name)
				return -ENOMEM;

			rt1011_dais_components[i].dai_name = CML_RT1011_CODEC_DAI;
		}

		snd_soc_card_cml.codec_conf = rt1011_dais_confs;
		snd_soc_card_cml.num_configs = SPK_CH;

		for (i = 0; i < ARRAY_SIZE(cml_rt1011_rt5682_dailink); i++) {
			if (!strcmp(cml_rt1011_rt5682_dailink[i].codecs->dai_name,
				    CML_RT1011_CODEC_DAI)) {
				cml_rt1011_rt5682_dailink[i].codecs = rt1011_dais_components;
				cml_rt1011_rt5682_dailink[i].num_codecs = SPK_CH;
				cml_rt1011_rt5682_dailink[i].codecs = ssp1_codec_4spk;
				cml_rt1011_rt5682_dailink[i].num_codecs =
						ARRAY_SIZE(ssp1_codec_4spk);
			}
		}
	}