mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ALSA: x86: hdmi: fix chmap array missing terminator entry
had_build_channel_allocation_map() allocates a single struct
snd_pcm_chmap_elem via kzalloc() and stores it as
intelhaddata->chmap->chmap. struct snd_pcm_chmap.chmap is expected to
be a zero-terminated array (see snd_pcm_std_chmaps[]), but
had_register_chmap_ctls() never overrides the TLV callback installed
by snd_pcm_add_chmap_ctls(), so the generic pcm_chmap_ctl_tlv() from
ALSA core is left in place.
pcm_chmap_ctl_tlv() is reachable by any local user via
SNDRV_CTL_IOCTL_TLV_READ on the "Playback Channel Map" control and
walks the array with "for (map = info->chmap; map->channels; map++)".
Since the driver's single element is never terminated, this walks
past the allocation. The same pointer is also freed on hot-unplug and
rebuilt on hot-plug under intelhaddata->mutex, while the TLV callback
runs under card->controls_rwsem without that mutex, so the walk can
also race a concurrent free of the array.
Fix this by allocating a second, zeroed element so the array is
properly terminated, and by dropping the inherited TLV callback
entirely at registration time, since the driver never implements one
of its own.
Fixes: 5dab11d897 ("ALSA: x86: hdmi: Add audio support for BYT and CHT")
Cc: stable@vger.kernel.org
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://patch.msgid.link/20261008085411.13742-1-peter.ujfalusi@linux.intel.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
b3e7ddd694
commit
f5e1a9a3fd
|
|
@ -475,7 +475,8 @@ static void had_build_channel_allocation_map(struct snd_intelhad *intelhaddata)
|
|||
kfree(intelhaddata->chmap->chmap);
|
||||
intelhaddata->chmap->chmap = NULL;
|
||||
|
||||
chmap = kzalloc_obj(*chmap);
|
||||
/* info->chmap must be zero-terminated; allocate a spare terminator entry */
|
||||
chmap = kzalloc_objs(*chmap, 2);
|
||||
if (!chmap)
|
||||
return;
|
||||
|
||||
|
|
@ -575,6 +576,12 @@ static int had_register_chmap_ctls(struct snd_intelhad *intelhaddata,
|
|||
intelhaddata->chmap->kctl->info = had_chmap_ctl_info;
|
||||
intelhaddata->chmap->kctl->get = had_chmap_ctl_get;
|
||||
intelhaddata->chmap->chmap = NULL;
|
||||
|
||||
/* drop the inherited TLV read: it walks chmap without our mutex */
|
||||
intelhaddata->chmap->kctl->tlv.c = NULL;
|
||||
intelhaddata->chmap->kctl->vd[0].access &=
|
||||
~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user