summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-04-30 04:06:48 -0400
committerTakashi Iwai <tiwai@suse.de>2018-04-30 04:06:48 -0400
commit76b3421b39bd610546931fc923edcf90c18fa395 (patch)
treef27e1ca71c7053ccd68c6ec44163410a6b8ed6a9 /sound
parent52759c0963510a2843774aac9b65ccaed3308dc0 (diff)
ALSA: aloop: Add missing cable lock to ctl API callbacks
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 <threeearcat@gmail.com> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/drivers/aloop.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 58e349fc893f..eab7f594ebe7 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -831,9 +831,11 @@ static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol,
831{ 831{
832 struct loopback *loopback = snd_kcontrol_chip(kcontrol); 832 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
833 833
834 mutex_lock(&loopback->cable_lock);
834 ucontrol->value.integer.value[0] = 835 ucontrol->value.integer.value[0] =
835 loopback->setup[kcontrol->id.subdevice] 836 loopback->setup[kcontrol->id.subdevice]
836 [kcontrol->id.device].rate_shift; 837 [kcontrol->id.device].rate_shift;
838 mutex_unlock(&loopback->cable_lock);
837 return 0; 839 return 0;
838} 840}
839 841
@@ -865,9 +867,11 @@ static int loopback_notify_get(struct snd_kcontrol *kcontrol,
865{ 867{
866 struct loopback *loopback = snd_kcontrol_chip(kcontrol); 868 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
867 869
870 mutex_lock(&loopback->cable_lock);
868 ucontrol->value.integer.value[0] = 871 ucontrol->value.integer.value[0] =
869 loopback->setup[kcontrol->id.subdevice] 872 loopback->setup[kcontrol->id.subdevice]
870 [kcontrol->id.device].notify; 873 [kcontrol->id.device].notify;
874 mutex_unlock(&loopback->cable_lock);
871 return 0; 875 return 0;
872} 876}
873 877
@@ -879,12 +883,14 @@ static int loopback_notify_put(struct snd_kcontrol *kcontrol,
879 int change = 0; 883 int change = 0;
880 884
881 val = ucontrol->value.integer.value[0] ? 1 : 0; 885 val = ucontrol->value.integer.value[0] ? 1 : 0;
886 mutex_lock(&loopback->cable_lock);
882 if (val != loopback->setup[kcontrol->id.subdevice] 887 if (val != loopback->setup[kcontrol->id.subdevice]
883 [kcontrol->id.device].notify) { 888 [kcontrol->id.device].notify) {
884 loopback->setup[kcontrol->id.subdevice] 889 loopback->setup[kcontrol->id.subdevice]
885 [kcontrol->id.device].notify = val; 890 [kcontrol->id.device].notify = val;
886 change = 1; 891 change = 1;
887 } 892 }
893 mutex_unlock(&loopback->cable_lock);
888 return change; 894 return change;
889} 895}
890 896
@@ -892,15 +898,18 @@ static int loopback_active_get(struct snd_kcontrol *kcontrol,
892 struct snd_ctl_elem_value *ucontrol) 898 struct snd_ctl_elem_value *ucontrol)
893{ 899{
894 struct loopback *loopback = snd_kcontrol_chip(kcontrol); 900 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
895 struct loopback_cable *cable = loopback->cables 901 struct loopback_cable *cable;
896 [kcontrol->id.subdevice][kcontrol->id.device ^ 1]; 902
897 unsigned int val = 0; 903 unsigned int val = 0;
898 904
905 mutex_lock(&loopback->cable_lock);
906 cable = loopback->cables[kcontrol->id.subdevice][kcontrol->id.device ^ 1];
899 if (cable != NULL) { 907 if (cable != NULL) {
900 unsigned int running = cable->running ^ cable->pause; 908 unsigned int running = cable->running ^ cable->pause;
901 909
902 val = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? 1 : 0; 910 val = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? 1 : 0;
903 } 911 }
912 mutex_unlock(&loopback->cable_lock);
904 ucontrol->value.integer.value[0] = val; 913 ucontrol->value.integer.value[0] = val;
905 return 0; 914 return 0;
906} 915}
@@ -943,9 +952,11 @@ static int loopback_rate_get(struct snd_kcontrol *kcontrol,
943{ 952{
944 struct loopback *loopback = snd_kcontrol_chip(kcontrol); 953 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
945 954
955 mutex_lock(&loopback->cable_lock);
946 ucontrol->value.integer.value[0] = 956 ucontrol->value.integer.value[0] =
947 loopback->setup[kcontrol->id.subdevice] 957 loopback->setup[kcontrol->id.subdevice]
948 [kcontrol->id.device].rate; 958 [kcontrol->id.device].rate;
959 mutex_unlock(&loopback->cable_lock);
949 return 0; 960 return 0;
950} 961}
951 962
@@ -965,9 +976,11 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
965{ 976{
966 struct loopback *loopback = snd_kcontrol_chip(kcontrol); 977 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
967 978
979 mutex_lock(&loopback->cable_lock);
968 ucontrol->value.integer.value[0] = 980 ucontrol->value.integer.value[0] =
969 loopback->setup[kcontrol->id.subdevice] 981 loopback->setup[kcontrol->id.subdevice]
970 [kcontrol->id.device].channels; 982 [kcontrol->id.device].channels;
983 mutex_unlock(&loopback->cable_lock);
971 return 0; 984 return 0;
972} 985}
973 986