summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Abbott <abbotti@mev.co.uk>2015-01-27 18:16:51 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-18 13:22:34 +0100
commit596c469f8f338819a95531c5bdf970b9d98e4bb9 (patch)
treed5b543594cacc95a75abc0bdb9ead935f53306fd
parent6e6493c26e176987bf215625ebcaea5954a05fa1 (diff)
downloadlwn-596c469f8f338819a95531c5bdf970b9d98e4bb9.tar.gz
lwn-596c469f8f338819a95531c5bdf970b9d98e4bb9.zip
staging: comedi: comedi_compat32.c: fix COMEDI_CMD copy back
commit 42b8ce6f55facfa101462e694d33fc6bca471138 upstream. `do_cmd_ioctl()` in "comedi_fops.c" handles the `COMEDI_CMD` ioctl. This returns `-EAGAIN` if it has copied a modified `struct comedi_cmd` back to user-space. (This occurs when the low-level Comedi driver's `do_cmdtest()` handler returns non-zero to indicate a problem with the contents of the `struct comedi_cmd`, or when the `struct comedi_cmd` has the `CMDF_BOGUS` flag set.) `compat_cmd()` in "comedi_compat32.c" handles the 32-bit compatible version of the `COMEDI_CMD` ioctl. Currently, it never copies a 32-bit compatible version of `struct comedi_cmd` back to user-space, which is at odds with the way the regular `COMEDI_CMD` ioctl is handled. To fix it, change `compat_cmd()` to copy a 32-bit compatible version of the `struct comedi_cmd` back to user-space when the main ioctl handler returns `-EAGAIN`. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/comedi/comedi_compat32.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
index ad208cdd53d4..83bcf968ac63 100644
--- a/drivers/staging/comedi/comedi_compat32.c
+++ b/drivers/staging/comedi/comedi_compat32.c
@@ -270,7 +270,7 @@ static int compat_cmd(struct file *file, unsigned long arg)
{
struct comedi_cmd __user *cmd;
struct comedi32_cmd_struct __user *cmd32;
- int rc;
+ int rc, err;
cmd32 = compat_ptr(arg);
cmd = compat_alloc_user_space(sizeof(*cmd));
@@ -279,7 +279,15 @@ static int compat_cmd(struct file *file, unsigned long arg)
if (rc)
return rc;
- return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
+ rc = translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
+ if (rc == -EAGAIN) {
+ /* Special case: copy cmd back to user. */
+ err = put_compat_cmd(cmd32, cmd);
+ if (err)
+ rc = err;
+ }
+
+ return rc;
}
/* Handle 32-bit COMEDI_CMDTEST ioctl. */