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

ALSA: control: Fix power_ref lock order for compat code, too

In the previous change for swapping the power_ref and controls_rwsem
lock order, the code path for the compat layer was forgotten.
This patch covers the remaining code.

Fixes: fcc62b19 ("ALSA: control: Take power_ref lock primarily")
Link: https://patch.msgid.link/20240808163128.20383-1-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent c37f7cd7
Loading
Loading
Loading
Loading
+37 −8
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ struct snd_ctl_elem_info32 {
static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
				    struct snd_ctl_elem_info32 __user *data32)
{
	struct snd_card *card = ctl->card;
	struct snd_ctl_elem_info *data __free(kfree) = NULL;
	int err;

@@ -95,7 +96,11 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
	if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
		return -EFAULT;

	err = snd_power_ref_and_wait(card);
	if (err < 0)
		return err;
	err = snd_ctl_elem_info(ctl, data);
	snd_power_unref(card);
	if (err < 0)
		return err;
	/* restore info to 32bit */
@@ -175,10 +180,7 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
	if (info == NULL)
		return -ENOMEM;
	info->id = *id;
	err = snd_power_ref_and_wait(card);
	if (!err)
	err = kctl->info(kctl, info);
	snd_power_unref(card);
	if (err >= 0) {
		err = info->type;
		*countp = info->count;
@@ -275,7 +277,7 @@ static int copy_ctl_value_to_user(void __user *userdata,
	return 0;
}

static int ctl_elem_read_user(struct snd_card *card,
static int __ctl_elem_read_user(struct snd_card *card,
				void __user *userdata, void __user *valuep)
{
	struct snd_ctl_elem_value *data __free(kfree) = NULL;
@@ -296,7 +298,20 @@ static int ctl_elem_read_user(struct snd_card *card,
	return copy_ctl_value_to_user(userdata, valuep, data, type, count);
}

static int ctl_elem_write_user(struct snd_ctl_file *file,
static int ctl_elem_read_user(struct snd_card *card,
			      void __user *userdata, void __user *valuep)
{
	int err;

	err = snd_power_ref_and_wait(card);
	if (err < 0)
		return err;
	err = __ctl_elem_read_user(card, userdata, valuep);
	snd_power_unref(card);
	return err;
}

static int __ctl_elem_write_user(struct snd_ctl_file *file,
				 void __user *userdata, void __user *valuep)
{
	struct snd_ctl_elem_value *data __free(kfree) = NULL;
@@ -318,6 +333,20 @@ static int ctl_elem_write_user(struct snd_ctl_file *file,
	return copy_ctl_value_to_user(userdata, valuep, data, type, count);
}

static int ctl_elem_write_user(struct snd_ctl_file *file,
			       void __user *userdata, void __user *valuep)
{
	struct snd_card *card = file->card;
	int err;

	err = snd_power_ref_and_wait(card);
	if (err < 0)
		return err;
	err = __ctl_elem_write_user(file, userdata, valuep);
	snd_power_unref(card);
	return err;
}

static int snd_ctl_elem_read_user_compat(struct snd_card *card,
					 struct snd_ctl_elem_value32 __user *data32)
{