summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Jones <davej@redhat.com>2005-05-13 23:31:19 -0400
committerGreg KH <gregkh@suse.de>2005-05-16 10:42:14 -0700
commit739b21c70fae430367c7617cb88548fe783ce24f (patch)
tree4874ca9b8bc470148e1ec9b9f89001da6d3f5000
parentb23b1dc851540dd0580251d98f6b9993779904e4 (diff)
downloadlinux-stable-739b21c70fae430367c7617cb88548fe783ce24f.tar.gz
linux-stable-739b21c70fae430367c7617cb88548fe783ce24f.tar.bz2
linux-stable-739b21c70fae430367c7617cb88548fe783ce24f.zip
[PATCH] Fix root hole in raw device
[Patch] Fix raw device ioctl pass-through Raw character devices are supposed to pass ioctls through to the block devices they are bound to. Unfortunately, they are using the wrong function for this: ioctl_by_bdev(), instead of blkdev_ioctl(). ioctl_by_bdev() performs a set_fs(KERNEL_DS) before calling the ioctl, redirecting the user-space buffer access to the kernel address space. This is, needless to say, a bad thing. This was noticed first on s390, where raw IO was non-functioning. The s390 driver config does not actually allow raw IO to be enabled, which was the first part of the problem. Secondly, the s390 kernel address space is distinct from user, causing legal raw ioctls to fail. I've reproduced this on a kernel built with 4G:4G split on x86, which fails in the same way (-EFAULT if the address does not exist kernel-side; returns success without actually populating the user buffer if it does.) The patch below fixes both the config and address-space problems. It's based closely on a patch by Jan Glauber <jang@de.ibm.com>, which has been tested on s390 at IBM. I've tested it on x86 4G:4G (split address space) and x86_64 (common address space). Kernel-address-space access has been assigned CAN-2005-1264. Signed-off-by: Stephen Tweedie <sct@redhat.com> Signed-off-by: Dave Jones <davej@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/block/ioctl.c2
-rw-r--r--drivers/char/raw.c2
2 files changed, 3 insertions, 1 deletions
diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c
index 5e03f5157ef9..6d7bcc9da9e7 100644
--- a/drivers/block/ioctl.c
+++ b/drivers/block/ioctl.c
@@ -237,3 +237,5 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
}
return ret;
}
+
+EXPORT_SYMBOL_GPL(blkdev_ioctl);
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index a2e33ec79615..131465e8de5a 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -122,7 +122,7 @@ raw_ioctl(struct inode *inode, struct file *filp,
{
struct block_device *bdev = filp->private_data;
- return ioctl_by_bdev(bdev, command, arg);
+ return blkdev_ioctl(bdev->bd_inode, filp, command, arg);
}
static void bind_device(struct raw_config_request *rq)