diff options
| -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)  EXPORT_SYMBOL(snd_ctl_remove_id);  /** - * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it + * snd_ctl_remove_user_ctl - remove and release the unlocked user control   * @file: active control handle   * @id: the control id to remove   * @@ -423,8 +423,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id);   *    * Returns 0 if successful, or a negative error code on failure.   */ -static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, -				      struct snd_ctl_elem_id *id) +static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, +				   struct snd_ctl_elem_id *id)  {  	struct snd_card *card = file->card;  	struct snd_kcontrol *kctl; @@ -433,15 +433,23 @@ static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file,  	down_write(&card->controls_rwsem);  	kctl = snd_ctl_find_id(card, id);  	if (kctl == NULL) { -		up_write(&card->controls_rwsem); -		return -ENOENT; +		ret = -ENOENT; +		goto error; +	} +	if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) { +		ret = -EINVAL; +		goto error;  	}  	for (idx = 0; idx < kctl->count; idx++)  		if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { -			up_write(&card->controls_rwsem); -			return -EBUSY; +			ret = -EBUSY; +			goto error;  		}  	ret = snd_ctl_remove(card, kctl); +	if (ret < 0) +		goto error; +	card->user_ctl_count--; +error:  	up_write(&card->controls_rwsem);  	return ret;  } @@ -951,7 +959,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,  	if (card->user_ctl_count >= MAX_USER_CONTROLS)  		return -ENOMEM; -	if (info->count > 1024) +	if (info->count < 1)  		return -EINVAL;  	access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :  		(info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| @@ -1052,18 +1060,10 @@ static int snd_ctl_elem_remove(struct snd_ctl_file *file,  			       struct snd_ctl_elem_id __user *_id)  {  	struct snd_ctl_elem_id id; -	int err;  	if (copy_from_user(&id, _id, sizeof(id)))  		return -EFAULT; -	err = snd_ctl_remove_unlocked_id(file, &id); -	if (! err) { -		struct snd_card *card = file->card; -		down_write(&card->controls_rwsem); -		card->user_ctl_count--; -		up_write(&card->controls_rwsem); -	} -	return err; +	return snd_ctl_remove_user_ctl(file, &id);  }  static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) | 
