CHROMIUM: virtwl: use compat_ptr in compat_ioctl implementations
BUG=None
TEST=virtio_wl.c compiles
Change-Id: I5e00d8d98d48996bc1c7a61babe4ea291ed61cc7
Signed-off-by: Zach Reizner <zachr@google.com>
Reviewed-on: https://chromium-review.googlesource.com/865494
Commit-Ready: Zach Reizner <zachr@chromium.org>
Tested-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Dmitry Torokhov <dtor@chromium.org>
(cherry picked from commit efa89ecc24b75cc89384f715135ec25e1caa226d)
Reviewed-on: https://chromium-review.googlesource.com/957809
diff --git a/drivers/virtio/virtio_wl.c b/drivers/virtio/virtio_wl.c
index e7d0d3d..f5f1e1d 100644
--- a/drivers/virtio/virtio_wl.c
+++ b/drivers/virtio/virtio_wl.c
@@ -41,6 +41,7 @@
#include <linux/anon_inodes.h>
#include <linux/cdev.h>
+#include <linux/compat.h>
#include <linux/completion.h>
#include <linux/err.h>
#include <linux/fdtable.h>
@@ -879,16 +880,14 @@
return ERR_PTR(ret);
}
-static long virtwl_ioctl_send(struct file *filp, unsigned long arg)
+static long virtwl_ioctl_send(struct file *filp, void __user *ptr)
{
struct virtwl_vfd *vfd = filp->private_data;
struct virtwl_ioctl_txn ioctl_send;
- void __user *user_data = (void __user *)arg +
- sizeof(struct virtwl_ioctl_txn);
+ void __user *user_data = ptr + sizeof(struct virtwl_ioctl_txn);
int ret;
- ret = copy_from_user(&ioctl_send, (void __user *)arg,
- sizeof(struct virtwl_ioctl_txn));
+ ret = copy_from_user(&ioctl_send, ptr, sizeof(struct virtwl_ioctl_txn));
if (ret)
return -EFAULT;
@@ -901,12 +900,11 @@
filp->f_flags & O_NONBLOCK);
}
-static long virtwl_ioctl_recv(struct file *filp, unsigned long arg)
+static long virtwl_ioctl_recv(struct file *filp, void __user *ptr)
{
struct virtwl_ioctl_txn ioctl_recv;
- void __user *user_data = (void __user *)arg +
- sizeof(struct virtwl_ioctl_txn);
- int __user *user_fds = (int __user *)arg;
+ void __user *user_data = ptr + sizeof(struct virtwl_ioctl_txn);
+ int __user *user_fds = (int __user *)ptr;
size_t vfd_count = VIRTWL_SEND_MAX_ALLOCS;
struct virtwl_vfd *vfds[VIRTWL_SEND_MAX_ALLOCS] = { 0 };
int fds[VIRTWL_SEND_MAX_ALLOCS];
@@ -917,8 +915,7 @@
for (i = 0; i < VIRTWL_SEND_MAX_ALLOCS; i++)
fds[i] = -1;
- ret = copy_from_user(&ioctl_recv, (void __user *)arg,
- sizeof(struct virtwl_ioctl_txn));
+ ret = copy_from_user(&ioctl_recv, ptr, sizeof(struct virtwl_ioctl_txn));
if (ret)
return -EFAULT;
@@ -932,7 +929,7 @@
if (ret < 0)
return ret;
- ret = copy_to_user(&((struct virtwl_ioctl_txn __user *)arg)->len, &ret,
+ ret = copy_to_user(&((struct virtwl_ioctl_txn __user *)ptr)->len, &ret,
sizeof(ioctl_recv.len));
if (ret) {
ret = -EFAULT;
@@ -969,27 +966,26 @@
}
static long virtwl_vfd_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
+ void __user *ptr)
{
switch (cmd) {
case VIRTWL_IOCTL_SEND:
- return virtwl_ioctl_send(filp, arg);
+ return virtwl_ioctl_send(filp, ptr);
case VIRTWL_IOCTL_RECV:
- return virtwl_ioctl_recv(filp, arg);
+ return virtwl_ioctl_recv(filp, ptr);
default:
return -ENOTTY;
}
}
-static long virtwl_ioctl_new(struct file *filp, unsigned long arg)
+static long virtwl_ioctl_new(struct file *filp, void __user *ptr)
{
struct virtwl_info *vi = filp->private_data;
struct virtwl_vfd *vfd;
struct virtwl_ioctl_new ioctl_new;
int ret;
- ret = copy_from_user(&ioctl_new, (void __user *)arg,
- sizeof(struct virtwl_ioctl_new));
+ ret = copy_from_user(&ioctl_new, ptr, sizeof(struct virtwl_ioctl_new));
if (ret)
return -EFAULT;
@@ -1008,8 +1004,7 @@
}
ioctl_new.fd = ret;
- ret = copy_to_user((void __user *)arg, &ioctl_new,
- sizeof(struct virtwl_ioctl_new));
+ ret = copy_to_user(ptr, &ioctl_new, sizeof(struct virtwl_ioctl_new));
if (ret) {
/* The release operation will handle freeing this alloc */
sys_close(ioctl_new.fd);
@@ -1019,8 +1014,8 @@
return 0;
}
-static long virtwl_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
+static long virtwl_ioctl_ptr(struct file *filp, unsigned int cmd,
+ void *__user ptr)
{
int err = 0;
@@ -1030,27 +1025,36 @@
return -ENOTTY;
if (_IOC_DIR(cmd) & _IOC_READ) {
- err = !access_ok(VERIFY_WRITE, (void __user *)arg,
- _IOC_SIZE(cmd));
+ err = !access_ok(VERIFY_WRITE, ptr, _IOC_SIZE(cmd));
} else if (_IOC_DIR(cmd) & _IOC_WRITE) {
- err = !access_ok(VERIFY_READ, (void __user *)arg,
- _IOC_SIZE(cmd));
+ err = !access_ok(VERIFY_READ, ptr, _IOC_SIZE(cmd));
}
if (err)
return -EFAULT;
if (filp->f_op == &virtwl_vfd_fops)
- return virtwl_vfd_ioctl(filp, cmd, arg);
+ return virtwl_vfd_ioctl(filp, cmd, ptr);
switch (cmd) {
case VIRTWL_IOCTL_NEW:
- return virtwl_ioctl_new(filp, arg);
+ return virtwl_ioctl_new(filp, ptr);
default:
return -ENOTTY;
}
}
+static long virtwl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ return virtwl_ioctl_ptr(filp, cmd, (void *__user)arg);
+}
+
+static long virtwl_ioctl_compat(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ return virtwl_ioctl_ptr(filp, cmd, compat_ptr(arg));
+}
+
static int virtwl_release(struct inode *inodep, struct file *filp)
{
return 0;
@@ -1059,7 +1063,7 @@
static const struct file_operations virtwl_fops = {
.open = virtwl_open,
.unlocked_ioctl = virtwl_ioctl,
- .compat_ioctl = virtwl_ioctl,
+ .compat_ioctl = virtwl_ioctl_compat,
.release = virtwl_release,
};
@@ -1067,7 +1071,7 @@
.mmap = virtwl_vfd_mmap,
.poll = virtwl_vfd_poll,
.unlocked_ioctl = virtwl_ioctl,
- .compat_ioctl = virtwl_ioctl,
+ .compat_ioctl = virtwl_ioctl_compat,
.release = virtwl_vfd_release,
};