mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
comedi: get rid of compat_alloc_user_space() mess in COMEDI_CMD{,TEST} compat
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
0a3ccc75a9
commit
bac42fb212
1 changed files with 63 additions and 112 deletions
|
@ -2931,155 +2931,106 @@ static int compat_rangeinfo(struct file *file, unsigned long arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy 32-bit cmd structure to native cmd structure. */
|
/* Copy 32-bit cmd structure to native cmd structure. */
|
||||||
static int get_compat_cmd(struct comedi_cmd __user *cmd,
|
static int get_compat_cmd(struct comedi_cmd *cmd,
|
||||||
struct comedi32_cmd_struct __user *cmd32)
|
struct comedi32_cmd_struct __user *cmd32)
|
||||||
{
|
{
|
||||||
int err;
|
struct comedi32_cmd_struct v32;
|
||||||
union {
|
|
||||||
unsigned int uint;
|
|
||||||
compat_uptr_t uptr;
|
|
||||||
} temp;
|
|
||||||
|
|
||||||
/* Copy cmd structure. */
|
if (copy_from_user(&v32, cmd32, sizeof(v32)))
|
||||||
if (!access_ok(cmd32, sizeof(*cmd32)) ||
|
|
||||||
!access_ok(cmd, sizeof(*cmd)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
err = 0;
|
cmd->subdev = v32.subdev;
|
||||||
err |= __get_user(temp.uint, &cmd32->subdev);
|
cmd->flags = v32.flags;
|
||||||
err |= __put_user(temp.uint, &cmd->subdev);
|
cmd->start_src = v32.start_src;
|
||||||
err |= __get_user(temp.uint, &cmd32->flags);
|
cmd->start_arg = v32.start_arg;
|
||||||
err |= __put_user(temp.uint, &cmd->flags);
|
cmd->scan_begin_src = v32.scan_begin_src;
|
||||||
err |= __get_user(temp.uint, &cmd32->start_src);
|
cmd->scan_begin_arg = v32.scan_begin_arg;
|
||||||
err |= __put_user(temp.uint, &cmd->start_src);
|
cmd->convert_src = v32.convert_src;
|
||||||
err |= __get_user(temp.uint, &cmd32->start_arg);
|
cmd->convert_arg = v32.convert_arg;
|
||||||
err |= __put_user(temp.uint, &cmd->start_arg);
|
cmd->scan_end_src = v32.scan_end_src;
|
||||||
err |= __get_user(temp.uint, &cmd32->scan_begin_src);
|
cmd->scan_end_arg = v32.scan_end_arg;
|
||||||
err |= __put_user(temp.uint, &cmd->scan_begin_src);
|
cmd->stop_src = v32.stop_src;
|
||||||
err |= __get_user(temp.uint, &cmd32->scan_begin_arg);
|
cmd->stop_arg = v32.stop_arg;
|
||||||
err |= __put_user(temp.uint, &cmd->scan_begin_arg);
|
cmd->chanlist = compat_ptr(v32.chanlist);
|
||||||
err |= __get_user(temp.uint, &cmd32->convert_src);
|
cmd->chanlist_len = v32.chanlist_len;
|
||||||
err |= __put_user(temp.uint, &cmd->convert_src);
|
cmd->data = compat_ptr(v32.data);
|
||||||
err |= __get_user(temp.uint, &cmd32->convert_arg);
|
cmd->data_len = v32.data_len;
|
||||||
err |= __put_user(temp.uint, &cmd->convert_arg);
|
return 0;
|
||||||
err |= __get_user(temp.uint, &cmd32->scan_end_src);
|
|
||||||
err |= __put_user(temp.uint, &cmd->scan_end_src);
|
|
||||||
err |= __get_user(temp.uint, &cmd32->scan_end_arg);
|
|
||||||
err |= __put_user(temp.uint, &cmd->scan_end_arg);
|
|
||||||
err |= __get_user(temp.uint, &cmd32->stop_src);
|
|
||||||
err |= __put_user(temp.uint, &cmd->stop_src);
|
|
||||||
err |= __get_user(temp.uint, &cmd32->stop_arg);
|
|
||||||
err |= __put_user(temp.uint, &cmd->stop_arg);
|
|
||||||
err |= __get_user(temp.uptr, &cmd32->chanlist);
|
|
||||||
err |= __put_user((unsigned int __force *)compat_ptr(temp.uptr),
|
|
||||||
&cmd->chanlist);
|
|
||||||
err |= __get_user(temp.uint, &cmd32->chanlist_len);
|
|
||||||
err |= __put_user(temp.uint, &cmd->chanlist_len);
|
|
||||||
err |= __get_user(temp.uptr, &cmd32->data);
|
|
||||||
err |= __put_user(compat_ptr(temp.uptr), &cmd->data);
|
|
||||||
err |= __get_user(temp.uint, &cmd32->data_len);
|
|
||||||
err |= __put_user(temp.uint, &cmd->data_len);
|
|
||||||
return err ? -EFAULT : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy native cmd structure to 32-bit cmd structure. */
|
/* Copy native cmd structure to 32-bit cmd structure. */
|
||||||
static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32,
|
static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32,
|
||||||
struct comedi_cmd __user *cmd)
|
struct comedi_cmd *cmd)
|
||||||
{
|
{
|
||||||
int err;
|
struct comedi32_cmd_struct v32;
|
||||||
unsigned int temp;
|
|
||||||
|
|
||||||
/*
|
memset(&v32, 0, sizeof(v32));
|
||||||
* Copy back most of cmd structure.
|
v32.subdev = cmd->subdev;
|
||||||
*
|
v32.flags = cmd->flags;
|
||||||
* Assume the pointer values are already valid.
|
v32.start_src = cmd->start_src;
|
||||||
* (Could use ptr_to_compat() to set them.)
|
v32.start_arg = cmd->start_arg;
|
||||||
*/
|
v32.scan_begin_src = cmd->scan_begin_src;
|
||||||
if (!access_ok(cmd, sizeof(*cmd)) ||
|
v32.scan_begin_arg = cmd->scan_begin_arg;
|
||||||
!access_ok(cmd32, sizeof(*cmd32)))
|
v32.convert_src = cmd->convert_src;
|
||||||
return -EFAULT;
|
v32.convert_arg = cmd->convert_arg;
|
||||||
|
v32.scan_end_src = cmd->scan_end_src;
|
||||||
err = 0;
|
v32.scan_end_arg = cmd->scan_end_arg;
|
||||||
err |= __get_user(temp, &cmd->subdev);
|
v32.stop_src = cmd->stop_src;
|
||||||
err |= __put_user(temp, &cmd32->subdev);
|
v32.stop_arg = cmd->stop_arg;
|
||||||
err |= __get_user(temp, &cmd->flags);
|
|
||||||
err |= __put_user(temp, &cmd32->flags);
|
|
||||||
err |= __get_user(temp, &cmd->start_src);
|
|
||||||
err |= __put_user(temp, &cmd32->start_src);
|
|
||||||
err |= __get_user(temp, &cmd->start_arg);
|
|
||||||
err |= __put_user(temp, &cmd32->start_arg);
|
|
||||||
err |= __get_user(temp, &cmd->scan_begin_src);
|
|
||||||
err |= __put_user(temp, &cmd32->scan_begin_src);
|
|
||||||
err |= __get_user(temp, &cmd->scan_begin_arg);
|
|
||||||
err |= __put_user(temp, &cmd32->scan_begin_arg);
|
|
||||||
err |= __get_user(temp, &cmd->convert_src);
|
|
||||||
err |= __put_user(temp, &cmd32->convert_src);
|
|
||||||
err |= __get_user(temp, &cmd->convert_arg);
|
|
||||||
err |= __put_user(temp, &cmd32->convert_arg);
|
|
||||||
err |= __get_user(temp, &cmd->scan_end_src);
|
|
||||||
err |= __put_user(temp, &cmd32->scan_end_src);
|
|
||||||
err |= __get_user(temp, &cmd->scan_end_arg);
|
|
||||||
err |= __put_user(temp, &cmd32->scan_end_arg);
|
|
||||||
err |= __get_user(temp, &cmd->stop_src);
|
|
||||||
err |= __put_user(temp, &cmd32->stop_src);
|
|
||||||
err |= __get_user(temp, &cmd->stop_arg);
|
|
||||||
err |= __put_user(temp, &cmd32->stop_arg);
|
|
||||||
/* Assume chanlist pointer is unchanged. */
|
/* Assume chanlist pointer is unchanged. */
|
||||||
err |= __get_user(temp, &cmd->chanlist_len);
|
v32.chanlist = ptr_to_compat(cmd->chanlist);
|
||||||
err |= __put_user(temp, &cmd32->chanlist_len);
|
v32.chanlist_len = cmd->chanlist_len;
|
||||||
/* Assume data pointer is unchanged. */
|
v32.data = ptr_to_compat(cmd->data);
|
||||||
err |= __get_user(temp, &cmd->data_len);
|
v32.data_len = cmd->data_len;
|
||||||
err |= __put_user(temp, &cmd32->data_len);
|
return copy_to_user(cmd32, &v32, sizeof(v32));
|
||||||
return err ? -EFAULT : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle 32-bit COMEDI_CMD ioctl. */
|
/* Handle 32-bit COMEDI_CMD ioctl. */
|
||||||
static int compat_cmd(struct file *file, unsigned long arg)
|
static int compat_cmd(struct file *file, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct comedi_cmd __user *cmd;
|
struct comedi_file *cfp = file->private_data;
|
||||||
struct comedi32_cmd_struct __user *cmd32;
|
struct comedi_device *dev = cfp->dev;
|
||||||
|
struct comedi_cmd cmd;
|
||||||
|
bool copy = false;
|
||||||
int rc, err;
|
int rc, err;
|
||||||
|
|
||||||
cmd32 = compat_ptr(arg);
|
rc = get_compat_cmd(&cmd, compat_ptr(arg));
|
||||||
cmd = compat_alloc_user_space(sizeof(*cmd));
|
|
||||||
|
|
||||||
rc = get_compat_cmd(cmd, cmd32);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = comedi_unlocked_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
|
mutex_lock(&dev->mutex);
|
||||||
if (rc == -EAGAIN) {
|
rc = do_cmd_ioctl(dev, &cmd, ©, file);
|
||||||
|
mutex_unlock(&dev->mutex);
|
||||||
|
if (copy) {
|
||||||
/* Special case: copy cmd back to user. */
|
/* Special case: copy cmd back to user. */
|
||||||
err = put_compat_cmd(cmd32, cmd);
|
err = put_compat_cmd(compat_ptr(arg), &cmd);
|
||||||
if (err)
|
if (err)
|
||||||
rc = err;
|
rc = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle 32-bit COMEDI_CMDTEST ioctl. */
|
/* Handle 32-bit COMEDI_CMDTEST ioctl. */
|
||||||
static int compat_cmdtest(struct file *file, unsigned long arg)
|
static int compat_cmdtest(struct file *file, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct comedi_cmd __user *cmd;
|
struct comedi_file *cfp = file->private_data;
|
||||||
struct comedi32_cmd_struct __user *cmd32;
|
struct comedi_device *dev = cfp->dev;
|
||||||
|
struct comedi_cmd cmd;
|
||||||
|
bool copy = false;
|
||||||
int rc, err;
|
int rc, err;
|
||||||
|
|
||||||
cmd32 = compat_ptr(arg);
|
rc = get_compat_cmd(&cmd, compat_ptr(arg));
|
||||||
cmd = compat_alloc_user_space(sizeof(*cmd));
|
|
||||||
|
|
||||||
rc = get_compat_cmd(cmd, cmd32);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = comedi_unlocked_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd);
|
mutex_lock(&dev->mutex);
|
||||||
if (rc < 0)
|
rc = do_cmdtest_ioctl(dev, &cmd, ©, file);
|
||||||
return rc;
|
mutex_unlock(&dev->mutex);
|
||||||
|
if (copy) {
|
||||||
err = put_compat_cmd(cmd32, cmd);
|
err = put_compat_cmd(compat_ptr(arg), &cmd);
|
||||||
if (err)
|
if (err)
|
||||||
rc = err;
|
rc = err;
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue