Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ALSA: compat_ioctl: avoid compat_alloc_user_space

Using compat_alloc_user_space() tends to add complexity
to the ioctl handling, so I am trying to remove it everywhere.

The two callers in sound/core can rewritten to just call
the same code that operates on a kernel pointer as the
native handler.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20200918095642.1446243-1-arnd@arndb.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Arnd Bergmann and committed by
Takashi Iwai
18d122c0 2b987515

+56 -48
+25 -13
sound/core/control.c
··· 717 717 } 718 718 719 719 static int snd_ctl_elem_list(struct snd_card *card, 720 - struct snd_ctl_elem_list __user *_list) 720 + struct snd_ctl_elem_list *list) 721 721 { 722 - struct snd_ctl_elem_list list; 723 722 struct snd_kcontrol *kctl; 724 723 struct snd_ctl_elem_id id; 725 724 unsigned int offset, space, jidx; 726 725 int err = 0; 727 726 728 - if (copy_from_user(&list, _list, sizeof(list))) 729 - return -EFAULT; 730 - offset = list.offset; 731 - space = list.space; 727 + offset = list->offset; 728 + space = list->space; 732 729 733 730 down_read(&card->controls_rwsem); 734 - list.count = card->controls_count; 735 - list.used = 0; 731 + list->count = card->controls_count; 732 + list->used = 0; 736 733 if (space > 0) { 737 734 list_for_each_entry(kctl, &card->controls, list) { 738 735 if (offset >= kctl->count) { ··· 738 741 } 739 742 for (jidx = offset; jidx < kctl->count; jidx++) { 740 743 snd_ctl_build_ioff(&id, kctl, jidx); 741 - if (copy_to_user(list.pids + list.used, &id, 744 + if (copy_to_user(list->pids + list->used, &id, 742 745 sizeof(id))) { 743 746 err = -EFAULT; 744 747 goto out; 745 748 } 746 - list.used++; 749 + list->used++; 747 750 if (!--space) 748 751 goto out; 749 752 } ··· 752 755 } 753 756 out: 754 757 up_read(&card->controls_rwsem); 755 - if (!err && copy_to_user(_list, &list, sizeof(list))) 756 - err = -EFAULT; 757 758 return err; 759 + } 760 + 761 + static int snd_ctl_elem_list_user(struct snd_card *card, 762 + struct snd_ctl_elem_list __user *_list) 763 + { 764 + struct snd_ctl_elem_list list; 765 + int err; 766 + 767 + if (copy_from_user(&list, _list, sizeof(list))) 768 + return -EFAULT; 769 + err = snd_ctl_elem_list(card, &list); 770 + if (err) 771 + return err; 772 + if (copy_to_user(_list, &list, sizeof(list))) 773 + return -EFAULT; 774 + 775 + return 0; 758 776 } 759 777 760 778 /* Check whether the given kctl info is valid */ ··· 1715 1703 case SNDRV_CTL_IOCTL_CARD_INFO: 1716 1704 return snd_ctl_card_info(card, ctl, cmd, argp); 1717 1705 case SNDRV_CTL_IOCTL_ELEM_LIST: 1718 - return snd_ctl_elem_list(card, argp); 1706 + return snd_ctl_elem_list_user(card, argp); 1719 1707 case SNDRV_CTL_IOCTL_ELEM_INFO: 1720 1708 return snd_ctl_elem_info_user(ctl, argp); 1721 1709 case SNDRV_CTL_IOCTL_ELEM_READ:
+6 -8
sound/core/control_compat.c
··· 22 22 static int snd_ctl_elem_list_compat(struct snd_card *card, 23 23 struct snd_ctl_elem_list32 __user *data32) 24 24 { 25 - struct snd_ctl_elem_list __user *data; 25 + struct snd_ctl_elem_list data = {}; 26 26 compat_caddr_t ptr; 27 27 int err; 28 28 29 - data = compat_alloc_user_space(sizeof(*data)); 30 - 31 29 /* offset, space, used, count */ 32 - if (copy_in_user(data, data32, 4 * sizeof(u32))) 30 + if (copy_from_user(&data, data32, 4 * sizeof(u32))) 33 31 return -EFAULT; 34 32 /* pids */ 35 - if (get_user(ptr, &data32->pids) || 36 - put_user(compat_ptr(ptr), &data->pids)) 33 + if (get_user(ptr, &data32->pids)) 37 34 return -EFAULT; 38 - err = snd_ctl_elem_list(card, data); 35 + data.pids = compat_ptr(ptr); 36 + err = snd_ctl_elem_list(card, &data); 39 37 if (err < 0) 40 38 return err; 41 39 /* copy the result */ 42 - if (copy_in_user(data32, data, 4 * sizeof(u32))) 40 + if (copy_to_user(data32, &data, 4 * sizeof(u32))) 43 41 return -EFAULT; 44 42 return 0; 45 43 }
+17 -10
sound/core/hwdep.c
··· 203 203 } 204 204 205 205 static int snd_hwdep_dsp_load(struct snd_hwdep *hw, 206 - struct snd_hwdep_dsp_image __user *_info) 206 + struct snd_hwdep_dsp_image *info) 207 207 { 208 - struct snd_hwdep_dsp_image info; 209 208 int err; 210 209 211 210 if (! hw->ops.dsp_load) 212 211 return -ENXIO; 213 - memset(&info, 0, sizeof(info)); 214 - if (copy_from_user(&info, _info, sizeof(info))) 215 - return -EFAULT; 216 - if (info.index >= 32) 212 + if (info->index >= 32) 217 213 return -EINVAL; 218 214 /* check whether the dsp was already loaded */ 219 - if (hw->dsp_loaded & (1u << info.index)) 215 + if (hw->dsp_loaded & (1u << info->index)) 220 216 return -EBUSY; 221 - err = hw->ops.dsp_load(hw, &info); 217 + err = hw->ops.dsp_load(hw, info); 222 218 if (err < 0) 223 219 return err; 224 - hw->dsp_loaded |= (1u << info.index); 220 + hw->dsp_loaded |= (1u << info->index); 225 221 return 0; 226 222 } 223 + 224 + static int snd_hwdep_dsp_load_user(struct snd_hwdep *hw, 225 + struct snd_hwdep_dsp_image __user *_info) 226 + { 227 + struct snd_hwdep_dsp_image info = {}; 228 + 229 + if (copy_from_user(&info, _info, sizeof(info))) 230 + return -EFAULT; 231 + return snd_hwdep_dsp_load(hw, &info); 232 + } 233 + 227 234 228 235 static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, 229 236 unsigned long arg) ··· 245 238 case SNDRV_HWDEP_IOCTL_DSP_STATUS: 246 239 return snd_hwdep_dsp_status(hw, argp); 247 240 case SNDRV_HWDEP_IOCTL_DSP_LOAD: 248 - return snd_hwdep_dsp_load(hw, argp); 241 + return snd_hwdep_dsp_load_user(hw, argp); 249 242 } 250 243 if (hw->ops.ioctl) 251 244 return hw->ops.ioctl(hw, file, cmd, arg);
+8 -17
sound/core/hwdep_compat.c
··· 19 19 static int snd_hwdep_dsp_load_compat(struct snd_hwdep *hw, 20 20 struct snd_hwdep_dsp_image32 __user *src) 21 21 { 22 - struct snd_hwdep_dsp_image __user *dst; 22 + struct snd_hwdep_dsp_image info = {}; 23 23 compat_caddr_t ptr; 24 - u32 val; 25 24 26 - dst = compat_alloc_user_space(sizeof(*dst)); 25 + if (copy_from_user(&info, src, 4 + 64) || 26 + get_user(ptr, &src->image) || 27 + get_user(info.length, &src->length) || 28 + get_user(info.driver_data, &src->driver_data)) 29 + return -EFAULT; 30 + info.image = compat_ptr(ptr); 27 31 28 - /* index and name */ 29 - if (copy_in_user(dst, src, 4 + 64)) 30 - return -EFAULT; 31 - if (get_user(ptr, &src->image) || 32 - put_user(compat_ptr(ptr), &dst->image)) 33 - return -EFAULT; 34 - if (get_user(val, &src->length) || 35 - put_user(val, &dst->length)) 36 - return -EFAULT; 37 - if (get_user(val, &src->driver_data) || 38 - put_user(val, &dst->driver_data)) 39 - return -EFAULT; 40 - 41 - return snd_hwdep_dsp_load(hw, dst); 32 + return snd_hwdep_dsp_load(hw, &info); 42 33 } 43 34 44 35 enum {