summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-17 11:54:55 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-17 11:54:55 -0800
commit93f30c73ecd0281cf3685ef0e4e384980a176176 (patch)
treebd272334a0dbd258c08b5b2237e8bf5e17ce7255 /drivers
parent06ede5f6086757f746b7be860ae76137f4e95032 (diff)
parent96271654f55c74ff7325fbdfc535466c9deb0ce6 (diff)
downloadlinux-93f30c73ecd0281cf3685ef0e4e384980a176176.tar.gz
Merge branch 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull compat and uaccess updates from Al Viro:

 - {get,put}_compat_sigset() series

 - assorted compat ioctl stuff

 - more set_fs() elimination

 - a few more timespec64 conversions

 - several removals of pointless access_ok() in places where it was
   followed only by non-__ variants of primitives

* 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (24 commits)
  coredump: call do_unlinkat directly instead of sys_unlink
  fs: expose do_unlinkat for built-in callers
  ext4: take handling of EXT4_IOC_GROUP_ADD into a helper, get rid of set_fs()
  ipmi: get rid of pointless access_ok()
  pi433: sanitize ioctl
  cxlflash: get rid of pointless access_ok()
  mtdchar: get rid of pointless access_ok()
  r128: switch compat ioctls to drm_ioctl_kernel()
  selection: get rid of field-by-field copyin
  VT_RESIZEX: get rid of field-by-field copyin
  i2c compat ioctls: move to ->compat_ioctl()
  sched_rr_get_interval(): move compat to native, get rid of set_fs()
  mips: switch to {get,put}_compat_sigset()
  sparc: switch to {get,put}_compat_sigset()
  s390: switch to {get,put}_compat_sigset()
  ppc: switch to {get,put}_compat_sigset()
  parisc: switch to {get,put}_compat_sigset()
  get_compat_sigset()
  get rid of {get,put}_compat_itimerspec()
  io_getevents: Use timespec64 to represent timeouts
  ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/ipmi/bt-bmc.c6
-rw-r--r--drivers/gpu/drm/r128/r128_drv.h4
-rw-r--r--drivers/gpu/drm/r128/r128_ioc32.c99
-rw-r--r--drivers/gpu/drm/r128/r128_state.c6
-rw-r--r--drivers/i2c/i2c-dev.c268
-rw-r--r--drivers/mtd/mtdchar.c24
-rw-r--r--drivers/scsi/cxlflash/main.c6
-rw-r--r--drivers/staging/pi433/pi433_if.c90
-rw-r--r--drivers/tty/vt/selection.c50
-rw-r--r--drivers/tty/vt/vt_ioctl.c68
10 files changed, 291 insertions, 330 deletions
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index 70d434bc1cbf..c4ef73c6f455 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -204,9 +204,6 @@ static ssize_t bt_bmc_read(struct file *file, char __user *buf,
 	ssize_t ret = 0;
 	ssize_t nread;
 
-	if (!access_ok(VERIFY_WRITE, buf, count))
-		return -EFAULT;
-
 	WARN_ON(*ppos);
 
 	if (wait_event_interruptible(bt_bmc->queue,
@@ -277,9 +274,6 @@ static ssize_t bt_bmc_write(struct file *file, const char __user *buf,
 	if (count < 5)
 		return -EINVAL;
 
-	if (!access_ok(VERIFY_READ, buf, count))
-		return -EFAULT;
-
 	WARN_ON(*ppos);
 
 	/*
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
index 09143b840482..2de40d276116 100644
--- a/drivers/gpu/drm/r128/r128_drv.h
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -147,6 +147,10 @@ extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file
 extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
 extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
 
+extern int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv);
+
 extern void r128_freelist_reset(struct drm_device *dev);
 
 extern int r128_wait_ring(drm_r128_private_t *dev_priv, int n);
diff --git a/drivers/gpu/drm/r128/r128_ioc32.c b/drivers/gpu/drm/r128/r128_ioc32.c
index 663f38c63ba6..6589f9e0310e 100644
--- a/drivers/gpu/drm/r128/r128_ioc32.c
+++ b/drivers/gpu/drm/r128/r128_ioc32.c
@@ -63,39 +63,36 @@ static int compat_r128_init(struct file *file, unsigned int cmd,
 			    unsigned long arg)
 {
 	drm_r128_init32_t init32;
-	drm_r128_init_t __user *init;
+	drm_r128_init_t init;
 
 	if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
 		return -EFAULT;
 
-	init = compat_alloc_user_space(sizeof(*init));
-	if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
-	    || __put_user(init32.func, &init->func)
-	    || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
-	    || __put_user(init32.is_pci, &init->is_pci)
-	    || __put_user(init32.cce_mode, &init->cce_mode)
-	    || __put_user(init32.cce_secure, &init->cce_secure)
-	    || __put_user(init32.ring_size, &init->ring_size)
-	    || __put_user(init32.usec_timeout, &init->usec_timeout)
-	    || __put_user(init32.fb_bpp, &init->fb_bpp)
-	    || __put_user(init32.front_offset, &init->front_offset)
-	    || __put_user(init32.front_pitch, &init->front_pitch)
-	    || __put_user(init32.back_offset, &init->back_offset)
-	    || __put_user(init32.back_pitch, &init->back_pitch)
-	    || __put_user(init32.depth_bpp, &init->depth_bpp)
-	    || __put_user(init32.depth_offset, &init->depth_offset)
-	    || __put_user(init32.depth_pitch, &init->depth_pitch)
-	    || __put_user(init32.span_offset, &init->span_offset)
-	    || __put_user(init32.fb_offset, &init->fb_offset)
-	    || __put_user(init32.mmio_offset, &init->mmio_offset)
-	    || __put_user(init32.ring_offset, &init->ring_offset)
-	    || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
-	    || __put_user(init32.buffers_offset, &init->buffers_offset)
-	    || __put_user(init32.agp_textures_offset,
-			  &init->agp_textures_offset))
-		return -EFAULT;
-
-	return drm_ioctl(file, DRM_IOCTL_R128_INIT, (unsigned long)init);
+	init.func = init32.func;
+	init.sarea_priv_offset = init32.sarea_priv_offset;
+	init.is_pci = init32.is_pci;
+	init.cce_mode = init32.cce_mode;
+	init.cce_secure = init32.cce_secure;
+	init.ring_size = init32.ring_size;
+	init.usec_timeout = init32.usec_timeout;
+	init.fb_bpp = init32.fb_bpp;
+	init.front_offset = init32.front_offset;
+	init.front_pitch = init32.front_pitch;
+	init.back_offset = init32.back_offset;
+	init.back_pitch = init32.back_pitch;
+	init.depth_bpp = init32.depth_bpp;
+	init.depth_offset = init32.depth_offset;
+	init.depth_pitch = init32.depth_pitch;
+	init.span_offset = init32.span_offset;
+	init.fb_offset = init32.fb_offset;
+	init.mmio_offset = init32.mmio_offset;
+	init.ring_offset = init32.ring_offset;
+	init.ring_rptr_offset = init32.ring_rptr_offset;
+	init.buffers_offset = init32.buffers_offset;
+	init.agp_textures_offset = init32.agp_textures_offset;
+
+	return drm_ioctl_kernel(file, r128_cce_init, &init,
+			DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
 }
 
 typedef struct drm_r128_depth32 {
@@ -111,25 +108,19 @@ static int compat_r128_depth(struct file *file, unsigned int cmd,
 			     unsigned long arg)
 {
 	drm_r128_depth32_t depth32;
-	drm_r128_depth_t __user *depth;
+	drm_r128_depth_t depth;
 
 	if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32)))
 		return -EFAULT;
 
-	depth = compat_alloc_user_space(sizeof(*depth));
-	if (!access_ok(VERIFY_WRITE, depth, sizeof(*depth))
-	    || __put_user(depth32.func, &depth->func)
-	    || __put_user(depth32.n, &depth->n)
-	    || __put_user((int __user *)(unsigned long)depth32.x, &depth->x)
-	    || __put_user((int __user *)(unsigned long)depth32.y, &depth->y)
-	    || __put_user((unsigned int __user *)(unsigned long)depth32.buffer,
-			  &depth->buffer)
-	    || __put_user((unsigned char __user *)(unsigned long)depth32.mask,
-			  &depth->mask))
-		return -EFAULT;
-
-	return drm_ioctl(file, DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
+	depth.func = depth32.func;
+	depth.n = depth32.n;
+	depth.x = compat_ptr(depth32.x);
+	depth.y = compat_ptr(depth32.y);
+	depth.buffer = compat_ptr(depth32.buffer);
+	depth.mask = compat_ptr(depth32.mask);
 
+	return drm_ioctl_kernel(file, r128_cce_depth, &depth, DRM_AUTH);
 }
 
 typedef struct drm_r128_stipple32 {
@@ -140,18 +131,14 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd,
 			       unsigned long arg)
 {
 	drm_r128_stipple32_t stipple32;
-	drm_r128_stipple_t __user *stipple;
+	drm_r128_stipple_t stipple;
 
 	if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32)))
 		return -EFAULT;
 
-	stipple = compat_alloc_user_space(sizeof(*stipple));
-	if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple))
-	    || __put_user((unsigned int __user *)(unsigned long)stipple32.mask,
-			  &stipple->mask))
-		return -EFAULT;
+	stipple.mask = compat_ptr(stipple32.mask);
 
-	return drm_ioctl(file, DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
+	return drm_ioctl_kernel(file, r128_cce_stipple, &stipple, DRM_AUTH);
 }
 
 typedef struct drm_r128_getparam32 {
@@ -163,19 +150,15 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd,
 				unsigned long arg)
 {
 	drm_r128_getparam32_t getparam32;
-	drm_r128_getparam_t __user *getparam;
+	drm_r128_getparam_t getparam;
 
 	if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
 		return -EFAULT;
 
-	getparam = compat_alloc_user_space(sizeof(*getparam));
-	if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
-	    || __put_user(getparam32.param, &getparam->param)
-	    || __put_user((void __user *)(unsigned long)getparam32.value,
-			  &getparam->value))
-		return -EFAULT;
+	getparam.param = getparam32.param;
+	getparam.value = compat_ptr(getparam32.value);
 
-	return drm_ioctl(file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
+	return drm_ioctl_kernel(file, r128_getparam, &getparam, DRM_AUTH);
 }
 
 drm_ioctl_compat_t *r128_compat_ioctls[] = {
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
index 8fd2d9f58f77..8fdc56c1c953 100644
--- a/drivers/gpu/drm/r128/r128_state.c
+++ b/drivers/gpu/drm/r128/r128_state.c
@@ -1460,7 +1460,7 @@ static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *fi
 	return ret;
 }
 
-static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_depth_t *depth = data;
@@ -1492,7 +1492,7 @@ static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *f
 	return ret;
 }
 
-static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_stipple_t *stipple = data;
@@ -1582,7 +1582,7 @@ static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file
 	return 0;
 }
 
-static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_getparam_t *param = data;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 6f638bbc922d..2cab27a68479 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -35,6 +35,7 @@
 #include <linux/notifier.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/compat.h>
 
 /*
  * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
@@ -238,46 +239,29 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
 }
 
 static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
-		unsigned long arg)
+		unsigned nmsgs, struct i2c_msg *msgs)
 {
-	struct i2c_rdwr_ioctl_data rdwr_arg;
-	struct i2c_msg *rdwr_pa;
 	u8 __user **data_ptrs;
 	int i, res;
 
-	if (copy_from_user(&rdwr_arg,
-			   (struct i2c_rdwr_ioctl_data __user *)arg,
-			   sizeof(rdwr_arg)))
-		return -EFAULT;
-
-	/* Put an arbitrary limit on the number of messages that can
-	 * be sent at once */
-	if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
-		return -EINVAL;
-
-	rdwr_pa = memdup_user(rdwr_arg.msgs,
-			      rdwr_arg.nmsgs * sizeof(struct i2c_msg));
-	if (IS_ERR(rdwr_pa))
-		return PTR_ERR(rdwr_pa);
-
-	data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
+	data_ptrs = kmalloc(nmsgs * sizeof(u8 __user *), GFP_KERNEL);
 	if (data_ptrs == NULL) {
-		kfree(rdwr_pa);
+		kfree(msgs);
 		return -ENOMEM;
 	}
 
 	res = 0;
-	for (i = 0; i < rdwr_arg.nmsgs; i++) {
+	for (i = 0; i < nmsgs; i++) {
 		/* Limit the size of the message to a sane amount */
-		if (rdwr_pa[i].len > 8192) {
+		if (msgs[i].len > 8192) {
 			res = -EINVAL;
 			break;
 		}
 
-		data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
-		rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len);
-		if (IS_ERR(rdwr_pa[i].buf)) {
-			res = PTR_ERR(rdwr_pa[i].buf);
+		data_ptrs[i] = (u8 __user *)msgs[i].buf;
+		msgs[i].buf = memdup_user(data_ptrs[i], msgs[i].len);
+		if (IS_ERR(msgs[i].buf)) {
+			res = PTR_ERR(msgs[i].buf);
 			break;
 		}
 
@@ -292,121 +276,117 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
 		 * greater (for example to account for a checksum byte at
 		 * the end of the message.)
 		 */
-		if (rdwr_pa[i].flags & I2C_M_RECV_LEN) {
-			if (!(rdwr_pa[i].flags & I2C_M_RD) ||
-			    rdwr_pa[i].buf[0] < 1 ||
-			    rdwr_pa[i].len < rdwr_pa[i].buf[0] +
+		if (msgs[i].flags & I2C_M_RECV_LEN) {
+			if (!(msgs[i].flags & I2C_M_RD) ||
+			    msgs[i].buf[0] < 1 ||
+			    msgs[i].len < msgs[i].buf[0] +
 					     I2C_SMBUS_BLOCK_MAX) {
 				res = -EINVAL;
 				break;
 			}
 
-			rdwr_pa[i].len = rdwr_pa[i].buf[0];
+			msgs[i].len = msgs[i].buf[0];
 		}
 	}
 	if (res < 0) {
 		int j;
 		for (j = 0; j < i; ++j)
-			kfree(rdwr_pa[j].buf);
+			kfree(msgs[j].buf);
 		kfree(data_ptrs);
-		kfree(rdwr_pa);
+		kfree(msgs);
 		return res;
 	}
 
-	res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);
+	res = i2c_transfer(client->adapter, msgs, nmsgs);
 	while (i-- > 0) {
-		if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
-			if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,
-					 rdwr_pa[i].len))
+		if (res >= 0 && (msgs[i].flags & I2C_M_RD)) {
+			if (copy_to_user(data_ptrs[i], msgs[i].buf,
+					 msgs[i].len))
 				res = -EFAULT;
 		}
-		kfree(rdwr_pa[i].buf);
+		kfree(msgs[i].buf);
 	}
 	kfree(data_ptrs);
-	kfree(rdwr_pa);
+	kfree(msgs);
 	return res;
 }
 
 static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
-		unsigned long arg)
+		u8 read_write, u8 command, u32 size,
+		union i2c_smbus_data __user *data)
 {
-	struct i2c_smbus_ioctl_data data_arg;
 	union i2c_smbus_data temp = {};
 	int datasize, res;
 
-	if (copy_from_user(&data_arg,
-			   (struct i2c_smbus_ioctl_data __user *) arg,
-			   sizeof(struct i2c_smbus_ioctl_data)))
-		return -EFAULT;
-	if ((data_arg.size != I2C_SMBUS_BYTE) &&
-	    (data_arg.size != I2C_SMBUS_QUICK) &&
-	    (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
-	    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
-	    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
-	    (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
-	    (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
-	    (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
-	    (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
+	if ((size != I2C_SMBUS_BYTE) &&
+	    (size != I2C_SMBUS_QUICK) &&
+	    (size != I2C_SMBUS_BYTE_DATA) &&
+	    (size != I2C_SMBUS_WORD_DATA) &&
+	    (size != I2C_SMBUS_PROC_CALL) &&
+	    (size != I2C_SMBUS_BLOCK_DATA) &&
+	    (size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
+	    (size != I2C_SMBUS_I2C_BLOCK_DATA) &&
+	    (size != I2C_SMBUS_BLOCK_PROC_CALL)) {
 		dev_dbg(&client->adapter->dev,
 			"size out of range (%x) in ioctl I2C_SMBUS.\n",
-			data_arg.size);
+			size);
 		return -EINVAL;
 	}
 	/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
 	   so the check is valid if size==I2C_SMBUS_QUICK too. */
-	if ((data_arg.read_write != I2C_SMBUS_READ) &&
-	    (data_arg.read_write != I2C_SMBUS_WRITE)) {
+	if ((read_write != I2C_SMBUS_READ) &&
+	    (read_write != I2C_SMBUS_WRITE)) {
 		dev_dbg(&client->adapter->dev,
 			"read_write out of range (%x) in ioctl I2C_SMBUS.\n",
-			data_arg.read_write);
+			read_write);
 		return -EINVAL;
 	}
 
 	/* Note that command values are always valid! */
 
-	if ((data_arg.size == I2C_SMBUS_QUICK) ||
-	    ((data_arg.size == I2C_SMBUS_BYTE) &&
-	    (data_arg.read_write == I2C_SMBUS_WRITE)))
+	if ((size == I2C_SMBUS_QUICK) ||
+	    ((size == I2C_SMBUS_BYTE) &&
+	    (read_write == I2C_SMBUS_WRITE)))
 		/* These are special: we do not use data */
 		return i2c_smbus_xfer(client->adapter, client->addr,
-				      client->flags, data_arg.read_write,
-				      data_arg.command, data_arg.size, NULL);
+				      client->flags, read_write,
+				      command, size, NULL);
 
-	if (data_arg.data == NULL) {
+	if (data == NULL) {
 		dev_dbg(&client->adapter->dev,
 			"data is NULL pointer in ioctl I2C_SMBUS.\n");
 		return -EINVAL;
 	}
 
-	if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
-	    (data_arg.size == I2C_SMBUS_BYTE))
-		datasize = sizeof(data_arg.data->byte);
-	else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
-		 (data_arg.size == I2C_SMBUS_PROC_CALL))
-		datasize = sizeof(data_arg.data->word);
+	if ((size == I2C_SMBUS_BYTE_DATA) ||
+	    (size == I2C_SMBUS_BYTE))
+		datasize = sizeof(data->byte);
+	else if ((size == I2C_SMBUS_WORD_DATA) ||
+		 (size == I2C_SMBUS_PROC_CALL))
+		datasize = sizeof(data->word);
 	else /* size == smbus block, i2c block, or block proc. call */
-		datasize = sizeof(data_arg.data->block);
+		datasize = sizeof(data->block);
 
-	if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
-	    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
-	    (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
-	    (data_arg.read_write == I2C_SMBUS_WRITE)) {
-		if (copy_from_user(&temp, data_arg.data, datasize))
+	if ((size == I2C_SMBUS_PROC_CALL) ||
+	    (size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+	    (size == I2C_SMBUS_I2C_BLOCK_DATA) ||
+	    (read_write == I2C_SMBUS_WRITE)) {
+		if (copy_from_user(&temp, data, datasize))
 			return -EFAULT;
 	}
-	if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
+	if (size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
 		/* Convert old I2C block commands to the new
 		   convention. This preserves binary compatibility. */
-		data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
-		if (data_arg.read_write == I2C_SMBUS_READ)
+		size = I2C_SMBUS_I2C_BLOCK_DATA;
+		if (read_write == I2C_SMBUS_READ)
 			temp.block[0] = I2C_SMBUS_BLOCK_MAX;
 	}
 	res = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
-	      data_arg.read_write, data_arg.command, data_arg.size, &temp);
-	if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
-		     (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
-		     (data_arg.read_write == I2C_SMBUS_READ))) {
-		if (copy_to_user(data_arg.data, &temp, datasize))
+	      read_write, command, size, &temp);
+	if (!res && ((size == I2C_SMBUS_PROC_CALL) ||
+		     (size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+		     (read_write == I2C_SMBUS_READ))) {
+		if (copy_to_user(data, &temp, datasize))
 			return -EFAULT;
 	}
 	return res;
@@ -454,12 +434,39 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		funcs = i2c_get_functionality(client->adapter);
 		return put_user(funcs, (unsigned long __user *)arg);
 
-	case I2C_RDWR:
-		return i2cdev_ioctl_rdwr(client, arg);
+	case I2C_RDWR: {
+		struct i2c_rdwr_ioctl_data rdwr_arg;
+		struct i2c_msg *rdwr_pa;
+
+		if (copy_from_user(&rdwr_arg,
+				   (struct i2c_rdwr_ioctl_data __user *)arg,
+				   sizeof(rdwr_arg)))
+			return -EFAULT;
+
+		/* Put an arbitrary limit on the number of messages that can
+		 * be sent at once */
+		if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
+			return -EINVAL;
 
-	case I2C_SMBUS:
-		return i2cdev_ioctl_smbus(client, arg);
+		rdwr_pa = memdup_user(rdwr_arg.msgs,
+				      rdwr_arg.nmsgs * sizeof(struct i2c_msg));
+		if (IS_ERR(rdwr_pa))
+			return PTR_ERR(rdwr_pa);
+
+		return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
+	}
 
+	case I2C_SMBUS: {
+		struct i2c_smbus_ioctl_data data_arg;
+		if (copy_from_user(&data_arg,
+				   (struct i2c_smbus_ioctl_data __user *) arg,
+				   sizeof(struct i2c_smbus_ioctl_data)))
+			return -EFAULT;
+		return i2cdev_ioctl_smbus(client, data_arg.read_write,
+					  data_arg.command,
+					  data_arg.size,
+					  data_arg.data);
+	}
 	case I2C_RETRIES:
 		client->adapter->retries = arg;
 		break;
@@ -480,6 +487,90 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	return 0;
 }
 
+#ifdef CONFIG_COMPAT
+
+struct i2c_smbus_ioctl_data32 {
+	u8 read_write;
+	u8 command;
+	u32 size;
+	compat_caddr_t data; /* union i2c_smbus_data *data */
+};
+
+struct i2c_msg32 {
+	u16 addr;
+	u16 flags;
+	u16 len;
+	compat_caddr_t buf;
+};
+
+struct i2c_rdwr_ioctl_data32 {
+	compat_caddr_t msgs; /* struct i2c_msg __user *msgs */
+	u32 nmsgs;
+};
+
+static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct i2c_client *client = file->private_data;
+	unsigned long funcs;
+	switch (cmd) {
+	case I2C_FUNCS:
+		funcs = i2c_get_functionality(client->adapter);
+		return put_user(funcs, (compat_ulong_t __user *)arg);
+	case I2C_RDWR: {
+		struct i2c_rdwr_ioctl_data32 rdwr_arg;
+		struct i2c_msg32 *p;
+		struct i2c_msg *rdwr_pa;
+		int i;
+
+		if (copy_from_user(&rdwr_arg,
+				   (struct i2c_rdwr_ioctl_data32 __user *)arg,
+				   sizeof(rdwr_arg)))
+			return -EFAULT;
+
+		if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
+			return -EINVAL;
+
+		rdwr_pa = kmalloc_array(rdwr_arg.nmsgs, sizeof(struct i2c_msg),
+				      GFP_KERNEL);
+		if (!rdwr_pa)
+			return -ENOMEM;
+
+		p = compat_ptr(rdwr_arg.msgs);
+		for (i = 0; i < rdwr_arg.nmsgs; i++) {
+			struct i2c_msg32 umsg;
+			if (copy_from_user(&umsg, p + i, sizeof(umsg))) {
+				kfree(rdwr_pa);
+				return -EFAULT;
+			}
+			rdwr_pa[i] = (struct i2c_msg) {
+				.addr = umsg.addr,
+				.flags = umsg.flags,
+				.len = umsg.len,
+				.buf = compat_ptr(umsg.buf)
+			};
+		}
+
+		return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
+	}
+	case I2C_SMBUS: {
+		struct i2c_smbus_ioctl_data32	data32;
+		if (copy_from_user(&data32,
+				   (void __user *) arg,
+				   sizeof(data32)))
+			return -EFAULT;
+		return i2cdev_ioctl_smbus(client, data32.read_write,
+					  data32.command,
+					  data32.size,
+					  compat_ptr(data32.data));
+	}
+	default:
+		return i2cdev_ioctl(file, cmd, arg);
+	}
+}
+#else
+#define compat_i2cdev_ioctl NULL
+#endif
+
 static int i2cdev_open(struct inode *inode, struct file *file)
 {
 	unsigned int minor = iminor(inode);
@@ -527,6 +618,7 @@ static const struct file_operations i2cdev_fops = {
 	.read		= i2cdev_read,
 	.write		= i2cdev_write,
 	.unlocked_ioctl	= i2cdev_ioctl,
+	.compat_ioctl	= compat_i2cdev_ioctl,
 	.open		= i2cdev_open,
 	.release	= i2cdev_release,
 };
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3568294d4854..de8c902059b8 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -375,12 +375,7 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
 		return -EINVAL;
 
 	if (!mtd->_write_oob)
-		ret = -EOPNOTSUPP;
-	else
-		ret = access_ok(VERIFY_READ, ptr, length) ? 0 : -EFAULT;
-
-	if (ret)
-		return ret;
+		return -EOPNOTSUPP;
 
 	ops.ooblen = length;
 	ops.ooboffs = start & (mtd->writesize - 1);
@@ -419,9 +414,6 @@ static int mtdchar_readoob(struct file *file, struct mtd_info *mtd,
 	if (length > 4096)
 		return -EINVAL;
 
-	if (!access_ok(VERIFY_WRITE, ptr, length))
-		return -EFAULT;
-
 	ops.ooblen = length;
 	ops.ooboffs = start & (mtd->writesize - 1);
 	ops.datbuf = NULL;
@@ -618,9 +610,6 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd,
 
 	usr_data = (const void __user *)(uintptr_t)req.usr_data;
 	usr_oob = (const void __user *)(uintptr_t)req.usr_oob;
-	if (!access_ok(VERIFY_READ, usr_data, req.len) ||
-	    !access_ok(VERIFY_READ, usr_oob, req.ooblen))
-		return -EFAULT;
 
 	if (!mtd->_write_oob)
 		return -EOPNOTSUPP;
@@ -662,21 +651,10 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
 	struct mtd_info *mtd = mfi->mtd;
 	void __user *argp = (void __user *)arg;
 	int ret = 0;
-	u_long size;
 	struct mtd_info_user info;
 
 	pr_debug("MTD_ioctl\n");
 
-	size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
-	if (cmd & IOC_IN) {
-		if (!access_ok(VERIFY_READ, argp, size))
-			return -EFAULT;
-	}
-	if (cmd & IOC_OUT) {
-		if (!access_ok(VERIFY_WRITE, argp, size))
-			return -EFAULT;
-	}
-
 	switch (cmd) {
 	case MEMGETREGIONCOUNT:
 		if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 617802855233..38b3a9c84fd1 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -3393,12 +3393,6 @@ static int cxlflash_afu_debug(struct cxlflash_cfg *cfg,
 			goto out;
 		}
 
-		if (unlikely(!access_ok(is_write ? VERIFY_READ : VERIFY_WRITE,
-					ubuf, ulen))) {
-			rc = -EFAULT;
-			goto out;
-		}
-
 		buf = kmalloc(ulen + cache_line_size() - 1, GFP_KERNEL);
 		if (unlikely(!buf)) {
 			rc = -ENOMEM;
diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c
index d946838450d4..2a205c6173dc 100644
--- a/drivers/staging/pi433/pi433_if.c
+++ b/drivers/staging/pi433/pi433_if.c
@@ -762,32 +762,15 @@ abort:
 static long
 pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	int			err = 0;
 	int			retval = 0;
 	struct pi433_instance	*instance;
 	struct pi433_device	*device;
-	u32			tmp;
+	void __user *argp = (void __user *)arg;
 
 	/* Check type and command number */
 	if (_IOC_TYPE(cmd) != PI433_IOC_MAGIC)
 		return -ENOTTY;
 
-	/* Check access direction once here; don't repeat below.
-	 * IOC_DIR is from the user perspective, while access_ok is
-	 * from the kernel perspective; so they look reversed.
-	 */
-	if (_IOC_DIR(cmd) & _IOC_READ)
-		err = !access_ok(VERIFY_WRITE,
-				 (void __user *)arg,
-				 _IOC_SIZE(cmd));
-
-	if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
-		err = !access_ok(VERIFY_READ,
-				 (void __user *)arg,
-				 _IOC_SIZE(cmd));
-	if (err)
-		return -EFAULT;
-
 	/* TODO? guard against device removal before, or while,
 	 * we issue this ioctl. --> device_get()
 	 */
@@ -799,78 +782,33 @@ pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
 	switch (cmd) {
 	case PI433_IOC_RD_TX_CFG:
-		tmp = _IOC_SIZE(cmd);
-		if ((tmp == 0) || ((tmp % sizeof(struct pi433_tx_cfg)) != 0)) {
-			retval = -EINVAL;
-			break;
-		}
-
-		if (__copy_to_user((void __user *)arg,
-				    &instance->tx_cfg,
-				    tmp))
-		{
-			retval = -EFAULT;
-			break;
-		}
-
+		if (copy_to_user(argp, &instance->tx_cfg,
+					sizeof(struct pi433_tx_cfg)))
+			return -EFAULT;
 		break;
 	case PI433_IOC_WR_TX_CFG:
-		tmp = _IOC_SIZE(cmd);
-		if ((tmp == 0) || ((tmp % sizeof(struct pi433_tx_cfg)) != 0)) {
-			retval = -EINVAL;
-			break;
-		}
-
-		if (__copy_from_user(&instance->tx_cfg,
-				     (void __user *)arg,
-				     tmp))
-		{
-			retval = -EFAULT;
-			break;
-		}
-
+		if (copy_from_user(&instance->tx_cfg, argp,
+					sizeof(struct pi433_tx_cfg)))
+			return -EFAULT;
 		break;
-
 	case PI433_IOC_RD_RX_CFG:
-		tmp = _IOC_SIZE(cmd);
-		if ( (tmp == 0) || ((tmp % sizeof(struct pi433_rx_cfg)) != 0) ) {
-			retval = -EINVAL;
-			break;
-		}
-
-		if (__copy_to_user((void __user *)arg,
-				   &device->rx_cfg,
-				   tmp))
-		{
-			retval = -EFAULT;
-			break;
-		}
-
+		if (copy_to_user(argp, &device->rx_cfg,
+					sizeof(struct pi433_rx_cfg)))
+			return -EFAULT;
 		break;
 	case PI433_IOC_WR_RX_CFG:
-		tmp = _IOC_SIZE(cmd);
 		mutex_lock(&device->rx_lock);
 
 		/* during pendig read request, change of config not allowed */
 		if (device->rx_active) {
-			retval = -EAGAIN;
-			mutex_unlock(&device->rx_lock);
-			break;
-		}
-
-		if ( (tmp == 0) || ((tmp % sizeof(struct pi433_rx_cfg)) != 0) ) {
-			retval = -EINVAL;
 			mutex_unlock(&device->rx_lock);
-			break;
+			return -EAGAIN;
 		}
 
-		if (__copy_from_user(&device->rx_cfg,
-				     (void __user *)arg,
-				     tmp))
-		{
-			retval = -EFAULT;
+		if (copy_from_user(&device->rx_cfg, argp,
+					sizeof(struct pi433_rx_cfg))) {
 			mutex_unlock(&device->rx_lock);
-			break;
+			return -EFAULT;
 		}
 
 		mutex_unlock(&device->rx_lock);
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 7a4c8022c023..af4da9507180 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -156,42 +156,34 @@ static int store_utf8(u16 c, char *p)
 int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
-	int sel_mode, new_sel_start, new_sel_end, spc;
+	int new_sel_start, new_sel_end, spc;
+	struct tiocl_selection v;
 	char *bp, *obp;
 	int i, ps, pe, multiplier;
 	u16 c;
 	int mode;
 
 	poke_blanked_console();
+	if (copy_from_user(&v, sel, sizeof(*sel)))
+		return -EFAULT;
 
-	{ unsigned short xs, ys, xe, ye;
+	v.xs = limit(v.xs - 1, vc->vc_cols - 1);
+	v.ys = limit(v.ys - 1, vc->vc_rows - 1);
+	v.xe = limit(v.xe - 1, vc->vc_cols - 1);
+	v.ye = limit(v.ye - 1, vc->vc_rows - 1);
+	ps = v.ys * vc->vc_size_row + (v.xs << 1);
+	pe = v.ye * vc->vc_size_row + (v.xe << 1);
 
-	  if (!access_ok(VERIFY_READ, sel, sizeof(*sel)))
-		return -EFAULT;
-	  __get_user(xs, &sel->xs);
-	  __get_user(ys, &sel->ys);
-	  __get_user(xe, &sel->xe);
-	  __get_user(ye, &sel->ye);
-	  __get_user(sel_mode, &sel->sel_mode);
-	  xs--; ys--; xe--; ye--;
-	  xs = limit(xs, vc->vc_cols - 1);
-	  ys = limit(ys, vc->vc_rows - 1);
-	  xe = limit(xe, vc->vc_cols - 1);
-	  ye = limit(ye, vc->vc_rows - 1);
-	  ps = ys * vc->vc_size_row + (xs << 1);
-	  pe = ye * vc->vc_size_row + (xe << 1);
-
-	  if (sel_mode == TIOCL_SELCLEAR) {
-	      /* useful for screendump without selection highlights */
-	      clear_selection();
-	      return 0;
-	  }
-
-	  if (mouse_reporting() && (sel_mode & TIOCL_SELMOUSEREPORT)) {
-	      mouse_report(tty, sel_mode & TIOCL_SELBUTTONMASK, xs, ys);
-	      return 0;
-	  }
-        }
+	if (v.sel_mode == TIOCL_SELCLEAR) {
+		/* useful for screendump without selection highlights */
+		clear_selection();
+		return 0;
+	}
+
+	if (mouse_reporting() && (v.sel_mode & TIOCL_SELMOUSEREPORT)) {
+		mouse_report(tty, v.sel_mode & TIOCL_SELBUTTONMASK, v.xs, v.ys);
+		return 0;
+	}
 
 	if (ps > pe)	/* make sel_start <= sel_end */
 	{
@@ -210,7 +202,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
 	else
 		use_unicode = 0;
 
-	switch (sel_mode)
+	switch (v.sel_mode)
 	{
 		case TIOCL_SELCHAR:	/* character-by-character selection */
 			new_sel_start = ps;
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 2d2b420598b2..d61be307256a 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -843,58 +843,44 @@ int vt_ioctl(struct tty_struct *tty,
 
 	case VT_RESIZEX:
 	{
-		struct vt_consize __user *vtconsize = up;
-		ushort ll,cc,vlin,clin,vcol,ccol;
+		struct vt_consize v;
 		if (!perm)
 			return -EPERM;
-		if (!access_ok(VERIFY_READ, vtconsize,
-				sizeof(struct vt_consize))) {
-			ret = -EFAULT;
-			break;
-		}
+		if (copy_from_user(&v, up, sizeof(struct vt_consize)))
+			return -EFAULT;
 		/* FIXME: Should check the copies properly */
-		__get_user(ll, &vtconsize->v_rows);
-		__get_user(cc, &vtconsize->v_cols);
-		__get_user(vlin, &vtconsize->v_vlin);
-		__get_user(clin, &vtconsize->v_clin);
-		__get_user(vcol, &vtconsize->v_vcol);
-		__get_user(ccol, &vtconsize->v_ccol);
-		vlin = vlin ? vlin : vc->vc_scan_lines;
-		if (clin) {
-			if (ll) {
-				if (ll != vlin/clin) {
-					/* Parameters don't add up */
-					ret = -EINVAL;
-					break;
-				}
-			} else 
-				ll = vlin/clin;
+		if (!v.v_vlin)
+			v.v_vlin = vc->vc_scan_lines;
+		if (v.v_clin) {
+			int rows = v.v_vlin/v.v_clin;
+			if (v.v_rows != rows) {
+				if (v.v_rows) /* Parameters don't add up */
+					return -EINVAL;
+				v.v_rows = rows;
+			}
 		}
-		if (vcol && ccol) {
-			if (cc) {
-				if (cc != vcol/ccol) {
-					ret = -EINVAL;
-					break;
-				}
-			} else
-				cc = vcol/ccol;
+		if (v.v_vcol && v.v_ccol) {
+			int cols = v.v_vcol/v.v_ccol;
+			if (v.v_cols != cols) {
+				if (v.v_cols)
+					return -EINVAL;
+				v.v_cols = cols;
+			}
 		}
 
-		if (clin > 32) {
-			ret =  -EINVAL;
-			break;
-		}
-		    
+		if (v.v_clin > 32)
+			return -EINVAL;
+
 		for (i = 0; i < MAX_NR_CONSOLES; i++) {
 			if (!vc_cons[i].d)
 				continue;
 			console_lock();
-			if (vlin)
-				vc_cons[i].d->vc_scan_lines = vlin;
-			if (clin)
-				vc_cons[i].d->vc_font.height = clin;
+			if (v.v_vlin)
+				vc_cons[i].d->vc_scan_lines = v.v_vlin;
+			if (v.v_clin)
+				vc_cons[i].d->vc_font.height = v.v_clin;
 			vc_cons[i].d->vc_resize_user = 1;
-			vc_resize(vc_cons[i].d, cc, ll);
+			vc_resize(vc_cons[i].d, v.v_cols, v.v_rows);
 			console_unlock();
 		}
 		break;