hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/sound/core/control.c
....@@ -1,22 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Routines for driver control interface
34 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4
- *
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program; if not, write to the Free Software
18
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
- *
205 */
216
227 #include <linux/threads.h>
....@@ -26,6 +11,7 @@
2611 #include <linux/vmalloc.h>
2712 #include <linux/time.h>
2813 #include <linux/mm.h>
14
+#include <linux/math64.h>
2915 #include <linux/sched/signal.h>
3016 #include <sound/core.h>
3117 #include <sound/minors.h>
....@@ -54,7 +40,7 @@
5440 struct snd_ctl_file *ctl;
5541 int i, err;
5642
57
- err = nonseekable_open(inode, file);
43
+ err = stream_open(inode, file);
5844 if (err < 0)
5945 return err;
6046
....@@ -164,14 +150,14 @@
164150 return;
165151 if (card->shutdown)
166152 return;
167
- read_lock(&card->ctl_files_rwlock);
153
+ read_lock_irqsave(&card->ctl_files_rwlock, flags);
168154 #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
169155 card->mixer_oss_change_count++;
170156 #endif
171157 list_for_each_entry(ctl, &card->ctl_files, list) {
172158 if (!ctl->subscribed)
173159 continue;
174
- spin_lock_irqsave(&ctl->read_lock, flags);
160
+ spin_lock(&ctl->read_lock);
175161 list_for_each_entry(ev, &ctl->events, list) {
176162 if (ev->id.numid == id->numid) {
177163 ev->mask |= mask;
....@@ -188,10 +174,10 @@
188174 }
189175 _found:
190176 wake_up(&ctl->change_sleep);
191
- spin_unlock_irqrestore(&ctl->read_lock, flags);
177
+ spin_unlock(&ctl->read_lock);
192178 kill_fasync(&ctl->fasync, SIGIO, POLL_IN);
193179 }
194
- read_unlock(&card->ctl_files_rwlock);
180
+ read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
195181 }
196182 EXPORT_SYMBOL(snd_ctl_notify);
197183
....@@ -211,16 +197,12 @@
211197 static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count,
212198 unsigned int access, struct snd_ctl_file *file)
213199 {
214
- unsigned int size;
215200 unsigned int idx;
216201
217202 if (count == 0 || count > MAX_CONTROL_COUNT)
218203 return -EINVAL;
219204
220
- size = sizeof(struct snd_kcontrol);
221
- size += sizeof(struct snd_kcontrol_volatile) * count;
222
-
223
- *kctl = kzalloc(size, GFP_KERNEL);
205
+ *kctl = kzalloc(struct_size(*kctl, vd, count), GFP_KERNEL);
224206 if (!*kctl)
225207 return -ENOMEM;
226208
....@@ -267,7 +249,8 @@
267249 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
268250 SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE |
269251 SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND |
270
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
252
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK |
253
+ SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK);
271254
272255 err = snd_ctl_new(&kctl, count, access, NULL);
273256 if (err < 0)
....@@ -348,22 +331,41 @@
348331 return 0;
349332 }
350333
351
-/* add a new kcontrol object; call with card->controls_rwsem locked */
352
-static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
334
+enum snd_ctl_add_mode {
335
+ CTL_ADD_EXCLUSIVE, CTL_REPLACE, CTL_ADD_ON_REPLACE,
336
+};
337
+
338
+/* add/replace a new kcontrol object; call with card->controls_rwsem locked */
339
+static int __snd_ctl_add_replace(struct snd_card *card,
340
+ struct snd_kcontrol *kcontrol,
341
+ enum snd_ctl_add_mode mode)
353342 {
354343 struct snd_ctl_elem_id id;
355344 unsigned int idx;
356345 unsigned int count;
346
+ struct snd_kcontrol *old;
347
+ int err;
357348
358349 id = kcontrol->id;
359350 if (id.index > UINT_MAX - kcontrol->count)
360351 return -EINVAL;
361352
362
- if (snd_ctl_find_id(card, &id)) {
363
- dev_err(card->dev,
364
- "control %i:%i:%i:%s:%i is already present\n",
365
- id.iface, id.device, id.subdevice, id.name, id.index);
366
- return -EBUSY;
353
+ old = snd_ctl_find_id(card, &id);
354
+ if (!old) {
355
+ if (mode == CTL_REPLACE)
356
+ return -EINVAL;
357
+ } else {
358
+ if (mode == CTL_ADD_EXCLUSIVE) {
359
+ dev_err(card->dev,
360
+ "control %i:%i:%i:%s:%i is already present\n",
361
+ id.iface, id.device, id.subdevice, id.name,
362
+ id.index);
363
+ return -EBUSY;
364
+ }
365
+
366
+ err = snd_ctl_remove(card, old);
367
+ if (err < 0)
368
+ return err;
367369 }
368370
369371 if (snd_ctl_find_hole(card, kcontrol->count) < 0)
....@@ -382,6 +384,29 @@
382384 return 0;
383385 }
384386
387
+static int snd_ctl_add_replace(struct snd_card *card,
388
+ struct snd_kcontrol *kcontrol,
389
+ enum snd_ctl_add_mode mode)
390
+{
391
+ int err = -EINVAL;
392
+
393
+ if (! kcontrol)
394
+ return err;
395
+ if (snd_BUG_ON(!card || !kcontrol->info))
396
+ goto error;
397
+
398
+ down_write(&card->controls_rwsem);
399
+ err = __snd_ctl_add_replace(card, kcontrol, mode);
400
+ up_write(&card->controls_rwsem);
401
+ if (err < 0)
402
+ goto error;
403
+ return 0;
404
+
405
+ error:
406
+ snd_ctl_free_one(kcontrol);
407
+ return err;
408
+}
409
+
385410 /**
386411 * snd_ctl_add - add the control instance to the card
387412 * @card: the card instance
....@@ -398,23 +423,7 @@
398423 */
399424 int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
400425 {
401
- int err = -EINVAL;
402
-
403
- if (! kcontrol)
404
- return err;
405
- if (snd_BUG_ON(!card || !kcontrol->info))
406
- goto error;
407
-
408
- down_write(&card->controls_rwsem);
409
- err = __snd_ctl_add(card, kcontrol);
410
- up_write(&card->controls_rwsem);
411
- if (err < 0)
412
- goto error;
413
- return 0;
414
-
415
- error:
416
- snd_ctl_free_one(kcontrol);
417
- return err;
426
+ return snd_ctl_add_replace(card, kcontrol, CTL_ADD_EXCLUSIVE);
418427 }
419428 EXPORT_SYMBOL(snd_ctl_add);
420429
....@@ -435,53 +444,8 @@
435444 int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
436445 bool add_on_replace)
437446 {
438
- struct snd_ctl_elem_id id;
439
- unsigned int count;
440
- unsigned int idx;
441
- struct snd_kcontrol *old;
442
- int ret;
443
-
444
- if (!kcontrol)
445
- return -EINVAL;
446
- if (snd_BUG_ON(!card || !kcontrol->info)) {
447
- ret = -EINVAL;
448
- goto error;
449
- }
450
- id = kcontrol->id;
451
- down_write(&card->controls_rwsem);
452
- old = snd_ctl_find_id(card, &id);
453
- if (!old) {
454
- if (add_on_replace)
455
- goto add;
456
- up_write(&card->controls_rwsem);
457
- ret = -EINVAL;
458
- goto error;
459
- }
460
- ret = snd_ctl_remove(card, old);
461
- if (ret < 0) {
462
- up_write(&card->controls_rwsem);
463
- goto error;
464
- }
465
-add:
466
- if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
467
- up_write(&card->controls_rwsem);
468
- ret = -ENOMEM;
469
- goto error;
470
- }
471
- list_add_tail(&kcontrol->list, &card->controls);
472
- card->controls_count += kcontrol->count;
473
- kcontrol->id.numid = card->last_numid + 1;
474
- card->last_numid += kcontrol->count;
475
- id = kcontrol->id;
476
- count = kcontrol->count;
477
- up_write(&card->controls_rwsem);
478
- for (idx = 0; idx < count; idx++, id.index++, id.numid++)
479
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
480
- return 0;
481
-
482
-error:
483
- snd_ctl_free_one(kcontrol);
484
- return ret;
447
+ return snd_ctl_add_replace(card, kcontrol,
448
+ add_on_replace ? CTL_ADD_ON_REPLACE : CTL_REPLACE);
485449 }
486450 EXPORT_SYMBOL(snd_ctl_replace);
487451
....@@ -753,22 +717,19 @@
753717 }
754718
755719 static int snd_ctl_elem_list(struct snd_card *card,
756
- struct snd_ctl_elem_list __user *_list)
720
+ struct snd_ctl_elem_list *list)
757721 {
758
- struct snd_ctl_elem_list list;
759722 struct snd_kcontrol *kctl;
760723 struct snd_ctl_elem_id id;
761724 unsigned int offset, space, jidx;
762725 int err = 0;
763726
764
- if (copy_from_user(&list, _list, sizeof(list)))
765
- return -EFAULT;
766
- offset = list.offset;
767
- space = list.space;
727
+ offset = list->offset;
728
+ space = list->space;
768729
769730 down_read(&card->controls_rwsem);
770
- list.count = card->controls_count;
771
- list.used = 0;
731
+ list->count = card->controls_count;
732
+ list->used = 0;
772733 if (space > 0) {
773734 list_for_each_entry(kctl, &card->controls, list) {
774735 if (offset >= kctl->count) {
....@@ -777,12 +738,12 @@
777738 }
778739 for (jidx = offset; jidx < kctl->count; jidx++) {
779740 snd_ctl_build_ioff(&id, kctl, jidx);
780
- if (copy_to_user(list.pids + list.used, &id,
741
+ if (copy_to_user(list->pids + list->used, &id,
781742 sizeof(id))) {
782743 err = -EFAULT;
783744 goto out;
784745 }
785
- list.used++;
746
+ list->used++;
786747 if (!--space)
787748 goto out;
788749 }
....@@ -791,56 +752,219 @@
791752 }
792753 out:
793754 up_read(&card->controls_rwsem);
794
- if (!err && copy_to_user(_list, &list, sizeof(list)))
795
- err = -EFAULT;
796755 return err;
797756 }
798757
799
-static bool validate_element_member_dimension(struct snd_ctl_elem_info *info)
758
+static int snd_ctl_elem_list_user(struct snd_card *card,
759
+ struct snd_ctl_elem_list __user *_list)
800760 {
801
- unsigned int members;
802
- unsigned int i;
761
+ struct snd_ctl_elem_list list;
762
+ int err;
803763
804
- if (info->dimen.d[0] == 0)
805
- return true;
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;
806771
807
- members = 1;
808
- for (i = 0; i < ARRAY_SIZE(info->dimen.d); ++i) {
809
- if (info->dimen.d[i] == 0)
810
- break;
811
- members *= info->dimen.d[i];
812
-
813
- /*
814
- * info->count should be validated in advance, to guarantee
815
- * calculation soundness.
816
- */
817
- if (members > info->count)
818
- return false;
819
- }
820
-
821
- for (++i; i < ARRAY_SIZE(info->dimen.d); ++i) {
822
- if (info->dimen.d[i] > 0)
823
- return false;
824
- }
825
-
826
- return members == info->count;
772
+ return 0;
827773 }
828774
829
-static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
830
- struct snd_ctl_elem_info *info)
775
+/* Check whether the given kctl info is valid */
776
+static int snd_ctl_check_elem_info(struct snd_card *card,
777
+ const struct snd_ctl_elem_info *info)
831778 {
832
- struct snd_card *card = ctl->card;
833
- struct snd_kcontrol *kctl;
779
+ static const unsigned int max_value_counts[] = {
780
+ [SNDRV_CTL_ELEM_TYPE_BOOLEAN] = 128,
781
+ [SNDRV_CTL_ELEM_TYPE_INTEGER] = 128,
782
+ [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = 128,
783
+ [SNDRV_CTL_ELEM_TYPE_BYTES] = 512,
784
+ [SNDRV_CTL_ELEM_TYPE_IEC958] = 1,
785
+ [SNDRV_CTL_ELEM_TYPE_INTEGER64] = 64,
786
+ };
787
+
788
+ if (info->type < SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
789
+ info->type > SNDRV_CTL_ELEM_TYPE_INTEGER64) {
790
+ if (card)
791
+ dev_err(card->dev,
792
+ "control %i:%i:%i:%s:%i: invalid type %d\n",
793
+ info->id.iface, info->id.device,
794
+ info->id.subdevice, info->id.name,
795
+ info->id.index, info->type);
796
+ return -EINVAL;
797
+ }
798
+ if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
799
+ info->value.enumerated.items == 0) {
800
+ if (card)
801
+ dev_err(card->dev,
802
+ "control %i:%i:%i:%s:%i: zero enum items\n",
803
+ info->id.iface, info->id.device,
804
+ info->id.subdevice, info->id.name,
805
+ info->id.index);
806
+ return -EINVAL;
807
+ }
808
+ if (info->count > max_value_counts[info->type]) {
809
+ if (card)
810
+ dev_err(card->dev,
811
+ "control %i:%i:%i:%s:%i: invalid count %d\n",
812
+ info->id.iface, info->id.device,
813
+ info->id.subdevice, info->id.name,
814
+ info->id.index, info->count);
815
+ return -EINVAL;
816
+ }
817
+
818
+ return 0;
819
+}
820
+
821
+/* The capacity of struct snd_ctl_elem_value.value.*/
822
+static const unsigned int value_sizes[] = {
823
+ [SNDRV_CTL_ELEM_TYPE_BOOLEAN] = sizeof(long),
824
+ [SNDRV_CTL_ELEM_TYPE_INTEGER] = sizeof(long),
825
+ [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = sizeof(unsigned int),
826
+ [SNDRV_CTL_ELEM_TYPE_BYTES] = sizeof(unsigned char),
827
+ [SNDRV_CTL_ELEM_TYPE_IEC958] = sizeof(struct snd_aes_iec958),
828
+ [SNDRV_CTL_ELEM_TYPE_INTEGER64] = sizeof(long long),
829
+};
830
+
831
+#ifdef CONFIG_SND_CTL_VALIDATION
832
+/* fill the remaining snd_ctl_elem_value data with the given pattern */
833
+static void fill_remaining_elem_value(struct snd_ctl_elem_value *control,
834
+ struct snd_ctl_elem_info *info,
835
+ u32 pattern)
836
+{
837
+ size_t offset = value_sizes[info->type] * info->count;
838
+
839
+ offset = (offset + sizeof(u32) - 1) / sizeof(u32);
840
+ memset32((u32 *)control->value.bytes.data + offset, pattern,
841
+ sizeof(control->value) / sizeof(u32) - offset);
842
+}
843
+
844
+/* check whether the given integer ctl value is valid */
845
+static int sanity_check_int_value(struct snd_card *card,
846
+ const struct snd_ctl_elem_value *control,
847
+ const struct snd_ctl_elem_info *info,
848
+ int i)
849
+{
850
+ long long lval, lmin, lmax, lstep;
851
+ u64 rem;
852
+
853
+ switch (info->type) {
854
+ default:
855
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
856
+ lval = control->value.integer.value[i];
857
+ lmin = 0;
858
+ lmax = 1;
859
+ lstep = 0;
860
+ break;
861
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
862
+ lval = control->value.integer.value[i];
863
+ lmin = info->value.integer.min;
864
+ lmax = info->value.integer.max;
865
+ lstep = info->value.integer.step;
866
+ break;
867
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
868
+ lval = control->value.integer64.value[i];
869
+ lmin = info->value.integer64.min;
870
+ lmax = info->value.integer64.max;
871
+ lstep = info->value.integer64.step;
872
+ break;
873
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
874
+ lval = control->value.enumerated.item[i];
875
+ lmin = 0;
876
+ lmax = info->value.enumerated.items - 1;
877
+ lstep = 0;
878
+ break;
879
+ }
880
+
881
+ if (lval < lmin || lval > lmax) {
882
+ dev_err(card->dev,
883
+ "control %i:%i:%i:%s:%i: value out of range %lld (%lld/%lld) at count %i\n",
884
+ control->id.iface, control->id.device,
885
+ control->id.subdevice, control->id.name,
886
+ control->id.index, lval, lmin, lmax, i);
887
+ return -EINVAL;
888
+ }
889
+ if (lstep) {
890
+ div64_u64_rem(lval, lstep, &rem);
891
+ if (rem) {
892
+ dev_err(card->dev,
893
+ "control %i:%i:%i:%s:%i: unaligned value %lld (step %lld) at count %i\n",
894
+ control->id.iface, control->id.device,
895
+ control->id.subdevice, control->id.name,
896
+ control->id.index, lval, lstep, i);
897
+ return -EINVAL;
898
+ }
899
+ }
900
+
901
+ return 0;
902
+}
903
+
904
+/* perform sanity checks to the given snd_ctl_elem_value object */
905
+static int sanity_check_elem_value(struct snd_card *card,
906
+ const struct snd_ctl_elem_value *control,
907
+ const struct snd_ctl_elem_info *info,
908
+ u32 pattern)
909
+{
910
+ size_t offset;
911
+ int i, ret = 0;
912
+ u32 *p;
913
+
914
+ switch (info->type) {
915
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
916
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
917
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
918
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
919
+ for (i = 0; i < info->count; i++) {
920
+ ret = sanity_check_int_value(card, control, info, i);
921
+ if (ret < 0)
922
+ return ret;
923
+ }
924
+ break;
925
+ default:
926
+ break;
927
+ }
928
+
929
+ /* check whether the remaining area kept untouched */
930
+ offset = value_sizes[info->type] * info->count;
931
+ offset = (offset + sizeof(u32) - 1) / sizeof(u32);
932
+ p = (u32 *)control->value.bytes.data + offset;
933
+ for (; offset < sizeof(control->value) / sizeof(u32); offset++, p++) {
934
+ if (*p != pattern) {
935
+ ret = -EINVAL;
936
+ break;
937
+ }
938
+ *p = 0; /* clear the checked area */
939
+ }
940
+
941
+ return ret;
942
+}
943
+#else
944
+static inline void fill_remaining_elem_value(struct snd_ctl_elem_value *control,
945
+ struct snd_ctl_elem_info *info,
946
+ u32 pattern)
947
+{
948
+}
949
+
950
+static inline int sanity_check_elem_value(struct snd_card *card,
951
+ struct snd_ctl_elem_value *control,
952
+ struct snd_ctl_elem_info *info,
953
+ u32 pattern)
954
+{
955
+ return 0;
956
+}
957
+#endif
958
+
959
+static int __snd_ctl_elem_info(struct snd_card *card,
960
+ struct snd_kcontrol *kctl,
961
+ struct snd_ctl_elem_info *info,
962
+ struct snd_ctl_file *ctl)
963
+{
834964 struct snd_kcontrol_volatile *vd;
835965 unsigned int index_offset;
836966 int result;
837967
838
- down_read(&card->controls_rwsem);
839
- kctl = snd_ctl_find_id(card, &info->id);
840
- if (kctl == NULL) {
841
- up_read(&card->controls_rwsem);
842
- return -ENOENT;
843
- }
844968 #ifdef CONFIG_SND_DEBUG
845969 info->access = 0;
846970 #endif
....@@ -859,7 +983,26 @@
859983 } else {
860984 info->owner = -1;
861985 }
986
+ if (!snd_ctl_skip_validation(info) &&
987
+ snd_ctl_check_elem_info(card, info) < 0)
988
+ result = -EINVAL;
862989 }
990
+ return result;
991
+}
992
+
993
+static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
994
+ struct snd_ctl_elem_info *info)
995
+{
996
+ struct snd_card *card = ctl->card;
997
+ struct snd_kcontrol *kctl;
998
+ int result;
999
+
1000
+ down_read(&card->controls_rwsem);
1001
+ kctl = snd_ctl_find_id(card, &info->id);
1002
+ if (kctl == NULL)
1003
+ result = -ENOENT;
1004
+ else
1005
+ result = __snd_ctl_elem_info(card, kctl, info, ctl);
8631006 up_read(&card->controls_rwsem);
8641007 return result;
8651008 }
....@@ -878,6 +1021,8 @@
8781021 result = snd_ctl_elem_info(ctl, &info);
8791022 if (result < 0)
8801023 return result;
1024
+ /* drop internal access flags */
1025
+ info.access &= ~SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK;
8811026 if (copy_to_user(_info, &info, sizeof(info)))
8821027 return -EFAULT;
8831028 return result;
....@@ -889,6 +1034,9 @@
8891034 struct snd_kcontrol *kctl;
8901035 struct snd_kcontrol_volatile *vd;
8911036 unsigned int index_offset;
1037
+ struct snd_ctl_elem_info info;
1038
+ const u32 pattern = 0xdeadbeef;
1039
+ int ret;
8921040
8931041 kctl = snd_ctl_find_id(card, &control->id);
8941042 if (kctl == NULL)
....@@ -900,7 +1048,31 @@
9001048 return -EPERM;
9011049
9021050 snd_ctl_build_ioff(&control->id, kctl, index_offset);
903
- return kctl->get(kctl, control);
1051
+
1052
+#ifdef CONFIG_SND_CTL_VALIDATION
1053
+ /* info is needed only for validation */
1054
+ memset(&info, 0, sizeof(info));
1055
+ info.id = control->id;
1056
+ ret = __snd_ctl_elem_info(card, kctl, &info, NULL);
1057
+ if (ret < 0)
1058
+ return ret;
1059
+#endif
1060
+
1061
+ if (!snd_ctl_skip_validation(&info))
1062
+ fill_remaining_elem_value(control, &info, pattern);
1063
+ ret = kctl->get(kctl, control);
1064
+ if (ret < 0)
1065
+ return ret;
1066
+ if (!snd_ctl_skip_validation(&info) &&
1067
+ sanity_check_elem_value(card, control, &info, pattern) < 0) {
1068
+ dev_err(card->dev,
1069
+ "control %i:%i:%i:%s:%i: access overflow\n",
1070
+ control->id.iface, control->id.device,
1071
+ control->id.subdevice, control->id.name,
1072
+ control->id.index);
1073
+ return -EINVAL;
1074
+ }
1075
+ return ret;
9041076 }
9051077
9061078 static int snd_ctl_elem_read_user(struct snd_card *card,
....@@ -1241,23 +1413,6 @@
12411413 static int snd_ctl_elem_add(struct snd_ctl_file *file,
12421414 struct snd_ctl_elem_info *info, int replace)
12431415 {
1244
- /* The capacity of struct snd_ctl_elem_value.value.*/
1245
- static const unsigned int value_sizes[] = {
1246
- [SNDRV_CTL_ELEM_TYPE_BOOLEAN] = sizeof(long),
1247
- [SNDRV_CTL_ELEM_TYPE_INTEGER] = sizeof(long),
1248
- [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = sizeof(unsigned int),
1249
- [SNDRV_CTL_ELEM_TYPE_BYTES] = sizeof(unsigned char),
1250
- [SNDRV_CTL_ELEM_TYPE_IEC958] = sizeof(struct snd_aes_iec958),
1251
- [SNDRV_CTL_ELEM_TYPE_INTEGER64] = sizeof(long long),
1252
- };
1253
- static const unsigned int max_value_counts[] = {
1254
- [SNDRV_CTL_ELEM_TYPE_BOOLEAN] = 128,
1255
- [SNDRV_CTL_ELEM_TYPE_INTEGER] = 128,
1256
- [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = 128,
1257
- [SNDRV_CTL_ELEM_TYPE_BYTES] = 512,
1258
- [SNDRV_CTL_ELEM_TYPE_IEC958] = 1,
1259
- [SNDRV_CTL_ELEM_TYPE_INTEGER64] = 64,
1260
- };
12611416 struct snd_card *card = file->card;
12621417 struct snd_kcontrol *kctl;
12631418 unsigned int count;
....@@ -1309,16 +1464,12 @@
13091464 * Check information and calculate the size of data specific to
13101465 * this userspace control.
13111466 */
1312
- if (info->type < SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
1313
- info->type > SNDRV_CTL_ELEM_TYPE_INTEGER64)
1314
- return -EINVAL;
1315
- if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
1316
- info->value.enumerated.items == 0)
1317
- return -EINVAL;
1318
- if (info->count < 1 ||
1319
- info->count > max_value_counts[info->type])
1320
- return -EINVAL;
1321
- if (!validate_element_member_dimension(info))
1467
+ /* pass NULL to card for suppressing error messages */
1468
+ err = snd_ctl_check_elem_info(NULL, info);
1469
+ if (err < 0)
1470
+ return err;
1471
+ /* user-space control doesn't allow zero-size data */
1472
+ if (info->count < 1)
13221473 return -EINVAL;
13231474 private_size = value_sizes[info->type] * info->count;
13241475
....@@ -1369,7 +1520,7 @@
13691520
13701521 /* This function manage to free the instance on failure. */
13711522 down_write(&card->controls_rwsem);
1372
- err = __snd_ctl_add(card, kctl);
1523
+ err = __snd_ctl_add_replace(card, kctl, CTL_ADD_EXCLUSIVE);
13731524 if (err < 0) {
13741525 snd_ctl_free_one(kctl);
13751526 goto unlock;
....@@ -1564,7 +1715,7 @@
15641715 case SNDRV_CTL_IOCTL_CARD_INFO:
15651716 return snd_ctl_card_info(card, ctl, cmd, argp);
15661717 case SNDRV_CTL_IOCTL_ELEM_LIST:
1567
- return snd_ctl_elem_list(card, argp);
1718
+ return snd_ctl_elem_list_user(card, argp);
15681719 case SNDRV_CTL_IOCTL_ELEM_INFO:
15691720 return snd_ctl_elem_info_user(ctl, argp);
15701721 case SNDRV_CTL_IOCTL_ELEM_READ:
....@@ -1774,8 +1925,8 @@
17741925
17751926 #ifdef CONFIG_COMPAT
17761927 /**
1777
- * snd_ctl_unregister_ioctl - de-register the device-specific compat 32bit
1778
- * control-ioctls
1928
+ * snd_ctl_unregister_ioctl_compat - de-register the device-specific compat
1929
+ * 32bit control-ioctls
17791930 * @fcn: ioctl callback function to unregister
17801931 */
17811932 int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
....@@ -1800,8 +1951,9 @@
18001951 {
18011952 struct snd_ctl_file *kctl;
18021953 int subdevice = -1;
1954
+ unsigned long flags;
18031955
1804
- read_lock(&card->ctl_files_rwlock);
1956
+ read_lock_irqsave(&card->ctl_files_rwlock, flags);
18051957 list_for_each_entry(kctl, &card->ctl_files, list) {
18061958 if (kctl->pid == task_pid(current)) {
18071959 subdevice = kctl->preferred_subdevice[type];
....@@ -1809,7 +1961,7 @@
18091961 break;
18101962 }
18111963 }
1812
- read_unlock(&card->ctl_files_rwlock);
1964
+ read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
18131965 return subdevice;
18141966 }
18151967 EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice);
....@@ -1858,13 +2010,14 @@
18582010 {
18592011 struct snd_card *card = device->device_data;
18602012 struct snd_ctl_file *ctl;
2013
+ unsigned long flags;
18612014
1862
- read_lock(&card->ctl_files_rwlock);
2015
+ read_lock_irqsave(&card->ctl_files_rwlock, flags);
18632016 list_for_each_entry(ctl, &card->ctl_files, list) {
18642017 wake_up(&ctl->change_sleep);
18652018 kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
18662019 }
1867
- read_unlock(&card->ctl_files_rwlock);
2020
+ read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
18682021
18692022 return snd_unregister_device(&card->ctl_dev);
18702023 }
....@@ -1893,7 +2046,7 @@
18932046 */
18942047 int snd_ctl_create(struct snd_card *card)
18952048 {
1896
- static struct snd_device_ops ops = {
2049
+ static const struct snd_device_ops ops = {
18972050 .dev_free = snd_ctl_dev_free,
18982051 .dev_register = snd_ctl_dev_register,
18992052 .dev_disconnect = snd_ctl_dev_disconnect,