@@ -150,14 +150,14 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
150150 return ;
151151 if (card -> shutdown )
152152 return ;
153- read_lock (& card -> ctl_files_rwlock );
153+ read_lock_irqsave (& card -> ctl_files_rwlock , flags );
154154#if IS_ENABLED (CONFIG_SND_MIXER_OSS )
155155 card -> mixer_oss_change_count ++ ;
156156#endif
157157 list_for_each_entry (ctl , & card -> ctl_files , list ) {
158158 if (!ctl -> subscribed )
159159 continue ;
160- spin_lock_irqsave (& ctl -> read_lock , flags );
160+ spin_lock (& ctl -> read_lock );
161161 list_for_each_entry (ev , & ctl -> events , list ) {
162162 if (ev -> id .numid == id -> numid ) {
163163 ev -> mask |= mask ;
@@ -174,10 +174,10 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
174174 }
175175 _found :
176176 wake_up (& ctl -> change_sleep );
177- spin_unlock_irqrestore (& ctl -> read_lock , flags );
177+ spin_unlock (& ctl -> read_lock );
178178 kill_fasync (& ctl -> fasync , SIGIO , POLL_IN );
179179 }
180- read_unlock (& card -> ctl_files_rwlock );
180+ read_unlock_irqrestore (& card -> ctl_files_rwlock , flags );
181181}
182182EXPORT_SYMBOL (snd_ctl_notify );
183183
@@ -717,22 +717,19 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
717717}
718718
719719static int snd_ctl_elem_list (struct snd_card * card ,
720- struct snd_ctl_elem_list __user * _list )
720+ struct snd_ctl_elem_list * list )
721721{
722- struct snd_ctl_elem_list list ;
723722 struct snd_kcontrol * kctl ;
724723 struct snd_ctl_elem_id id ;
725724 unsigned int offset , space , jidx ;
726725 int err = 0 ;
727726
728- if (copy_from_user (& list , _list , sizeof (list )))
729- return - EFAULT ;
730- offset = list .offset ;
731- space = list .space ;
727+ offset = list -> offset ;
728+ space = list -> space ;
732729
733730 down_read (& card -> controls_rwsem );
734- list . count = card -> controls_count ;
735- list . used = 0 ;
731+ list -> count = card -> controls_count ;
732+ list -> used = 0 ;
736733 if (space > 0 ) {
737734 list_for_each_entry (kctl , & card -> controls , list ) {
738735 if (offset >= kctl -> count ) {
@@ -741,12 +738,12 @@ static int snd_ctl_elem_list(struct snd_card *card,
741738 }
742739 for (jidx = offset ; jidx < kctl -> count ; jidx ++ ) {
743740 snd_ctl_build_ioff (& id , kctl , jidx );
744- if (copy_to_user (list . pids + list . used , & id ,
741+ if (copy_to_user (list -> pids + list -> used , & id ,
745742 sizeof (id ))) {
746743 err = - EFAULT ;
747744 goto out ;
748745 }
749- list . used ++ ;
746+ list -> used ++ ;
750747 if (!-- space )
751748 goto out ;
752749 }
@@ -755,11 +752,26 @@ static int snd_ctl_elem_list(struct snd_card *card,
755752 }
756753 out :
757754 up_read (& card -> controls_rwsem );
758- if (!err && copy_to_user (_list , & list , sizeof (list )))
759- err = - EFAULT ;
760755 return err ;
761756}
762757
758+ static int snd_ctl_elem_list_user (struct snd_card * card ,
759+ struct snd_ctl_elem_list __user * _list )
760+ {
761+ struct snd_ctl_elem_list list ;
762+ int err ;
763+
764+ if (copy_from_user (& list , _list , sizeof (list )))
765+ return - EFAULT ;
766+ err = snd_ctl_elem_list (card , & list );
767+ if (err )
768+ return err ;
769+ if (copy_to_user (_list , & list , sizeof (list )))
770+ return - EFAULT ;
771+
772+ return 0 ;
773+ }
774+
763775/* Check whether the given kctl info is valid */
764776static int snd_ctl_check_elem_info (struct snd_card * card ,
765777 const struct snd_ctl_elem_info * info )
@@ -1703,7 +1715,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
17031715 case SNDRV_CTL_IOCTL_CARD_INFO :
17041716 return snd_ctl_card_info (card , ctl , cmd , argp );
17051717 case SNDRV_CTL_IOCTL_ELEM_LIST :
1706- return snd_ctl_elem_list (card , argp );
1718+ return snd_ctl_elem_list_user (card , argp );
17071719 case SNDRV_CTL_IOCTL_ELEM_INFO :
17081720 return snd_ctl_elem_info_user (ctl , argp );
17091721 case SNDRV_CTL_IOCTL_ELEM_READ :
@@ -1939,16 +1951,17 @@ int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
19391951{
19401952 struct snd_ctl_file * kctl ;
19411953 int subdevice = -1 ;
1954+ unsigned long flags ;
19421955
1943- read_lock (& card -> ctl_files_rwlock );
1956+ read_lock_irqsave (& card -> ctl_files_rwlock , flags );
19441957 list_for_each_entry (kctl , & card -> ctl_files , list ) {
19451958 if (kctl -> pid == task_pid (current )) {
19461959 subdevice = kctl -> preferred_subdevice [type ];
19471960 if (subdevice != -1 )
19481961 break ;
19491962 }
19501963 }
1951- read_unlock (& card -> ctl_files_rwlock );
1964+ read_unlock_irqrestore (& card -> ctl_files_rwlock , flags );
19521965 return subdevice ;
19531966}
19541967EXPORT_SYMBOL_GPL (snd_ctl_get_preferred_subdevice );
@@ -1997,13 +2010,14 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
19972010{
19982011 struct snd_card * card = device -> device_data ;
19992012 struct snd_ctl_file * ctl ;
2013+ unsigned long flags ;
20002014
2001- read_lock (& card -> ctl_files_rwlock );
2015+ read_lock_irqsave (& card -> ctl_files_rwlock , flags );
20022016 list_for_each_entry (ctl , & card -> ctl_files , list ) {
20032017 wake_up (& ctl -> change_sleep );
20042018 kill_fasync (& ctl -> fasync , SIGIO , POLL_ERR );
20052019 }
2006- read_unlock (& card -> ctl_files_rwlock );
2020+ read_unlock_irqrestore (& card -> ctl_files_rwlock , flags );
20072021
20082022 return snd_unregister_device (& card -> ctl_dev );
20092023}
0 commit comments