Commit ee6a129d authored by Arnd Bergmann's avatar Arnd Bergmann

compat_ioctl: block: add blkdev_compat_ptr_ioctl

A lot of block drivers need only a trivial .compat_ioctl callback.

Add a helper function that can be set as the callback pointer
to only convert the argument using the compat_ptr() conversion
and otherwise assume all input and output data is compatible,
or handled using in_compat_syscall() checks.

This mirrors the compat_ptr_ioctl() helper function used in
character devices.
Reviewed-by: default avatarBen Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parent 78ed001d
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/compat.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/gfp.h> #include <linux/gfp.h>
...@@ -285,6 +286,26 @@ int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -285,6 +286,26 @@ int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
*/ */
EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl); EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl);
#ifdef CONFIG_COMPAT
/*
* This is the equivalent of compat_ptr_ioctl(), to be used by block
* drivers that implement only commands that are completely compatible
* between 32-bit and 64-bit user space
*/
int blkdev_compat_ptr_ioctl(struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long arg)
{
struct gendisk *disk = bdev->bd_disk;
if (disk->fops->ioctl)
return disk->fops->ioctl(bdev, mode, cmd,
(unsigned long)compat_ptr(arg));
return -ENOIOCTLCMD;
}
EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
#endif
static int blkdev_pr_register(struct block_device *bdev, static int blkdev_pr_register(struct block_device *bdev,
struct pr_registration __user *arg) struct pr_registration __user *arg)
{ {
......
...@@ -1711,6 +1711,13 @@ struct block_device_operations { ...@@ -1711,6 +1711,13 @@ struct block_device_operations {
const struct pr_ops *pr_ops; const struct pr_ops *pr_ops;
}; };
#ifdef CONFIG_COMPAT
extern int blkdev_compat_ptr_ioctl(struct block_device *, fmode_t,
unsigned int, unsigned long);
#else
#define blkdev_compat_ptr_ioctl NULL
#endif
extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int, extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int,
unsigned long); unsigned long);
extern int bdev_read_page(struct block_device *, sector_t, struct page *); extern int bdev_read_page(struct block_device *, sector_t, struct page *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment