[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20191217221708.3730997-10-arnd@arndb.de>
Date: Tue, 17 Dec 2019 23:16:50 +0100
From: Arnd Bergmann <arnd@...db.de>
To: Jens Axboe <axboe@...nel.dk>,
"James E.J. Bottomley" <jejb@...ux.ibm.com>,
"Martin K. Petersen" <martin.petersen@...cle.com>
Cc: linux-scsi@...r.kernel.org, linux-block@...r.kernel.org,
y2038@...ts.linaro.org, linux-kernel@...r.kernel.org,
Christoph Hellwig <hch@....de>,
Ben Hutchings <ben.hutchings@...ethink.co.uk>,
linux-doc@...r.kernel.org, corbet@....net, viro@...iv.linux.org.uk,
linux-fsdevel@...r.kernel.org, Arnd Bergmann <arnd@...db.de>
Subject: [PATCH v2 09/27] 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.
Signed-off-by: Arnd Bergmann <arnd@...db.de>
---
block/ioctl.c | 21 +++++++++++++++++++++
include/linux/blkdev.h | 7 +++++++
2 files changed, 28 insertions(+)
diff --git a/block/ioctl.c b/block/ioctl.c
index 5de98b97af2a..e728331d1a5b 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/capability.h>
+#include <linux/compat.h>
#include <linux/blkdev.h>
#include <linux/export.h>
#include <linux/gfp.h>
@@ -285,6 +286,26 @@ int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
*/
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,
struct pr_registration __user *arg)
{
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 47eb22a3b7f9..3e0408618da7 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1711,6 +1711,13 @@ struct block_device_operations {
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,
unsigned long);
extern int bdev_read_page(struct block_device *, sector_t, struct page *);
--
2.20.0
Powered by blists - more mailing lists