Skip to content

Commit 3fbfd22

Browse files
author
Al Viro
committed
comedi: get rid of compat_alloc_user_space() mess in COMEDI_CHANINFO compat
Just take copy_from_user() out of do_chaninfo_ioctl() into the caller and have compat_chaninfo() build a native version and pass it to do_chaninfo_ioctl() directly. Signed-off-by: Al Viro <[email protected]>
1 parent 5c6a874 commit 3fbfd22

File tree

1 file changed

+30
-38
lines changed

1 file changed

+30
-38
lines changed

drivers/staging/comedi/comedi_fops.c

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,41 +1049,38 @@ static int do_subdinfo_ioctl(struct comedi_device *dev,
10491049
* array of range table lengths to chaninfo->range_table_list if requested
10501050
*/
10511051
static int do_chaninfo_ioctl(struct comedi_device *dev,
1052-
struct comedi_chaninfo __user *arg)
1052+
struct comedi_chaninfo *it)
10531053
{
10541054
struct comedi_subdevice *s;
1055-
struct comedi_chaninfo it;
10561055

10571056
lockdep_assert_held(&dev->mutex);
1058-
if (copy_from_user(&it, arg, sizeof(it)))
1059-
return -EFAULT;
10601057

1061-
if (it.subdev >= dev->n_subdevices)
1058+
if (it->subdev >= dev->n_subdevices)
10621059
return -EINVAL;
1063-
s = &dev->subdevices[it.subdev];
1060+
s = &dev->subdevices[it->subdev];
10641061

1065-
if (it.maxdata_list) {
1062+
if (it->maxdata_list) {
10661063
if (s->maxdata || !s->maxdata_list)
10671064
return -EINVAL;
1068-
if (copy_to_user(it.maxdata_list, s->maxdata_list,
1065+
if (copy_to_user(it->maxdata_list, s->maxdata_list,
10691066
s->n_chan * sizeof(unsigned int)))
10701067
return -EFAULT;
10711068
}
10721069

1073-
if (it.flaglist)
1070+
if (it->flaglist)
10741071
return -EINVAL; /* flaglist not supported */
10751072

1076-
if (it.rangelist) {
1073+
if (it->rangelist) {
10771074
int i;
10781075

10791076
if (!s->range_table_list)
10801077
return -EINVAL;
10811078
for (i = 0; i < s->n_chan; i++) {
10821079
int x;
10831080

1084-
x = (dev->minor << 28) | (it.subdev << 24) | (i << 16) |
1081+
x = (dev->minor << 28) | (it->subdev << 24) | (i << 16) |
10851082
(s->range_table_list[i]->length);
1086-
if (put_user(x, it.rangelist + i))
1083+
if (put_user(x, it->rangelist + i))
10871084
return -EFAULT;
10881085
}
10891086
}
@@ -2205,9 +2202,14 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
22052202
(struct comedi_subdinfo __user *)arg,
22062203
file);
22072204
break;
2208-
case COMEDI_CHANINFO:
2209-
rc = do_chaninfo_ioctl(dev, (void __user *)arg);
2205+
case COMEDI_CHANINFO: {
2206+
struct comedi_chaninfo it;
2207+
if (copy_from_user(&it, (void __user *)arg, sizeof(it)))
2208+
rc = -EFAULT;
2209+
else
2210+
rc = do_chaninfo_ioctl(dev, &it);
22102211
break;
2212+
}
22112213
case COMEDI_RANGEINFO:
22122214
rc = do_rangeinfo_ioctl(dev, (void __user *)arg);
22132215
break;
@@ -2874,35 +2876,25 @@ struct comedi32_insnlist_struct {
28742876
/* Handle 32-bit COMEDI_CHANINFO ioctl. */
28752877
static int compat_chaninfo(struct file *file, unsigned long arg)
28762878
{
2877-
struct comedi_chaninfo __user *chaninfo;
2878-
struct comedi32_chaninfo_struct __user *chaninfo32;
2879+
struct comedi_file *cfp = file->private_data;
2880+
struct comedi_device *dev = cfp->dev;
2881+
struct comedi32_chaninfo_struct chaninfo32;
2882+
struct comedi_chaninfo chaninfo;
28792883
int err;
2880-
union {
2881-
unsigned int uint;
2882-
compat_uptr_t uptr;
2883-
} temp;
28842884

2885-
chaninfo32 = compat_ptr(arg);
2886-
chaninfo = compat_alloc_user_space(sizeof(*chaninfo));
2887-
2888-
/* Copy chaninfo structure. Ignore unused members. */
2889-
if (!access_ok(chaninfo32, sizeof(*chaninfo32)) ||
2890-
!access_ok(chaninfo, sizeof(*chaninfo)))
2885+
if (copy_from_user(&chaninfo32, compat_ptr(arg), sizeof(chaninfo32)))
28912886
return -EFAULT;
28922887

2893-
err = 0;
2894-
err |= __get_user(temp.uint, &chaninfo32->subdev);
2895-
err |= __put_user(temp.uint, &chaninfo->subdev);
2896-
err |= __get_user(temp.uptr, &chaninfo32->maxdata_list);
2897-
err |= __put_user(compat_ptr(temp.uptr), &chaninfo->maxdata_list);
2898-
err |= __get_user(temp.uptr, &chaninfo32->flaglist);
2899-
err |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist);
2900-
err |= __get_user(temp.uptr, &chaninfo32->rangelist);
2901-
err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist);
2902-
if (err)
2903-
return -EFAULT;
2888+
memset(&chaninfo, 0, sizeof(chaninfo));
2889+
chaninfo.subdev = chaninfo32.subdev;
2890+
chaninfo.maxdata_list = compat_ptr(chaninfo32.maxdata_list);
2891+
chaninfo.flaglist = compat_ptr(chaninfo32.flaglist);
2892+
chaninfo.rangelist = compat_ptr(chaninfo32.rangelist);
29042893

2905-
return comedi_unlocked_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo);
2894+
mutex_lock(&dev->mutex);
2895+
err = do_chaninfo_ioctl(dev, &chaninfo);
2896+
mutex_unlock(&dev->mutex);
2897+
return err;
29062898
}
29072899

29082900
/* Handle 32-bit COMEDI_RANGEINFO ioctl. */

0 commit comments

Comments
 (0)