Skip to content

Commit fd9f26e

Browse files
larsclausentiwai
authored andcommitted
ALSA: control: Don't access controls outside of protected regions
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: Lars-Peter Clausen <lars@metafoo.de> Acked-by: Jaroslav Kysela <perex@perex.cz> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 82262a4 commit fd9f26e

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

Diff for: sound/core/control.c

+10-5
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
330330
{
331331
struct snd_ctl_elem_id id;
332332
unsigned int idx;
333+
unsigned int count;
333334
int err = -EINVAL;
334335

335336
if (! kcontrol)
@@ -358,8 +359,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
358359
card->controls_count += kcontrol->count;
359360
kcontrol->id.numid = card->last_numid + 1;
360361
card->last_numid += kcontrol->count;
362+
count = kcontrol->count;
361363
up_write(&card->controls_rwsem);
362-
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
364+
for (idx = 0; idx < count; idx++, id.index++, id.numid++)
363365
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
364366
return 0;
365367

@@ -388,6 +390,7 @@ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
388390
bool add_on_replace)
389391
{
390392
struct snd_ctl_elem_id id;
393+
unsigned int count;
391394
unsigned int idx;
392395
struct snd_kcontrol *old;
393396
int ret;
@@ -423,8 +426,9 @@ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
423426
card->controls_count += kcontrol->count;
424427
kcontrol->id.numid = card->last_numid + 1;
425428
card->last_numid += kcontrol->count;
429+
count = kcontrol->count;
426430
up_write(&card->controls_rwsem);
427-
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
431+
for (idx = 0; idx < count; idx++, id.index++, id.numid++)
428432
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
429433
return 0;
430434

@@ -897,9 +901,9 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
897901
result = kctl->put(kctl, control);
898902
}
899903
if (result > 0) {
904+
struct snd_ctl_elem_id id = control->id;
900905
up_read(&card->controls_rwsem);
901-
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
902-
&control->id);
906+
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
903907
return 0;
904908
}
905909
}
@@ -1333,8 +1337,9 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
13331337
}
13341338
err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
13351339
if (err > 0) {
1340+
struct snd_ctl_elem_id id = kctl->id;
13361341
up_read(&card->controls_rwsem);
1337-
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
1342+
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &id);
13381343
return 0;
13391344
}
13401345
} else {

0 commit comments

Comments
 (0)