Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f604529d authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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
parents 124e39b3 18dd0aa5
Loading
Loading
Loading
Loading
+17 −17
Original line number Original line Diff line number Diff line
@@ -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);
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
 * @file: active control handle
 * @id: the control id to remove
 * @id: the control id to remove
 *
 *
@@ -423,7 +423,7 @@ EXPORT_SYMBOL(snd_ctl_remove_id);
 * 
 * 
 * Returns 0 if successful, or a negative error code on failure.
 * Returns 0 if successful, or a negative error code on failure.
 */
 */
static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file,
static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
				   struct snd_ctl_elem_id *id)
				   struct snd_ctl_elem_id *id)
{
{
	struct snd_card *card = file->card;
	struct snd_card *card = file->card;
@@ -433,15 +433,23 @@ static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file,
	down_write(&card->controls_rwsem);
	down_write(&card->controls_rwsem);
	kctl = snd_ctl_find_id(card, id);
	kctl = snd_ctl_find_id(card, id);
	if (kctl == NULL) {
	if (kctl == NULL) {
		up_write(&card->controls_rwsem);
		ret = -ENOENT;
		return -ENOENT;
		goto error;
	}
	if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) {
		ret = -EINVAL;
		goto error;
	}
	}
	for (idx = 0; idx < kctl->count; idx++)
	for (idx = 0; idx < kctl->count; idx++)
		if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) {
		if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) {
			up_write(&card->controls_rwsem);
			ret = -EBUSY;
			return -EBUSY;
			goto error;
		}
		}
	ret = snd_ctl_remove(card, kctl);
	ret = snd_ctl_remove(card, kctl);
	if (ret < 0)
		goto error;
	card->user_ctl_count--;
error:
	up_write(&card->controls_rwsem);
	up_write(&card->controls_rwsem);
	return ret;
	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)
	if (card->user_ctl_count >= MAX_USER_CONTROLS)
		return -ENOMEM;
		return -ENOMEM;
	if (info->count > 1024)
	if (info->count < 1)
		return -EINVAL;
		return -EINVAL;
	access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
	access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
		(info->access & (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 __user *_id)
{
{
	struct snd_ctl_elem_id id;
	struct snd_ctl_elem_id id;
	int err;


	if (copy_from_user(&id, _id, sizeof(id)))
	if (copy_from_user(&id, _id, sizeof(id)))
		return -EFAULT;
		return -EFAULT;
	err = snd_ctl_remove_unlocked_id(file, &id);
	return snd_ctl_remove_user_ctl(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;
}
}


static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)