[alsa-devel] [PATCH 07/24] ALSA: ctl: add a helper function to allocate for ELEM_LIST request

Takashi Sakamoto o-takashi at sakamocchi.jp
Sat Nov 25 10:19:49 CET 2017


When investigating compatibility layer, several functions for native ABI
are called by the layer. A 'snd_ctl_elem_list()' is such a function,
while it cannot receive a second argument for data on kernel space. This
will bring a future inconvenience in integration of the layer.

This commit adds a helper function to allocate memory object on kernel
space for the argument.

Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
 sound/core/control.c        | 41 ++++++++++++++++++++++++++++-------------
 sound/core/control_compat.c |  2 +-
 2 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/sound/core/control.c b/sound/core/control.c
index 8baee922a400..ad4d27c681c4 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -745,22 +745,19 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
 }
 
 static int snd_ctl_elem_list(struct snd_ctl_file *ctl_file,
-			     struct snd_ctl_elem_list __user *_list)
+			     struct snd_ctl_elem_list *list)
 {
-	struct snd_ctl_elem_list list;
 	struct snd_kcontrol *kctl;
 	struct snd_ctl_elem_id id;
 	unsigned int offset, space, jidx;
 	int err = 0;
 	
-	if (copy_from_user(&list, _list, sizeof(list)))
-		return -EFAULT;
-	offset = list.offset;
-	space = list.space;
+	offset = list->offset;
+	space = list->space;
 
 	down_read(&ctl_file->card->controls_rwsem);
-	list.count = ctl_file->card->controls_count;
-	list.used = 0;
+	list->count = ctl_file->card->controls_count;
+	list->used = 0;
 	if (space > 0) {
 		list_for_each_entry(kctl, &ctl_file->card->controls, list) {
 			if (offset >= kctl->count) {
@@ -769,12 +766,12 @@ static int snd_ctl_elem_list(struct snd_ctl_file *ctl_file,
 			}
 			for (jidx = offset; jidx < kctl->count; jidx++) {
 				snd_ctl_build_ioff(&id, kctl, jidx);
-				if (copy_to_user(list.pids + list.used, &id,
+				if (copy_to_user(list->pids + list->used, &id,
 						 sizeof(id))) {
 					err = -EFAULT;
 					goto out;
 				}
-				list.used++;
+				list->used++;
 				if (!--space)
 					goto out;
 			}
@@ -783,8 +780,26 @@ static int snd_ctl_elem_list(struct snd_ctl_file *ctl_file,
 	}
  out:
 	up_read(&ctl_file->card->controls_rwsem);
-	if (!err && copy_to_user(_list, &list, sizeof(list)))
-		err = -EFAULT;
+	return err;
+}
+
+static int snd_ctl_elem_list_user(struct snd_ctl_file *ctl_file,
+				  void __user *arg)
+{
+	struct snd_ctl_elem_list *list;
+	int err;
+
+	list = memdup_user(arg, sizeof(*list));
+	if (IS_ERR(list))
+		return PTR_ERR(list);
+
+	err = snd_ctl_elem_list(ctl_file, list);
+	if (err >= 0) {
+		if (copy_to_user(arg, list, sizeof(*list)))
+			err = -EFAULT;
+	}
+
+	kfree(list);
 	return err;
 }
 
@@ -1552,7 +1567,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
 	case SNDRV_CTL_IOCTL_CARD_INFO:
 		return snd_ctl_card_info(card, ctl, cmd, argp);
 	case SNDRV_CTL_IOCTL_ELEM_LIST:
-		return snd_ctl_elem_list(ctl, argp);
+		return snd_ctl_elem_list_user(ctl, argp);
 	case SNDRV_CTL_IOCTL_ELEM_INFO:
 		return snd_ctl_elem_info_user(ctl, argp);
 	case SNDRV_CTL_IOCTL_ELEM_READ:
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 3594bd41750e..8a4c58c0cf3b 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -422,7 +422,7 @@ static int snd_ctl_elem_list_compat(struct snd_ctl_file *ctl_file,
 	if (get_user(ptr, &data32->pids) ||
 	    put_user(compat_ptr(ptr), &data->pids))
 		return -EFAULT;
-	err = snd_ctl_elem_list(ctl_file, data);
+	err = snd_ctl_elem_list_user(ctl_file, data);
 	if (err < 0)
 		return err;
 	/* copy the result */
-- 
2.14.1



More information about the Alsa-devel mailing list