From: Gergo Koteles soyer@irl.hu
stable inclusion from stable-v6.6.8 commit 7fc8bfdb7007ccd013eb786c76f6619da56a98f2 bugzilla: https://gitee.com/openeuler/kernel/issues/I99K53
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 75a25d31b80770485641ad2789a854955f5c1e40 upstream.
Unloading then loading the module causes a NULL ponter dereference.
The hda_unbind zeroes the hda_component, later the hda_bind tries to dereference the codec field.
The hda_component is only initialized once by tas2781_generic_fixup.
Set only previously modified fields to NULL.
BUG: kernel NULL pointer dereference, address: 0000000000000322 Call Trace: <TASK> ? __die+0x23/0x70 ? page_fault_oops+0x171/0x4e0 ? exc_page_fault+0x7f/0x180 ? asm_exc_page_fault+0x26/0x30 ? tas2781_hda_bind+0x59/0x140 [snd_hda_scodec_tas2781_i2c] component_bind_all+0xf3/0x240 try_to_bring_up_aggregate_device+0x1c3/0x270 __component_add+0xbc/0x1a0 tas2781_hda_i2c_probe+0x289/0x3a0 [snd_hda_scodec_tas2781_i2c] i2c_device_probe+0x136/0x2e0
Fixes: 5be27f1e3ec9 ("ALSA: hda/tas2781: Add tas2781 HDA driver") Cc: stable@vger.kernel.org Signed-off-by: Gergo Koteles soyer@irl.hu Link: https://lore.kernel.org/r/8b8ed2bd5f75fbb32e354a3226c2f966fa85b46b.170215652... Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: ZhangPeng zhangpeng362@huawei.com --- sound/pci/hda/tas2781_hda_i2c.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index fb802802939e..b42837105c22 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -612,9 +612,13 @@ static void tas2781_hda_unbind(struct device *dev, { struct tasdevice_priv *tas_priv = dev_get_drvdata(dev); struct hda_component *comps = master_data; + comps = &comps[tas_priv->index];
- if (comps[tas_priv->index].dev == dev) - memset(&comps[tas_priv->index], 0, sizeof(*comps)); + if (comps->dev == dev) { + comps->dev = NULL; + memset(comps->name, 0, sizeof(comps->name)); + comps->playback_hook = NULL; + }
tasdevice_config_info_remove(tas_priv); tasdevice_dsp_remove(tas_priv);