diff options
| author | Takashi Iwai <tiwai@suse.de> | 2009-09-10 09:32:47 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2009-09-10 09:32:47 -0400 |
| commit | f604529d0c1c24be025f47b591366e257ee75f66 (patch) | |
| tree | 22f09696a541cb561e33e352e47259ff492261a6 | |
| parent | 124e39b34d9b38cde4cac02077d5b58f6c1f063e (diff) | |
| parent | 18dd0aa5afea7dc33953aa87de696e39074bbf78 (diff) | |
Merge branch 'topic/ctl-add-remove-fixes' into for-linus
* topic/ctl-add-remove-fixes:
sound: snd_ctl_remove_user_ctl: prevent removal of kernel controls
sound: snd_ctl_remove_unlocked_id: simplify user control counting
sound: snd_ctl_remove_unlocked_id: simplify error paths
sound: snd_ctl_elem_add: fix value count check
| -rw-r--r-- | sound/core/control.c | 34 |
1 files changed, 17 insertions, 17 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index 17b8d47a5cd0..a8b7fabe645e 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
| @@ -414,7 +414,7 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) | |||
| 414 | EXPORT_SYMBOL(snd_ctl_remove_id); | 414 | EXPORT_SYMBOL(snd_ctl_remove_id); |
| 415 | 415 | ||
| 416 | /** | 416 | /** |
| 417 | * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it | 417 | * snd_ctl_remove_user_ctl - remove and release the unlocked user control |
| 418 | * @file: active control handle | 418 | * @file: active control handle |
| 419 | * @id: the control id to remove | 419 | * @id: the control id to remove |
| 420 | * | 420 | * |
| @@ -423,8 +423,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id); | |||
| 423 | * | 423 | * |
| 424 | * Returns 0 if successful, or a negative error code on failure. | 424 | * Returns 0 if successful, or a negative error code on failure. |
| 425 | */ | 425 | */ |
| 426 | static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, | 426 | static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, |
| 427 | struct snd_ctl_elem_id *id) | 427 | struct snd_ctl_elem_id *id) |
| 428 | { | 428 | { |
| 429 | struct snd_card *card = file->card; | 429 | struct snd_card *card = file->card; |
| 430 | struct snd_kcontrol *kctl; | 430 | struct snd_kcontrol *kctl; |
| @@ -433,15 +433,23 @@ static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, | |||
| 433 | down_write(&card->controls_rwsem); | 433 | down_write(&card->controls_rwsem); |
| 434 | kctl = snd_ctl_find_id(card, id); | 434 | kctl = snd_ctl_find_id(card, id); |
| 435 | if (kctl == NULL) { | 435 | if (kctl == NULL) { |
| 436 | up_write(&card->controls_rwsem); | 436 | ret = -ENOENT; |
| 437 | return -ENOENT; | 437 | goto error; |
| 438 | } | ||
| 439 | if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) { | ||
| 440 | ret = -EINVAL; | ||
| 441 | goto error; | ||
| 438 | } | 442 | } |
| 439 | for (idx = 0; idx < kctl->count; idx++) | 443 | for (idx = 0; idx < kctl->count; idx++) |
| 440 | if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { | 444 | if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { |
| 441 | up_write(&card->controls_rwsem); | 445 | ret = -EBUSY; |
| 442 | return -EBUSY; | 446 | goto error; |
| 443 | } | 447 | } |
| 444 | ret = snd_ctl_remove(card, kctl); | 448 | ret = snd_ctl_remove(card, kctl); |
| 449 | if (ret < 0) | ||
| 450 | goto error; | ||
| 451 | card->user_ctl_count--; | ||
| 452 | error: | ||
| 445 | up_write(&card->controls_rwsem); | 453 | up_write(&card->controls_rwsem); |
| 446 | return ret; | 454 | return ret; |
| 447 | } | 455 | } |
| @@ -951,7 +959,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, | |||
| 951 | 959 | ||
| 952 | if (card->user_ctl_count >= MAX_USER_CONTROLS) | 960 | if (card->user_ctl_count >= MAX_USER_CONTROLS) |
| 953 | return -ENOMEM; | 961 | return -ENOMEM; |
| 954 | if (info->count > 1024) | 962 | if (info->count < 1) |
| 955 | return -EINVAL; | 963 | return -EINVAL; |
| 956 | access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : | 964 | access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : |
| 957 | (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| | 965 | (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| |
| @@ -1052,18 +1060,10 @@ static int snd_ctl_elem_remove(struct snd_ctl_file *file, | |||
| 1052 | struct snd_ctl_elem_id __user *_id) | 1060 | struct snd_ctl_elem_id __user *_id) |
| 1053 | { | 1061 | { |
| 1054 | struct snd_ctl_elem_id id; | 1062 | struct snd_ctl_elem_id id; |
| 1055 | int err; | ||
| 1056 | 1063 | ||
| 1057 | if (copy_from_user(&id, _id, sizeof(id))) | 1064 | if (copy_from_user(&id, _id, sizeof(id))) |
| 1058 | return -EFAULT; | 1065 | return -EFAULT; |
| 1059 | err = snd_ctl_remove_unlocked_id(file, &id); | 1066 | return snd_ctl_remove_user_ctl(file, &id); |
| 1060 | if (! err) { | ||
| 1061 | struct snd_card *card = file->card; | ||
| 1062 | down_write(&card->controls_rwsem); | ||
| 1063 | card->user_ctl_count--; | ||
| 1064 | up_write(&card->controls_rwsem); | ||
| 1065 | } | ||
| 1066 | return err; | ||
| 1067 | } | 1067 | } |
| 1068 | 1068 | ||
| 1069 | static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) | 1069 | static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) |
