Commit 79b789d8 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Ben Hutchings

ALSA: control: Don't access controls outside of protected regions

commit fd9f26e4 upstream.

A control that is visible on the card->controls list can be freed at any time.
This means we must not access any of its memory while not holding the
controls_rw_lock. Otherwise we risk a use after free access.
Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Acked-by: default avatarJaroslav Kysela <perex@perex.cz>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 0e2e43ec
...@@ -329,6 +329,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) ...@@ -329,6 +329,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
{ {
struct snd_ctl_elem_id id; struct snd_ctl_elem_id id;
unsigned int idx; unsigned int idx;
unsigned int count;
int err = -EINVAL; int err = -EINVAL;
if (! kcontrol) if (! kcontrol)
...@@ -357,8 +358,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) ...@@ -357,8 +358,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
card->controls_count += kcontrol->count; card->controls_count += kcontrol->count;
kcontrol->id.numid = card->last_numid + 1; kcontrol->id.numid = card->last_numid + 1;
card->last_numid += kcontrol->count; card->last_numid += kcontrol->count;
count = kcontrol->count;
up_write(&card->controls_rwsem); up_write(&card->controls_rwsem);
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) for (idx = 0; idx < count; idx++, id.index++, id.numid++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
return 0; return 0;
...@@ -387,6 +389,7 @@ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, ...@@ -387,6 +389,7 @@ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
bool add_on_replace) bool add_on_replace)
{ {
struct snd_ctl_elem_id id; struct snd_ctl_elem_id id;
unsigned int count;
unsigned int idx; unsigned int idx;
struct snd_kcontrol *old; struct snd_kcontrol *old;
int ret; int ret;
...@@ -422,8 +425,9 @@ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, ...@@ -422,8 +425,9 @@ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
card->controls_count += kcontrol->count; card->controls_count += kcontrol->count;
kcontrol->id.numid = card->last_numid + 1; kcontrol->id.numid = card->last_numid + 1;
card->last_numid += kcontrol->count; card->last_numid += kcontrol->count;
count = kcontrol->count;
up_write(&card->controls_rwsem); up_write(&card->controls_rwsem);
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) for (idx = 0; idx < count; idx++, id.index++, id.numid++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
return 0; return 0;
...@@ -894,9 +898,9 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, ...@@ -894,9 +898,9 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
result = kctl->put(kctl, control); result = kctl->put(kctl, control);
} }
if (result > 0) { if (result > 0) {
struct snd_ctl_elem_id id = control->id;
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
&control->id);
return 0; return 0;
} }
} }
...@@ -1330,8 +1334,9 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, ...@@ -1330,8 +1334,9 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
} }
err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv); err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
if (err > 0) { if (err > 0) {
struct snd_ctl_elem_id id = kctl->id;
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id); snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &id);
return 0; return 0;
} }
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment