Skip to content

Commit 0a3ccc7

Browse files
author
Al Viro
committed
comedi: do_cmd_ioctl(): lift copyin/copyout into the caller
Signed-off-by: Al Viro <[email protected]>
1 parent f0e4de5 commit 0a3ccc7

File tree

1 file changed

+24
-24
lines changed

1 file changed

+24
-24
lines changed

drivers/staging/comedi/comedi_fops.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,30 +1741,24 @@ static int __comedi_get_user_chanlist(struct comedi_device *dev,
17411741
* possibly modified comedi_cmd structure (when -EAGAIN returned)
17421742
*/
17431743
static int do_cmd_ioctl(struct comedi_device *dev,
1744-
struct comedi_cmd __user *arg, void *file)
1744+
struct comedi_cmd *cmd, bool *copy, void *file)
17451745
{
1746-
struct comedi_cmd cmd;
17471746
struct comedi_subdevice *s;
17481747
struct comedi_async *async;
17491748
unsigned int __user *user_chanlist;
17501749
int ret;
17511750

17521751
lockdep_assert_held(&dev->mutex);
17531752

1754-
if (copy_from_user(&cmd, arg, sizeof(cmd))) {
1755-
dev_dbg(dev->class_dev, "bad cmd address\n");
1756-
return -EFAULT;
1757-
}
1758-
1759-
/* get the user's cmd and do some simple validation */
1760-
ret = __comedi_get_user_cmd(dev, &cmd);
1753+
/* do some simple cmd validation */
1754+
ret = __comedi_get_user_cmd(dev, cmd);
17611755
if (ret)
17621756
return ret;
17631757

17641758
/* save user's chanlist pointer so it can be restored later */
1765-
user_chanlist = (unsigned int __user *)cmd.chanlist;
1759+
user_chanlist = (unsigned int __user *)cmd->chanlist;
17661760

1767-
s = &dev->subdevices[cmd.subdev];
1761+
s = &dev->subdevices[cmd->subdev];
17681762
async = s->async;
17691763

17701764
/* are we locked? (ioctl lock) */
@@ -1780,13 +1774,13 @@ static int do_cmd_ioctl(struct comedi_device *dev,
17801774
}
17811775

17821776
/* make sure channel/gain list isn't too short */
1783-
if (cmd.chanlist_len < 1) {
1777+
if (cmd->chanlist_len < 1) {
17841778
dev_dbg(dev->class_dev, "channel/gain list too short %u < 1\n",
1785-
cmd.chanlist_len);
1779+
cmd->chanlist_len);
17861780
return -EINVAL;
17871781
}
17881782

1789-
async->cmd = cmd;
1783+
async->cmd = *cmd;
17901784
async->cmd.data = NULL;
17911785

17921786
/* load channel/gain list */
@@ -1798,15 +1792,11 @@ static int do_cmd_ioctl(struct comedi_device *dev,
17981792

17991793
if (async->cmd.flags & CMDF_BOGUS || ret) {
18001794
dev_dbg(dev->class_dev, "test returned %d\n", ret);
1801-
cmd = async->cmd;
1795+
*cmd = async->cmd;
18021796
/* restore chanlist pointer before copying back */
1803-
cmd.chanlist = (unsigned int __force *)user_chanlist;
1804-
cmd.data = NULL;
1805-
if (copy_to_user(arg, &cmd, sizeof(cmd))) {
1806-
dev_dbg(dev->class_dev, "fault writing cmd\n");
1807-
ret = -EFAULT;
1808-
goto cleanup;
1809-
}
1797+
cmd->chanlist = (unsigned int __force *)user_chanlist;
1798+
cmd->data = NULL;
1799+
*copy = true;
18101800
ret = -EAGAIN;
18111801
goto cleanup;
18121802
}
@@ -2207,9 +2197,19 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
22072197
case COMEDI_CANCEL:
22082198
rc = do_cancel_ioctl(dev, arg, file);
22092199
break;
2210-
case COMEDI_CMD:
2211-
rc = do_cmd_ioctl(dev, (struct comedi_cmd __user *)arg, file);
2200+
case COMEDI_CMD: {
2201+
struct comedi_cmd cmd;
2202+
bool copy = false;
2203+
2204+
if (copy_from_user(&cmd, (void __user *)arg, sizeof(cmd))) {
2205+
rc = -EFAULT;
2206+
break;
2207+
}
2208+
rc = do_cmd_ioctl(dev, &cmd, &copy, file);
2209+
if (copy && copy_to_user((void __user *)arg, &cmd, sizeof(cmd)))
2210+
rc = -EFAULT;
22122211
break;
2212+
}
22132213
case COMEDI_CMDTEST: {
22142214
struct comedi_cmd cmd;
22152215
bool copy = false;

0 commit comments

Comments
 (0)