Skip to content

Commit b6a49cc

Browse files
tiwaigregkh
authored andcommitted
ALSA: aloop: Add missing cable lock to ctl API callbacks
commit 76b3421b39bd610546931fc923edcf90c18fa395 upstream. Some control API callbacks in aloop driver are too lazy to take the loopback->cable_lock and it results in possible races of cable access while it's being freed. It eventually lead to a UAF, as reported by fuzzer recently. This patch covers such control API callbacks and add the proper mutex locks. Reported-by: DaeRyong Jeong <[email protected]> Cc: <[email protected]> Signed-off-by: Takashi Iwai <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 68f4bc3 commit b6a49cc

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

sound/drivers/aloop.c

+15-2
Original file line numberDiff line numberDiff line change
@@ -832,9 +832,11 @@ static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol,
832832
{
833833
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
834834

835+
mutex_lock(&loopback->cable_lock);
835836
ucontrol->value.integer.value[0] =
836837
loopback->setup[kcontrol->id.subdevice]
837838
[kcontrol->id.device].rate_shift;
839+
mutex_unlock(&loopback->cable_lock);
838840
return 0;
839841
}
840842

@@ -866,9 +868,11 @@ static int loopback_notify_get(struct snd_kcontrol *kcontrol,
866868
{
867869
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
868870

871+
mutex_lock(&loopback->cable_lock);
869872
ucontrol->value.integer.value[0] =
870873
loopback->setup[kcontrol->id.subdevice]
871874
[kcontrol->id.device].notify;
875+
mutex_unlock(&loopback->cable_lock);
872876
return 0;
873877
}
874878

@@ -880,28 +884,33 @@ static int loopback_notify_put(struct snd_kcontrol *kcontrol,
880884
int change = 0;
881885

882886
val = ucontrol->value.integer.value[0] ? 1 : 0;
887+
mutex_lock(&loopback->cable_lock);
883888
if (val != loopback->setup[kcontrol->id.subdevice]
884889
[kcontrol->id.device].notify) {
885890
loopback->setup[kcontrol->id.subdevice]
886891
[kcontrol->id.device].notify = val;
887892
change = 1;
888893
}
894+
mutex_unlock(&loopback->cable_lock);
889895
return change;
890896
}
891897

892898
static int loopback_active_get(struct snd_kcontrol *kcontrol,
893899
struct snd_ctl_elem_value *ucontrol)
894900
{
895901
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
896-
struct loopback_cable *cable = loopback->cables
897-
[kcontrol->id.subdevice][kcontrol->id.device ^ 1];
902+
struct loopback_cable *cable;
903+
898904
unsigned int val = 0;
899905

906+
mutex_lock(&loopback->cable_lock);
907+
cable = loopback->cables[kcontrol->id.subdevice][kcontrol->id.device ^ 1];
900908
if (cable != NULL) {
901909
unsigned int running = cable->running ^ cable->pause;
902910

903911
val = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? 1 : 0;
904912
}
913+
mutex_unlock(&loopback->cable_lock);
905914
ucontrol->value.integer.value[0] = val;
906915
return 0;
907916
}
@@ -944,9 +953,11 @@ static int loopback_rate_get(struct snd_kcontrol *kcontrol,
944953
{
945954
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
946955

956+
mutex_lock(&loopback->cable_lock);
947957
ucontrol->value.integer.value[0] =
948958
loopback->setup[kcontrol->id.subdevice]
949959
[kcontrol->id.device].rate;
960+
mutex_unlock(&loopback->cable_lock);
950961
return 0;
951962
}
952963

@@ -966,9 +977,11 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
966977
{
967978
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
968979

980+
mutex_lock(&loopback->cable_lock);
969981
ucontrol->value.integer.value[0] =
970982
loopback->setup[kcontrol->id.subdevice]
971983
[kcontrol->id.device].channels;
984+
mutex_unlock(&loopback->cable_lock);
972985
return 0;
973986
}
974987

0 commit comments

Comments
 (0)