From patchwork Thu Jan 2 14:55:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315885 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1ECF314BD for ; Thu, 2 Jan 2020 14:58:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F1A122072C for ; Thu, 2 Jan 2020 14:58:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728599AbgABO6C (ORCPT ); Thu, 2 Jan 2020 09:58:02 -0500 Received: from mout.kundenserver.de ([212.227.126.133]:57085 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728544AbgABO6C (ORCPT ); Thu, 2 Jan 2020 09:58:02 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MLzSD-1j4yPT0dAv-00Hze6; Thu, 02 Jan 2020 15:57:46 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Al Viro , Douglas Gilbert , Steffen Maier , linux-scsi@vger.kernel.org, Jens Axboe , Chaitanya Kulkarni , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 03/22] compat: scsi: sg: fix v3 compat read/write interface Date: Thu, 2 Jan 2020 15:55:21 +0100 Message-Id: <20200102145552.1853992-4-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:nRc504jMOm3JteF2RHJQED6rMExyEXomIbEfWluQRtfGedaueYQ HSnicqYeOwDMEjGgqcf4j08q/sMz5sHGGLthM74HFeHngEPEkorJ45QatkmReK5HEnYGg0Q oLtQoQ+Cf1LpV37J0Pz07NhxUCOLR9IJXxJ2yqt8zUvjH6ItrQ9pvGsmV0x6jLpTq1PxO9/ ufsyhI+t4Svq5bNIPe5gg== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:BnXOhNwbfkU=:G4tQDXF/WQu5mAC+Qjokpr UzEnwTBWXbsWHaLla/qdLs2mW5qNgZFwTiUDd5DGbBe2SricT8IdiLgWGayPiowyVZtcGJO/P B6taIxfgDh2HALD87S/IQmx4wUXwYB1G2D74gIpPEfxtmCHHZ729sfiWkGsJ0hF+VTpRZwLz3 brfDXU+c7fPpl5WV8D/9dt1WEGMraFDU1geUYc+AtvT4hrluVjuHlrkKNgZzbOc+0+p0WNL+z K0l2aGuYpsEjy13CBPGhTjb3csc88TfTvTBoUANZ4/fXBArGyxir/jD59hg2kjLX6t7hLuaw8 qZi5DT3kG1FVW4VsbQa1noXXXr4pgEd/iVqU4lFSOeqfLhbZOnjkj4+7q/toElEx5/QoG6woP AZ9Fe8xbsqoeew7RyIMyhyHVXujjooBHbqe+MzgR6kKtVt0GIyk7V8LSliYgOhlWBhzEsNI9Y FdMd/eMbUjQCyCISrCrtTZqD2lX1Bh5LDLrosiISU0xar6BJe1iQgjUnhKidcO2sqw3KOxd0b h3dXVxLFB3qm4UZ0nZRaVCQAA6rrJw76q9BMg5EeccPRRWz9zB0B/6y8V7izQJdVqmRdTnE13 aLa4tQxm3nxcjMcHlJ90A8hQBoW5YQnbBN/z23+CSluU7B9fm0RusOc4zrQvUeUmAhIhgq6Ea fLiKLXSx9zXlxZfL8xm4lkePrfln4NDwecxDAka5J9x5vgPcH7qnFZ0hSnJTz9dwmOzz3zjRa nQ42O1hnRr37jL6KnlRFoiyyYbFOQxVShu7NJ7XGnDqCaoBek9uOp3bXYRMFsjmp0216Q4A2R vHWzGQAk4Oh06U6wzVfXf+fcOV4Yy7UZkWEIUUHWrSozyHsatqTsxDaIsvOkDKre1ioI3FqbN ZTQ6UcJF3QsKHHwZgbRQ== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org In the v5.4 merge window, a cleanup patch from Al Viro conflicted with my rework of the compat handling for sg.c read(). Linus Torvalds did a correct merge but pointed out that the resulting code is still unsatisfactory. I later noticed that the sg_new_read() function still gets the compat mode wrong, when the 'count' argument is large enough to pass a compat_sg_io_hdr object, but not a nativ sg_io_hdr. To address both of these, move the definition of compat_sg_io_hdr into a scsi/sg.h to make it visible to sg.c and rewrite the logic for reading req_pack_id as well as the size check to a simpler version that gets the expected results. Fixes: c35a5cfb4150 ("scsi: sg: sg_read(): simplify reading ->pack_id of userland sg_io_hdr_t") Fixes: 98aaaec4a150 ("compat_ioctl: reimplement SG_IO handling") Signed-off-by: Arnd Bergmann --- block/scsi_ioctl.c | 29 +---------- drivers/scsi/sg.c | 126 +++++++++++++++++++++------------------------ include/scsi/sg.h | 30 +++++++++++ 3 files changed, 90 insertions(+), 95 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 650bade5ea5a..b61dbf4d8443 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -20,6 +20,7 @@ #include #include #include +#include struct blk_cmd_filter { unsigned long read_ok[BLK_SCSI_CMD_PER_LONG]; @@ -550,34 +551,6 @@ static inline int blk_send_start_stop(struct request_queue *q, return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data); } -#ifdef CONFIG_COMPAT -struct compat_sg_io_hdr { - compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ - compat_int_t dxfer_direction; /* [i] data transfer direction */ - unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ - unsigned char mx_sb_len; /* [i] max length to write to sbp */ - unsigned short iovec_count; /* [i] 0 implies no scatter gather */ - compat_uint_t dxfer_len; /* [i] byte count of data transfer */ - compat_uint_t dxferp; /* [i], [*io] points to data transfer memory - or scatter gather list */ - compat_uptr_t cmdp; /* [i], [*i] points to command to perform */ - compat_uptr_t sbp; /* [i], [*o] points to sense_buffer memory */ - compat_uint_t timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ - compat_uint_t flags; /* [i] 0 -> default, see SG_FLAG... */ - compat_int_t pack_id; /* [i->o] unused internally (normally) */ - compat_uptr_t usr_ptr; /* [i->o] unused internally */ - unsigned char status; /* [o] scsi status */ - unsigned char masked_status; /* [o] shifted, masked scsi status */ - unsigned char msg_status; /* [o] messaging level data (optional) */ - unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ - unsigned short host_status; /* [o] errors from host adapter */ - unsigned short driver_status; /* [o] errors from software driver */ - compat_int_t resid; /* [o] dxfer_len - actual_transferred */ - compat_uint_t duration; /* [o] time taken by cmd (unit: millisec) */ - compat_uint_t info; /* [o] auxiliary information */ -}; -#endif - int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp) { #ifdef CONFIG_COMPAT diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 160748ad9c0f..eace8886d95a 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -405,6 +405,38 @@ sg_release(struct inode *inode, struct file *filp) return 0; } +static int get_sg_io_pack_id(int *pack_id, void __user *buf, size_t count) +{ + struct sg_header __user *old_hdr = buf; + int reply_len; + + if (count >= SZ_SG_HEADER) { + /* negative reply_len means v3 format, otherwise v1/v2 */ + if (get_user(reply_len, &old_hdr->reply_len)) + return -EFAULT; + + if (reply_len >= 0) + return get_user(*pack_id, &old_hdr->pack_id); + + if (in_compat_syscall() && + count >= sizeof(struct compat_sg_io_hdr)) { + struct compat_sg_io_hdr __user *hp = buf; + + return get_user(*pack_id, &hp->pack_id); + } + + if (count >= sizeof(struct sg_io_hdr)) { + struct sg_io_hdr __user *hp = buf; + + return get_user(*pack_id, &hp->pack_id); + } + } + + /* no valid header was passed, so ignore the pack_id */ + *pack_id = -1; + return 0; +} + static ssize_t sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) { @@ -413,8 +445,8 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) Sg_request *srp; int req_pack_id = -1; sg_io_hdr_t *hp; - struct sg_header *old_hdr = NULL; - int retval = 0; + struct sg_header *old_hdr; + int retval; /* * This could cause a response to be stranded. Close the associated @@ -429,79 +461,34 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, "sg_read: count=%d\n", (int) count)); - if (sfp->force_packid && (count >= SZ_SG_HEADER)) { - old_hdr = memdup_user(buf, SZ_SG_HEADER); - if (IS_ERR(old_hdr)) - return PTR_ERR(old_hdr); - if (old_hdr->reply_len < 0) { - if (count >= SZ_SG_IO_HDR) { - /* - * This is stupid. - * - * We're copying the whole sg_io_hdr_t from user - * space just to get the 'pack_id' field. But the - * field is at different offsets for the compat - * case, so we'll use "get_sg_io_hdr()" to copy - * the whole thing and convert it. - * - * We could do something like just calculating the - * offset based of 'in_compat_syscall()', but the - * 'compat_sg_io_hdr' definition is in the wrong - * place for that. - */ - sg_io_hdr_t *new_hdr; - new_hdr = kmalloc(SZ_SG_IO_HDR, GFP_KERNEL); - if (!new_hdr) { - retval = -ENOMEM; - goto free_old_hdr; - } - retval = get_sg_io_hdr(new_hdr, buf); - req_pack_id = new_hdr->pack_id; - kfree(new_hdr); - if (retval) { - retval = -EFAULT; - goto free_old_hdr; - } - } - } else - req_pack_id = old_hdr->pack_id; - } + if (sfp->force_packid) + retval = get_sg_io_pack_id(&req_pack_id, buf, count); + if (retval) + return retval; + srp = sg_get_rq_mark(sfp, req_pack_id); if (!srp) { /* now wait on packet to arrive */ - if (atomic_read(&sdp->detaching)) { - retval = -ENODEV; - goto free_old_hdr; - } - if (filp->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - goto free_old_hdr; - } + if (atomic_read(&sdp->detaching)) + return -ENODEV; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; retval = wait_event_interruptible(sfp->read_wait, (atomic_read(&sdp->detaching) || (srp = sg_get_rq_mark(sfp, req_pack_id)))); - if (atomic_read(&sdp->detaching)) { - retval = -ENODEV; - goto free_old_hdr; - } - if (retval) { + if (atomic_read(&sdp->detaching)) + return -ENODEV; + if (retval) /* -ERESTARTSYS as signal hit process */ - goto free_old_hdr; - } - } - if (srp->header.interface_id != '\0') { - retval = sg_new_read(sfp, buf, count, srp); - goto free_old_hdr; + return retval; } + if (srp->header.interface_id != '\0') + return sg_new_read(sfp, buf, count, srp); hp = &srp->header; - if (old_hdr == NULL) { - old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL); - if (! old_hdr) { - retval = -ENOMEM; - goto free_old_hdr; - } - } - memset(old_hdr, 0, SZ_SG_HEADER); + old_hdr = kzalloc(SZ_SG_HEADER, GFP_KERNEL); + if (!old_hdr) + return -ENOMEM; + old_hdr->reply_len = (int) hp->timeout; old_hdr->pack_len = old_hdr->reply_len; /* old, strange behaviour */ old_hdr->pack_id = hp->pack_id; @@ -575,7 +562,12 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) int err = 0, err2; int len; - if (count < SZ_SG_IO_HDR) { + if (in_compat_syscall()) { + if (count < sizeof(struct compat_sg_io_hdr)) { + err = -EINVAL; + goto err_out; + } + } else if (count < SZ_SG_IO_HDR) { err = -EINVAL; goto err_out; } diff --git a/include/scsi/sg.h b/include/scsi/sg.h index f91bcca604e4..29c7ad04d2e2 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h @@ -68,6 +68,36 @@ typedef struct sg_io_hdr unsigned int info; /* [o] auxiliary information */ } sg_io_hdr_t; /* 64 bytes long (on i386) */ +#if defined(__KERNEL__) +#include + +struct compat_sg_io_hdr { + compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ + compat_int_t dxfer_direction; /* [i] data transfer direction */ + unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + unsigned char mx_sb_len; /* [i] max length to write to sbp */ + unsigned short iovec_count; /* [i] 0 implies no scatter gather */ + compat_uint_t dxfer_len; /* [i] byte count of data transfer */ + compat_uint_t dxferp; /* [i], [*io] points to data transfer memory + or scatter gather list */ + compat_uptr_t cmdp; /* [i], [*i] points to command to perform */ + compat_uptr_t sbp; /* [i], [*o] points to sense_buffer memory */ + compat_uint_t timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ + compat_uint_t flags; /* [i] 0 -> default, see SG_FLAG... */ + compat_int_t pack_id; /* [i->o] unused internally (normally) */ + compat_uptr_t usr_ptr; /* [i->o] unused internally */ + unsigned char status; /* [o] scsi status */ + unsigned char masked_status; /* [o] shifted, masked scsi status */ + unsigned char msg_status; /* [o] messaging level data (optional) */ + unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ + unsigned short host_status; /* [o] errors from host adapter */ + unsigned short driver_status; /* [o] errors from software driver */ + compat_int_t resid; /* [o] dxfer_len - actual_transferred */ + compat_uint_t duration; /* [o] time taken by cmd (unit: millisec) */ + compat_uint_t info; /* [o] auxiliary information */ +}; +#endif + #define SG_INTERFACE_ID_ORIG 'S' /* Use negative values to flag difference from original sg_header structure */ From patchwork Thu Jan 2 14:55:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315891 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8A13D139A for ; Thu, 2 Jan 2020 14:58:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 72B8F20848 for ; Thu, 2 Jan 2020 14:58:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728559AbgABO6r (ORCPT ); Thu, 2 Jan 2020 09:58:47 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:38545 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728544AbgABO6q (ORCPT ); Thu, 2 Jan 2020 09:58:46 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1Ml6Zo-1jRu2Z2XTo-00lSv9; Thu, 02 Jan 2020 15:58:03 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" , Jens Axboe Cc: Arnd Bergmann , Jan Kara , Stefan Haberland , Dmitry Fomichev , Ajay Joshi , Damien Le Moal , Ming Lei , Chaitanya Kulkarni , Bart Van Assche , Pavel Begunkov , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 04/22] compat_ioctl: block: add blkdev_compat_ptr_ioctl Date: Thu, 2 Jan 2020 15:55:22 +0100 Message-Id: <20200102145552.1853992-5-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:KgLrTmywy3bbbvY0LZm/M628mSRoY/VIMuh4eTLrKVmXyt1GW9D qTf9qNpJ/r7gpch3KaMQdHvbCSK6zQjXj0kj1ywg/xU9Uk5+nwu+opKHMwpA36qU04BTioD HZfur8uZF/wduzz3V8sIdThEty5+pSYqtRa3D1yKuuaZuP45I5oMWpH2mNA4ppQZRbEO6K4 /U0HiGQxN0B3xuc4JwpPQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:owynCMj6ZB0=:dY43jbnMOLA/sdXkY9YXDt 3D3kgMLQNVE2RgFfOx7xc8a7esy4Fk42QCIElbKmzyZNWvodqHLKFx4ctaNvzwEx4QdbIlD/7 U5mBSqAfU0IFPgM0KznBV/Kt+5Dijw+iAR3saaWatbQwFh+KPONxqJwf9A/eCYD53+xYhcCPT eSF/ObWp06DdewxPFGVOSUZfnrkGWfFhXHLQl7vOeakoA59y8TU88Ksfl6GK+Qo90B0KGEmgy ejpLEkyNilqUY2xWsdhuxjdzaV6ghqW1GGNgUp1GKxtnsdAumOut2g5zTQNI+C5TPpzDQpNa0 vX4rtkdN2cAopgwRuCAE1CQY7JylXi1gUQ/QPZoKlerMe+Lv0V9O7/7Ra6e0wqehoXCEJXWTc N/7ojAA696jwWZv3Lygju4MbQysj87aBctHELqawOETtkZAB9bTuXZFwXIcj+bQ3kvgN9GSiG F16dgsTmc37bPg7XScURB2edDngbgkVdD6p0ZszQrtrhTsCxb1RTDDytfTwnKiaduP1UYIrKK HAhMXOup7KC+tUg3R/qdZsdLBlVr3HJoQ0MIW7M4h//vlOfRooJJ3TJRhd9iRVIfG2tSmHIRb z+RoSGIhvAtLLVsQCbO7lYabm919yTgWAg/+pYkBXR3d1fFIU+hqWFCKFd5nd8h0CUfnatQJv LBTi7IJGa43pxCfytY17FC34U2Iplp9vXiRImIwrNjUlDAWQpOHZZhp8DeJQf3Z/XE23m2Pg5 KGFberihYSRc8vkKrTyUIoONZ5V8R6DPUdRGmnhITcSq0q3zpcfLEtSbrUWpY7pWUmODhPKA8 1v0yzafUNyvPRH8jvHtL2i/QY5R4ZUJfUdT5s6J4DzukGwp1iEu4On0wPmyq+6HpMmpGNIeVW GZS+P8C4HMsApTc0z9lQ== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org 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 --- 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 +#include #include #include #include @@ -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 *); From patchwork Thu Jan 2 14:55:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315893 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BDC83139A for ; Thu, 2 Jan 2020 14:58:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A64D12072C for ; Thu, 2 Jan 2020 14:58:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728652AbgABO6t (ORCPT ); Thu, 2 Jan 2020 09:58:49 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:58161 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728544AbgABO6t (ORCPT ); Thu, 2 Jan 2020 09:58:49 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1M433w-1in1vY3uwi-0003Hv; Thu, 02 Jan 2020 15:58:21 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Jeff Dike , Richard Weinberger , Anton Ivanov , Justin Sanders , Jens Axboe , Daniel Walter , Alex Dewar , linux-um@lists.infradead.org, linux-kernel@vger.kernel.org, linux-block@vger.kernel.org Subject: [PATCH v3 05/22] compat_ioctl: ubd, aoe: use blkdev_compat_ptr_ioctl Date: Thu, 2 Jan 2020 15:55:23 +0100 Message-Id: <20200102145552.1853992-6-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:8p6BJLwWlOj4GvZq2jwHiMBi4e9jJiHHbTeRXtMc/ApbEdKhklc gKlW1NaJh90o2mvhxJRo47hmvCzaB15auzhfRK08JSJldtXQK+TFAbQnCnVZulkj5SogMn4 LfbZdloSdsbQbAhiQeotT/ZakSv8yylow0e+EApZlUEBrIppF2EzpE6WOgmXG/gLywQZxZx rjT/qfDnsWHma4CB8nMaA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:MrbTKH9MBv8=:tGOIcVKUd15dl5QCSnQhWi l92uQbcHjmyxlz3mrYVH+VEzMKjGo99LlZCaa00Cs9CW/8c1yR4TqOnAqtq2cyyTm7BydkDN3 M1oQrb3D0yzJNz2qT5vhX3uAaH9ELre7mNJf1lFrEaltKs9LrMdgZRFSTBKHTv0XwHoIhlFrK iAfucu65aHNau9imkICR//naYpZqEe9oJQsmFCqqC/NXNoZoEy0HdLC/zwDzcJxQr++0Ql1w7 OmyB01FdKfIB+dNOl9q4mUPgwSCJ2FF8GOI7rLsVEajQ3twqYGU532orIIbPP579kpe+vW6Wd 0UTU50Gqjbi3Rdb7hQIOoPue8RDQlEMCADDW1tijPnR+7ds73XPy+g8cy3nK1lgTPGntDwN4U w9nzLdHkPHMEbkIxd7zHVKlkHwJecfUC9u9xk4Y8PDzsJVnuVkSthxgVpw5j2b1lT7QAzLA3p MEBPOADTWWZwQjSFNVx4yflFSY0A+SzaTL7NlPJYWlyciQyUDWeKi3+wD5GIvBAi4GKCNRwL3 zWoZHo9QzmA2vj8e5m5I6i+17omfJdbjOcb8IJKcPC0vF7ZnuMluOIRnSvlSOJ2Dhc4xk8+qx DpCnZNOjGxjAAQOT/1dsbvbJD4T7byudIqLDyiiYxeZ5RIiZeHk0Vl/p0hK8pn06oKk1ZSIMb dW+VDrNJlVEVt21k5K7jrzRxpAY0n0AF41TdhraKf3lagtDcva/ON8ug0sirgQiezEBvcovUr pMDACkpS3KTrz8X6yZpRQlhYjuCAKlBRv8D8gk3191Z52wetwpvcQSfgE7bszS0A1ItxITQlj n5szWhlnByKP4I8KStDZLS1PXM/QlWPFNuHICr8hjXvzl7SKGhsHGE1BmVHcWsG6s8qFFncjK iNE5bzoy6IW09u5hSBow== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org These drivers implement the HDIO_GET_IDENTITY and CDROMVOLREAD ioctl commands, which are compatible between 32-bit and 64-bit user space and traditionally handled by compat_blkdev_driver_ioctl(). As a prerequisite to removing that function, make both drivers use blkdev_compat_ptr_ioctl() as their .compat_ioctl callback. Signed-off-by: Arnd Bergmann --- arch/um/drivers/ubd_kern.c | 1 + drivers/block/aoe/aoeblk.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 6627d7c30f37..582eb5b1f09b 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -113,6 +113,7 @@ static const struct block_device_operations ubd_blops = { .open = ubd_open, .release = ubd_release, .ioctl = ubd_ioctl, + .compat_ioctl = blkdev_compat_ptr_ioctl, .getgeo = ubd_getgeo, }; diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index bd19f8af950b..7b32fb673375 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -329,6 +329,7 @@ static const struct block_device_operations aoe_bdops = { .open = aoeblk_open, .release = aoeblk_release, .ioctl = aoeblk_ioctl, + .compat_ioctl = blkdev_compat_ptr_ioctl, .getgeo = aoeblk_getgeo, .owner = THIS_MODULE, }; From patchwork Thu Jan 2 14:55:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315911 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 711E9138C for ; Thu, 2 Jan 2020 15:01:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 45E1E2084D for ; Thu, 2 Jan 2020 15:01:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728572AbgABPBt (ORCPT ); Thu, 2 Jan 2020 10:01:49 -0500 Received: from mout.kundenserver.de ([212.227.126.131]:43503 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728571AbgABPBt (ORCPT ); Thu, 2 Jan 2020 10:01:49 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MgNMV-1jNDHv2yNj-00huQe; Thu, 02 Jan 2020 15:58:36 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Jens Axboe , linux-block@vger.kernel.org, Damien Le Moal , Chaitanya Kulkarni , Hannes Reinecke , Martin Wilck , linux-kernel@vger.kernel.org Subject: [PATCH v3 06/22] compat_ioctl: move CDROM_SEND_PACKET handling into scsi Date: Thu, 2 Jan 2020 15:55:24 +0100 Message-Id: <20200102145552.1853992-7-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:T0MtbbbNn4rNNb/Anyk65rw4LDZWytRlnVScu4W2i/Dg0nz4nlW pMqNaQCjZ7zhJDlD/BvC2guey0iURPwYaDKlZWmNNwucLt7t2s7CWwdnaJXO0qXRTJHUkir x+Wl2nqYmfKUrxFP/2/yeZYCEi+g4MYySOSGeyK7It38/Oz9W/WLrx7VsWCXCR4s6w/uQZ3 xbj1olaPsNfgXVf40KEHA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:xQDwJs3SNtw=:Ne6Q6kaaP4dZ0JUaNyZ3ZQ uiWUxURhTQxVkBo5lzD1fieHmGc5cG97RTyD0UDseP3tMra1DZKJGxMYfeCOMsH+PDt6q8kda dFjMxQ9EoiQK5I+8X+KjsXL1USg7TdDg34sN69L91oaKOBs6olqzre2AeQhviL+6jZ0+HgiX8 6aIRXOlqCmVRK4ysQWqgmmss0WUhRtPVv9kQ54U0Ce/3S5SF2wAVwwz1N8fVLKrpwWw1kr7d8 dAfgbRenlw0EUtg/tbDox6jMAtV9G2d7pL+yOZEo9CP/kxgMNZOdxk8FvwqCRBnsTGqspj3yc Qbv759INyyYhk7Kl0tjNqpOC6UmjeVex885Fyb6r2QxbomASej4g62F+lWg9VGcnEBewhPO3i QYveh9IG2dMTLSEPIqh8SFtLGOVG6SSA0lHv9cThoCDGXGQYAH/DPwdr5EErVwidCB0YojgdI eoYnfe52syeSyqkGWhPIg6Z2TrINcWWkWXJ/xsQ+65DKlFrGzD29geIs2Hytv7deVFWpwb+dZ t1VNNtovQuvSidVN/i37unQVZ/NhuSaTF+1jz73qZjqAz/GMknGDpaDDIeX4gPUpccnt6AEbY 66l66Dl8QkpP03Yk/SAMy2NjTdlNH4hJ3/b8qPPMTdmBWzT+DeROOq3/R/Jb+ZCARSoATOqVk YrDRYpz2ymfyVSHHHWZr+KceNcroJU52y3ExDnPj6UpdZVO9tKHcvx6VkpYxJimMSWHB9wXhS ZJsyNpAZx1cq3aZ7tiV+NNJRLQlOBioNwjXQApvoaVqxU/T2VhtGWUPQcvOUIGRxNlGFDlxj0 wdY3dfJOO4W0ej9yD5d6OgKo3g1aTh85nCt8b8k6BixJOWmca2aOh62RpKI90Hd+qJND1szYX iW77BYAmhF4uMmdXJYlg== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org There is only one implementation of this ioctl, so move the handling out of the common block layer code into the place where it's actually needed. It also gets called indirectly through pktcdvd, which needs to be aware of this change. As I noticed, the old implementation of the compat handler failed to convert the structure on the way out, so the updated fields never got written back to user space. This is either not important, or it has never worked and should be fixed now. Signed-off-by: Arnd Bergmann --- block/compat_ioctl.c | 47 +--------- block/scsi_ioctl.c | 185 ++++++++++++++++++++++++++++------------ drivers/block/pktcdvd.c | 6 +- 3 files changed, 135 insertions(+), 103 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 3ed7a0f144a9..e34203f7d1cf 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -103,18 +103,6 @@ struct compat_cdrom_read_audio { compat_caddr_t buf; }; -struct compat_cdrom_generic_command { - unsigned char cmd[CDROM_PACKET_SIZE]; - compat_caddr_t buffer; - compat_uint_t buflen; - compat_int_t stat; - compat_caddr_t sense; - unsigned char data_direction; - compat_int_t quiet; - compat_int_t timeout; - compat_caddr_t reserved[1]; -}; - static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { @@ -142,38 +130,6 @@ static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode, (unsigned long)cdread_audio); } -static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - struct cdrom_generic_command __user *cgc; - struct compat_cdrom_generic_command __user *cgc32; - u32 data; - unsigned char dir; - int itmp; - - cgc = compat_alloc_user_space(sizeof(*cgc)); - cgc32 = compat_ptr(arg); - - if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) || - get_user(data, &cgc32->buffer) || - put_user(compat_ptr(data), &cgc->buffer) || - copy_in_user(&cgc->buflen, &cgc32->buflen, - (sizeof(unsigned int) + sizeof(int))) || - get_user(data, &cgc32->sense) || - put_user(compat_ptr(data), &cgc->sense) || - get_user(dir, &cgc32->data_direction) || - put_user(dir, &cgc->data_direction) || - get_user(itmp, &cgc32->quiet) || - put_user(itmp, &cgc->quiet) || - get_user(itmp, &cgc32->timeout) || - put_user(itmp, &cgc->timeout) || - get_user(data, &cgc32->reserved[0]) || - put_user(compat_ptr(data), &cgc->reserved[0])) - return -EFAULT; - - return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc); -} - struct compat_blkpg_ioctl_arg { compat_int_t op; compat_int_t flags; @@ -225,8 +181,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, return compat_hdio_ioctl(bdev, mode, cmd, arg); case CDROMREADAUDIO: return compat_cdrom_read_audio(bdev, mode, cmd, arg); - case CDROM_SEND_PACKET: - return compat_cdrom_generic_command(bdev, mode, cmd, arg); /* * No handler required for the ones below, we just need to @@ -264,6 +218,7 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, case CDROM_DISC_STATUS: case CDROM_CHANGER_NSLOTS: case CDROM_GET_CAPABILITY: + case CDROM_SEND_PACKET: /* Ignore cdrom.h about these next 5 ioctls, they absolutely do * not take a struct cdrom_read, instead they take a struct cdrom_msf * which is compatible. diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index b61dbf4d8443..b4e73d5dd5c2 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -639,6 +639,136 @@ int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp) } EXPORT_SYMBOL(get_sg_io_hdr); +#ifdef CONFIG_COMPAT +struct compat_cdrom_generic_command { + unsigned char cmd[CDROM_PACKET_SIZE]; + compat_caddr_t buffer; + compat_uint_t buflen; + compat_int_t stat; + compat_caddr_t sense; + unsigned char data_direction; + compat_int_t quiet; + compat_int_t timeout; + compat_caddr_t reserved[1]; +}; +#endif + +static int scsi_get_cdrom_generic_arg(struct cdrom_generic_command *cgc, + const void __user *arg) +{ +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) { + struct compat_cdrom_generic_command cgc32; + + if (copy_from_user(&cgc32, arg, sizeof(cgc32))) + return -EFAULT; + + *cgc = (struct cdrom_generic_command) { + .buffer = compat_ptr(cgc32.buffer), + .buflen = cgc32.buflen, + .stat = cgc32.stat, + .sense = compat_ptr(cgc32.sense), + .data_direction = cgc32.data_direction, + .quiet = cgc32.quiet, + .timeout = cgc32.timeout, + .reserved[0] = compat_ptr(cgc32.reserved[0]), + }; + memcpy(&cgc->cmd, &cgc32.cmd, CDROM_PACKET_SIZE); + return 0; + } +#endif + if (copy_from_user(cgc, arg, sizeof(*cgc))) + return -EFAULT; + + return 0; +} + +static int scsi_put_cdrom_generic_arg(const struct cdrom_generic_command *cgc, + void __user *arg) +{ +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) { + struct compat_cdrom_generic_command cgc32 = { + .buffer = (uintptr_t)(cgc->buffer), + .buflen = cgc->buflen, + .stat = cgc->stat, + .sense = (uintptr_t)(cgc->sense), + .data_direction = cgc->data_direction, + .quiet = cgc->quiet, + .timeout = cgc->timeout, + .reserved[0] = (uintptr_t)(cgc->reserved[0]), + }; + memcpy(&cgc32.cmd, &cgc->cmd, CDROM_PACKET_SIZE); + + if (copy_to_user(arg, &cgc32, sizeof(cgc32))) + return -EFAULT; + + return 0; + } +#endif + if (copy_to_user(arg, cgc, sizeof(*cgc))) + return -EFAULT; + + return 0; +} + +static int scsi_cdrom_send_packet(struct request_queue *q, + struct gendisk *bd_disk, + fmode_t mode, void __user *arg) +{ + struct cdrom_generic_command cgc; + struct sg_io_hdr hdr; + int err; + + err = scsi_get_cdrom_generic_arg(&cgc, arg); + if (err) + return err; + + cgc.timeout = clock_t_to_jiffies(cgc.timeout); + memset(&hdr, 0, sizeof(hdr)); + hdr.interface_id = 'S'; + hdr.cmd_len = sizeof(cgc.cmd); + hdr.dxfer_len = cgc.buflen; + switch (cgc.data_direction) { + case CGC_DATA_UNKNOWN: + hdr.dxfer_direction = SG_DXFER_UNKNOWN; + break; + case CGC_DATA_WRITE: + hdr.dxfer_direction = SG_DXFER_TO_DEV; + break; + case CGC_DATA_READ: + hdr.dxfer_direction = SG_DXFER_FROM_DEV; + break; + case CGC_DATA_NONE: + hdr.dxfer_direction = SG_DXFER_NONE; + break; + default: + return -EINVAL; + } + + hdr.dxferp = cgc.buffer; + hdr.sbp = cgc.sense; + if (hdr.sbp) + hdr.mx_sb_len = sizeof(struct request_sense); + hdr.timeout = jiffies_to_msecs(cgc.timeout); + hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; + hdr.cmd_len = sizeof(cgc.cmd); + + err = sg_io(q, bd_disk, &hdr, mode); + if (err == -EFAULT) + return -EFAULT; + + if (hdr.status) + return -EIO; + + cgc.stat = err; + cgc.buflen = hdr.resid; + if (scsi_put_cdrom_generic_arg(&cgc, arg)) + return -EFAULT; + + return err; +} + int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mode, unsigned int cmd, void __user *arg) { @@ -689,60 +819,9 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod err = -EFAULT; break; } - case CDROM_SEND_PACKET: { - struct cdrom_generic_command cgc; - struct sg_io_hdr hdr; - - err = -EFAULT; - if (copy_from_user(&cgc, arg, sizeof(cgc))) - break; - cgc.timeout = clock_t_to_jiffies(cgc.timeout); - memset(&hdr, 0, sizeof(hdr)); - hdr.interface_id = 'S'; - hdr.cmd_len = sizeof(cgc.cmd); - hdr.dxfer_len = cgc.buflen; - err = 0; - switch (cgc.data_direction) { - case CGC_DATA_UNKNOWN: - hdr.dxfer_direction = SG_DXFER_UNKNOWN; - break; - case CGC_DATA_WRITE: - hdr.dxfer_direction = SG_DXFER_TO_DEV; - break; - case CGC_DATA_READ: - hdr.dxfer_direction = SG_DXFER_FROM_DEV; - break; - case CGC_DATA_NONE: - hdr.dxfer_direction = SG_DXFER_NONE; - break; - default: - err = -EINVAL; - } - if (err) - break; - - hdr.dxferp = cgc.buffer; - hdr.sbp = cgc.sense; - if (hdr.sbp) - hdr.mx_sb_len = sizeof(struct request_sense); - hdr.timeout = jiffies_to_msecs(cgc.timeout); - hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; - hdr.cmd_len = sizeof(cgc.cmd); - - err = sg_io(q, bd_disk, &hdr, mode); - if (err == -EFAULT) - break; - - if (hdr.status) - err = -EIO; - - cgc.stat = err; - cgc.buflen = hdr.resid; - if (copy_to_user(arg, &cgc, sizeof(cgc))) - err = -EFAULT; - + case CDROM_SEND_PACKET: + err = scsi_cdrom_send_packet(q, bd_disk, mode, arg); break; - } /* * old junk scsi send command ioctl diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 861fc65a1b75..ab4d3be4b646 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2671,15 +2671,13 @@ static int pkt_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned in case CDROMEJECT: case CDROMMULTISESSION: case CDROMREADTOCENTRY: + case CDROM_SEND_PACKET: /* compat mode handled in scsi_cmd_ioctl */ case SCSI_IOCTL_SEND_COMMAND: return pkt_ioctl(bdev, mode, cmd, (unsigned long)compat_ptr(arg)); - /* FIXME: no handler so far */ - case CDROM_LAST_WRITTEN: - /* handled in compat_blkdev_driver_ioctl */ - case CDROM_SEND_PACKET: default: + case CDROM_LAST_WRITTEN: return -ENOIOCTLCMD; } } From patchwork Thu Jan 2 14:55:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315895 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4FE7414B4 for ; Thu, 2 Jan 2020 14:59:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 369622072C for ; Thu, 2 Jan 2020 14:59:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728566AbgABO7c (ORCPT ); Thu, 2 Jan 2020 09:59:32 -0500 Received: from mout.kundenserver.de ([212.227.126.187]:60111 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728544AbgABO7c (ORCPT ); Thu, 2 Jan 2020 09:59:32 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MMoOy-1j3asu1Afs-00Ip7v; Thu, 02 Jan 2020 15:58:56 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Jens Axboe , Damien Le Moal , Mauro Carvalho Chehab , Jonathan Corbet , =?utf-8?q?Diego_Elio_Petten=C3=B2?= , Guenter Roeck , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 07/22] compat_ioctl: move CDROMREADADIO to cdrom.c Date: Thu, 2 Jan 2020 15:55:25 +0100 Message-Id: <20200102145552.1853992-8-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:yC0KphMQ1+jnKNs/TZQcxE6mhJ8DI2BYfsTPoVcbUgaeAslYM1E +kDeZqbUJadN1PpR9x8xf6D1wRqI76SYi4qPB8Pn5nQ5LVbniZIaEa5h5YVIDwT0GvC4BEc VSbWkOJMe6hAEy4xQ5Qilz8rsgyXx60SBBEXK2X/bPWP2D+3dyjKdrOdXgRD7sf+oCaeOSw MvEzObUZ8SGijvgCyrrGg== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:0LyknXyySuU=:QGnS3AemUqQiWwsUb3cQ/0 uuErWnUU23YRVY1fLesU2gdZctGhMViXl8+td7MXCS35Fk9iowBsTwHZRD80P/Hx91wyK6v/R 5nt5w2FQNTNwP8rgUFqVHjzku2BAMJPhyoj4KQ89HowsHYZim9Ldxo68o4b+8/XxWwNP2qkNz pnNUU8PuHd6PcfuanisY4QTXj6pk9A/67mABX40gtjRWMYddnOgA8uL1ZaY1kuwL6isZEs9Ki /JDLvt9IWDOIm7pYo7AKlFRW5383nr+mb+NrYM0uV3SU0412iMKKcAbkE97TDFif92HbVyfbc QeBy3LD2IZFHu3HFxT52awhYufiOTtQSgJkL1IPStQfWUl2JerUq9vcQqTMJt7I7UjOvtJuoL k9cqEqREoPTUgLY3Xq0QqnvxMjkCtihchOz6CHtpxNW763ZJjRC6zp7HZoQodID3Pea7pB4u2 FgbeWeX+xdwf/I9UXF87392pBu0Nx+xQGf4t6whI7RTSy/NmYlROtB/9vjp0TOXiQuNGETnqm SMYt86fggLGoYEV5V6T/9CQEweNSxvbqouK+e1KmGvCKKNXD719X8rhh0MqOJ9LS1k6+ZfAzz pCPwjiU2N9LigHlM0PyXlgoM2pwP+CYbRTy9jQMzn0k6fx97qiQOC+xlurx1PiiTFw33mJGvq bu1DrM1gKavMfJUn8yJIFWTaLVWvFLYfpaAFci+kzktY40ScAYUbMzdOmcGG827F/Q7FRK5ez 2SGBpPcAaSrLNUSqVjg1vLhmCixfxq+wUHqRYHK9FtXMk1/9LvZRmhhiBKISNVyRy5iXHiwln Yvd5ArmMtpq1/2599K8jgYBJvrinU6YiMZELyzXSRBdwPQ1kq7hc0beTn0IGb1XZDtNP9u6hn UW6qirvFHKQzVxCJVrJA== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Again, there is only one file that needs this, so move the conversion handler into the native implementation. Signed-off-by: Arnd Bergmann --- block/compat_ioctl.c | 36 ------------------------------------ drivers/cdrom/cdrom.c | 28 +++++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 39 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index e34203f7d1cf..91a5dcf6e36c 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -96,40 +96,6 @@ static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode, return error; } -struct compat_cdrom_read_audio { - union cdrom_addr addr; - u8 addr_format; - compat_int_t nframes; - compat_caddr_t buf; -}; - -static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - struct cdrom_read_audio __user *cdread_audio; - struct compat_cdrom_read_audio __user *cdread_audio32; - __u32 data; - void __user *datap; - - cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio)); - cdread_audio32 = compat_ptr(arg); - - if (copy_in_user(&cdread_audio->addr, - &cdread_audio32->addr, - (sizeof(*cdread_audio32) - - sizeof(compat_caddr_t)))) - return -EFAULT; - - if (get_user(data, &cdread_audio32->buf)) - return -EFAULT; - datap = compat_ptr(data); - if (put_user(datap, &cdread_audio->buf)) - return -EFAULT; - - return __blkdev_driver_ioctl(bdev, mode, cmd, - (unsigned long)cdread_audio); -} - struct compat_blkpg_ioctl_arg { compat_int_t op; compat_int_t flags; @@ -179,8 +145,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, case HDIO_GET_ADDRESS: case HDIO_GET_BUSSTATE: return compat_hdio_ioctl(bdev, mode, cmd, arg); - case CDROMREADAUDIO: - return compat_cdrom_read_audio(bdev, mode, cmd, arg); /* * No handler required for the ones below, we just need to diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index eebdcbef0578..48095025e588 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -3017,9 +3017,31 @@ static noinline int mmc_ioctl_cdrom_read_audio(struct cdrom_device_info *cdi, struct cdrom_read_audio ra; int lba; - if (copy_from_user(&ra, (struct cdrom_read_audio __user *)arg, - sizeof(ra))) - return -EFAULT; +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) { + struct compat_cdrom_read_audio { + union cdrom_addr addr; + u8 addr_format; + compat_int_t nframes; + compat_caddr_t buf; + } ra32; + + if (copy_from_user(&ra32, arg, sizeof(ra32))) + return -EFAULT; + + ra = (struct cdrom_read_audio) { + .addr = ra32.addr, + .addr_format = ra32.addr_format, + .nframes = ra32.nframes, + .buf = compat_ptr(ra32.buf), + }; + } else +#endif + { + if (copy_from_user(&ra, (struct cdrom_read_audio __user *)arg, + sizeof(ra))) + return -EFAULT; + } if (ra.addr_format == CDROM_MSF) lba = msf_to_lba(ra.addr.msf.minute, From patchwork Thu Jan 2 14:55:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315897 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C0A91139A for ; Thu, 2 Jan 2020 14:59:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A95D420848 for ; Thu, 2 Jan 2020 14:59:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728695AbgABO7p (ORCPT ); Thu, 2 Jan 2020 09:59:45 -0500 Received: from mout.kundenserver.de ([212.227.126.135]:60677 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728544AbgABO7p (ORCPT ); Thu, 2 Jan 2020 09:59:45 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1N49xZ-1jn8pu1q4X-0105tC; Thu, 02 Jan 2020 15:59:07 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , linux-block@vger.kernel.org, Jens Axboe , Hannes Reinecke , Martin Wilck , Jonathan Corbet , Mauro Carvalho Chehab , Guenter Roeck , =?utf-8?q?Diego_Elio_Petten=C3=B2?= , linux-kernel@vger.kernel.org Subject: [PATCH v3 08/22] compat_ioctl: cdrom: handle CDROM_LAST_WRITTEN Date: Thu, 2 Jan 2020 15:55:26 +0100 Message-Id: <20200102145552.1853992-9-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:IWmxlyxI1qDwOyVeMVL1WEG4Wr9pkXMYxQX0pGf2w844D03lneV mJ+v/3Zju8V9e+ypSQIdzA7JlLVZDaOpD4oA+aLLJN9iDnF3iB0zWPl9PwpeYIrAMzq1yxa 5emoGaoNRK+PsiIAybanfpyNDZr8DB0jz8KcocrzKhStdA5dDEwNZPLKWSS23HS5ffM/zEx gIpNBKqIzppGYrr3etarA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:1IH1nB+jcXY=:HSkthDNTH1sqo6kPxACiAN 31gKDaW2LonLFIknfehsDRwI8jCQ/x4+dX7A/MFQphAzpdmupNQosnyjmKgRL4oiTp5p2NZjw nWZM5IadK8L5/enUkP9N7fhF/NOxlF2y/tbPuUwa88yG7BrDDbb1T0W6GN/I5p7MFcHl66dKW AfwKqOSgSzIwg0KOSRKtBzMPsfavscLljV4oDfYcBknrpux5V7f22qySw3jSeidJ/I0SmW6h/ 6NpG4ZJLlOchf5vV0zQUkcUsOk+nECfl8ukIbXLTheGkeODX/8s8KwtFQr7P5Yykq+g4GV8iZ HDykSId0YwNcmn7nZTDKBPrqqRA7XMhoI9mwqTULGEGW+E0Y3Du2w6hgwwh23lOGt/iIN5thE MkCvBWqZZWYlWwvKdu3ZklZsEIe4Sst5fF3i6tdtKSZn1IlmX428IpmyIJj5jO3To0bd8WwOP 4k2NchSVuF5hYan2+nlikM+scEclYSg3LojcmKzh07wLR0tH1GESd7di1eseVp1U1FNUy8jwr iWz853oY0iPx4dbBhqYN+U+QS+y5UINZ3eo1JJ3cnT1eUZFJ4ALPBLpQvoYdZ5Od3SmB8tODS SptVWPTIJK6Sz5cartwYIZxoCjtoV35hvPQO7AKDWgMm8FsQ5RkmIZj8xjMqA+jIX3IPepPVq BlYkEIxNKghbtycuROaZazY42KOyi+bm53XovQgC0bgJmRtMBDLDY52cguuGRzFKUMIda/h/h 6ix+khD0ESk4QbdhJtmojUjUKpwkDQ93dLiNvqVbOk5637CxBE6EBLTSqw55Qd8CrJ2++GysO iHAm3iNRqDlNjDOSHir/6LmTkAobhf1E4VP8TJpS5q+6KqHFHo7+rFa9NO2DpUam4YdD0VVbN 96L9Bcrit/jRuaAjbsTQ== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org This is the only ioctl command that does not have a proper compat handler. Making the normal implementation do the right thing is actually very simply, so just do that by using an in_compat_syscall() check to avoid the special case in the pkcdvd driver. Signed-off-by: Arnd Bergmann --- drivers/block/pktcdvd.c | 24 +----------------------- drivers/cdrom/cdrom.c | 7 ++++--- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index ab4d3be4b646..5f970a7d32c0 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2663,26 +2663,6 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, return ret; } -#ifdef CONFIG_COMPAT -static int pkt_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - /* compatible */ - case CDROMEJECT: - case CDROMMULTISESSION: - case CDROMREADTOCENTRY: - case CDROM_SEND_PACKET: /* compat mode handled in scsi_cmd_ioctl */ - case SCSI_IOCTL_SEND_COMMAND: - return pkt_ioctl(bdev, mode, cmd, (unsigned long)compat_ptr(arg)); - - /* FIXME: no handler so far */ - default: - case CDROM_LAST_WRITTEN: - return -ENOIOCTLCMD; - } -} -#endif - static unsigned int pkt_check_events(struct gendisk *disk, unsigned int clearing) { @@ -2704,9 +2684,7 @@ static const struct block_device_operations pktcdvd_ops = { .open = pkt_open, .release = pkt_close, .ioctl = pkt_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = pkt_compat_ioctl, -#endif + .compat_ioctl = blkdev_compat_ptr_ioctl, .check_events = pkt_check_events, }; diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 48095025e588..faca0f346fff 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -3293,9 +3293,10 @@ static noinline int mmc_ioctl_cdrom_last_written(struct cdrom_device_info *cdi, ret = cdrom_get_last_written(cdi, &last); if (ret) return ret; - if (copy_to_user((long __user *)arg, &last, sizeof(last))) - return -EFAULT; - return 0; + if (in_compat_syscall()) + return put_user(last, (__s32 __user *)arg); + + return put_user(last, (long __user *)arg); } static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, From patchwork Thu Jan 2 14:55:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315899 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D736E139A for ; Thu, 2 Jan 2020 15:00:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C036F20848 for ; Thu, 2 Jan 2020 15:00:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728544AbgABPAA (ORCPT ); Thu, 2 Jan 2020 10:00:00 -0500 Received: from mout.kundenserver.de ([212.227.126.133]:38155 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728571AbgABPAA (ORCPT ); Thu, 2 Jan 2020 10:00:00 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MRC7g-1j80hl0TzQ-00NCqd; Thu, 02 Jan 2020 15:59:41 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Denis Efremov , Jens Axboe , Tim Waugh , Konrad Rzeszutek Wilk , =?utf-8?q?Roger_Pau_Monn?= =?utf-8?q?=C3=A9?= , Boris Ostrovsky , Juergen Gross , Stefano Stabellini , Mauro Carvalho Chehab , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, xen-devel@lists.xenproject.org Subject: [PATCH v3 09/22] compat_ioctl: block: handle cdrom compat ioctl in non-cdrom drivers Date: Thu, 2 Jan 2020 15:55:27 +0100 Message-Id: <20200102145552.1853992-10-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:wdBfmrr02CDq12M4nkT7pYNOf7/IjRYzD6XaAXcfqVJrqqMMGD4 Mj1RZUqzgSy3Zk9mHA3hDqTUTSPM2zyioOW8jhhA1emfYvfFwxO+++Pe9hS9QA4czZwQg6k 4MKhacs+eRa3ix03OK5bjf21w6KCI94uyIGo7K/HqOPIsCwIUA6+IKC9zLuD0yBNFu2gdqy nI8s23bcuYnMA59aKrR6g== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:vqvyIdRboDI=:4G6b2uAPholNj2UDYiYmio JDXbP4extzMTSJHJgAyBUUCyBnivB++pBb80Vcp87nHRYSpxu2qXNgFymOZpoQXAwlejNRI8w ba59u58QOcgD2QKRCt0jPhzU+N4dn/EBnBZiB09mZPCpuMdAmhx6KYdAzdzCl441XvV2bBhqy qyprK6D1Kc3S/A9ngV1tZ3cKUB/2ndb4cHtqSg6ajI3StbJFA75on6GaNbqOdul6R+JiODwVm Wvd6/wb+1tnKN7jyyMhrLM+gvjg57Ze+cwLOwa+Xv8TsumZYtuMsdvw6XPLMOekb4Pnw6ibY4 aYVXfZ24lB7yDNpF1z2eqx4wItOZxb4uN9DwVANPeXiBYgBCfYN3rj+ke2bU8975XxeCMLE99 kcPi6glqkmKk8dHxM9220A/YNhoJOuyg9f5jN7TxWIA1V2oXvG3MxdXbyx5YjipMJs6Y23nG7 jd/M3t8I0ck1nv/gn3/c51IYY66Mcggsz28Rn/3mV1f9yIrCGKGd4Aikip43xz40YZsXLkUhg MLwabVeTnSpKKlcDL4UvkdSAB+BjlnwpRtSTmBdMYN61wukrYTQXZs5UuxN5BcfnH+Zjdgkw1 ztwz+WhkzdS+maadwl1X2syIckfFIOStWau12zybQUEknzc9iCGfn6Q5f7QKvLIjmJYC42pBA nhOsEM+SgSh+DKojLrUhxVsZ1AwzMdUDp6UgIFJHIY47ugiqUCJD/MnVOJRkIOMpFE6QAg9xy uisF1/f5wpGcN9Lh5RA+fs4RDKg2dcXPkozJl3diLjS0apQhlkWBRBjkDdPuxAlBTujiuBZDm kH6M268ja7s+OktpaLNIl6o6/KCND2KWfDcgNPWNZ0BsU69eU2eQ+08k1NVyU9HDLb2phBonK ltQ8HA/kA1Rq2ZBOf41w== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Various block drivers implement the CDROMMULTISESSION, CDROM_GET_CAPABILITY, and CDROMEJECT ioctl commands, relying on the block layer to handle compat_ioctl mode for them. Move this into the drivers directly as a preparation for simplifying the block layer later. When only integer arguments or no arguments are passed, the same handler can be used for .ioctl and .compat_ioctl, and when only pointer arguments are passed, the newly added blkdev_compat_ptr_ioctl can be used. Signed-off-by: Arnd Bergmann --- drivers/block/floppy.c | 3 +++ drivers/block/paride/pd.c | 1 + drivers/block/paride/pf.c | 1 + drivers/block/sunvdc.c | 1 + drivers/block/xen-blkfront.c | 1 + 5 files changed, 7 insertions(+) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 485865fd0412..cd3612e4e2e1 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3879,6 +3879,9 @@ static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int { int drive = (long)bdev->bd_disk->private_data; switch (cmd) { + case CDROMEJECT: /* CD-ROM eject */ + case 0x6470: /* SunOS floppy eject */ + case FDMSGON: case FDMSGOFF: case FDSETEMSGTRESH: diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 6f9ad3fc716f..c0967507d085 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -874,6 +874,7 @@ static const struct block_device_operations pd_fops = { .open = pd_open, .release = pd_release, .ioctl = pd_ioctl, + .compat_ioctl = pd_ioctl, .getgeo = pd_getgeo, .check_events = pd_check_events, .revalidate_disk= pd_revalidate diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 6b7d4cab3687..bb09f21ce21a 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -276,6 +276,7 @@ static const struct block_device_operations pf_fops = { .open = pf_open, .release = pf_release, .ioctl = pf_ioctl, + .compat_ioctl = pf_ioctl, .getgeo = pf_getgeo, .check_events = pf_check_events, }; diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 571612e233fe..39aeebc6837d 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -171,6 +171,7 @@ static const struct block_device_operations vdc_fops = { .owner = THIS_MODULE, .getgeo = vdc_getgeo, .ioctl = vdc_ioctl, + .compat_ioctl = blkdev_compat_ptr_ioctl, }; static void vdc_blk_queue_start(struct vdc_port *port) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index c02be06c5299..57d50c5ba309 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -2632,6 +2632,7 @@ static const struct block_device_operations xlvbd_block_fops = .release = blkif_release, .getgeo = blkif_getgeo, .ioctl = blkif_ioctl, + .compat_ioctl = blkdev_compat_ptr_ioctl, }; From patchwork Thu Jan 2 14:55:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315901 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6DA37138C for ; Thu, 2 Jan 2020 15:00:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 55565217F4 for ; Thu, 2 Jan 2020 15:00:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728604AbgABPAh (ORCPT ); Thu, 2 Jan 2020 10:00:37 -0500 Received: from mout.kundenserver.de ([212.227.126.131]:60753 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728571AbgABPAh (ORCPT ); Thu, 2 Jan 2020 10:00:37 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MF3Y8-1iy5eq3Xmi-00FPMR; Thu, 02 Jan 2020 16:00:16 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , FUJITA Tomonori , Jens Axboe , Chaitanya Kulkarni , Benjamin Block , linux-scsi@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 11/22] compat_ioctl: bsg: add handler Date: Thu, 2 Jan 2020 15:55:29 +0100 Message-Id: <20200102145552.1853992-12-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:/v9BoeMw07nWpYw7u0vnyk6+iF7B9Ivx59/dmMOCA43quUma0Cb LvLgvdr6nk111g9XSXmi72uMA3v10UdDlFT1nwsCVEGt5vo6q0GP3uEay7CQEp+2Bjxbbej b5IDipv+F8eqFr46BmUUI2g8OckLtnPOxuymbLTcB38VCY3+aEVgccCWvTzb1jacfZOgcrF Bu9ksi0IpGAWcsPQAVeWA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:iJ1ciBf4Kro=:ulm3L4FFhXfpjGZ9FP2kXX GRP7BlD+CAPrLeiwd3yqbkPYqdhqc0xp7s0sA3FbN/gmBxw+t+lTsy/SJYTXKsrrhpByqoheF XNkLZkrdKF6VahgIPO4Wlv0JyZd4JbZnebYEPEyTVylSSP44jdggR60kll84/R92BiVUaGhfP 7H3f+mUkQeJZCo2uisJ9yL3khr7rM0mTRCPX0KzL3okPkjic6cWKN+EVU1EBs9c/fFYlHlBJZ R1Ol1e6FWQ2Ka/WINrAq3xpWSapauRQhPdFu3rcc98lfbXV2KYo5W+dn3OW0c38QMnu4gLPnz WxIRqTa2QgZgW2p4PMCdxQSKKLKIXvixbeHzbz/TZ8fjZqMgZXVVqE3J7PbYyf1wNdDLdlfFl IOee34z5uqxwApJ39i9waQVotAfHaZvgSDZxqjqzfyADFiW+c45Yz76ZD/SnQsWSuI8owcjLJ Ihq3f4J5ezbpzkzR1SFk/3DDNLbZlfQLpWWbMaHkh+bIvcn331kmD3GRjQtNXf/mrMXQEgb1S GMHSGRGFBW2hwQbOU+icy4JZSEIcIgdLCNXax3Nv0oFO0mgSq5BkfRLE1V6tkKiI/2CN4zU+M 7OIwKWiL9L2dcDDGRoH1dxkGjADNbVzSiuvPF4kyrVPWzO1zRzTmcVNoi5kK9BTKHOBJmnZKW AjZhcEvjyWQhAheRoL/Njj3+miFC/SDyoPIUMJX7bBKkUPxmdAQ8G6z12cfJsnXTU46ZTYeQz i5n6UaK6gDbVwv2vV7h+A/sWUzVobF/7R9vBjZcrlv9ztJQNApCXQTJNXR0FU1jZDluas4CtG f8PUD3qzSi6YAo/UhTqUVLk2r0jUy/SuDyt7eGYrQFXd+2n3PAW01OzGuVpmqkysmw3U5Pt1R /AZ4VVxCvjfMJEIpNo4g== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org bsg_ioctl() calls into scsi_cmd_ioctl() for a couple of generic commands and relies on fs/compat_ioctl.c to handle it correctly in compat mode. Adding a private compat_ioctl() handler avoids that round-trip and lets us get rid of the generic emulation once this is done. Note that bsg implements an SG_IO command that is different from the other drivers and does not need emulation. Signed-off-by: Arnd Bergmann --- block/bsg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/bsg.c b/block/bsg.c index 833c44b3d458..d7bae94b64d9 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -382,6 +382,7 @@ static const struct file_operations bsg_fops = { .open = bsg_open, .release = bsg_release, .unlocked_ioctl = bsg_ioctl, + .compat_ioctl = compat_ptr_ioctl, .owner = THIS_MODULE, .llseek = default_llseek, }; From patchwork Thu Jan 2 14:55:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315925 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 75F10138C for ; Thu, 2 Jan 2020 15:04:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5D71520848 for ; Thu, 2 Jan 2020 15:04:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728632AbgABPEM (ORCPT ); Thu, 2 Jan 2020 10:04:12 -0500 Received: from mout.kundenserver.de ([212.227.126.130]:47589 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728571AbgABPEL (ORCPT ); Thu, 2 Jan 2020 10:04:11 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MnJUy-1jU5yG242e-00jFzj; Thu, 02 Jan 2020 16:01:28 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , "Michael S. Tsirkin" , Jason Wang , Paolo Bonzini , Stefan Hajnoczi , Jens Axboe , Doug Gilbert , =?utf-8?q?Kai_M=C3=A4kisara?= , Alexander Viro , Dongli Zhang , Thomas Gleixner , Bart Van Assche , Hannes Reinecke , Damien Le Moal , John Garry , Martin Wilck , Heiko Carstens , "Gustavo A. R. Silva" , Ira Weiny , Iustin Pop , "Darrick J. Wong" , virtualization@lists.linux-foundation.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v3 13/22] compat_ioctl: scsi: move ioctl handling into drivers Date: Thu, 2 Jan 2020 15:55:31 +0100 Message-Id: <20200102145552.1853992-14-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:/e80zwdT+wTicn0NMZuh6AZ7aAB/UfmFnLijkeDZsj8gxRxFW5k N//+5PnYmCiu9NnLxiRRE0mJZsNb5V80V0Ex9rjoeqi05jIqFZUh7ziOTX1gQPinUT7BRpl jeZoob0rgUjez9ZHLn85pzbYf/4sEvUOCPWPa7vZZizKKCEb9w9+sVRqZzLRRJXjzvWZ0R9 cMqCviOyZOxSKDQ9baMYQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:x/Q6tmSDxu8=:OjjUVNa82AbH3RiNJYC9Xv mVO9b74kQFTgrYlXKNbSlG6Vs6Vo86LTUPlv7WUijUK9dAJWI30NUAICkIZeWWQDt4J8/G9/I rBiyU5BTmVPe9ZTaxtUKgYpGXr1BnqCVSpj7sb85DTv5pERnqhIthEtb8SjBT2U5W7k61RrOa ldAV9tfo8NkGWJnxXUe0hGwQJJwcjW/eRNwO6rXGiTGuu6RfJsdfw+p1HkjxjQjNJe+mhRrrA qQpNP4iMPELMR3BoMoZVSWDJrD4ltCbNQOHfR85DpIvWIsQW7EwwCeC/xk6fm4uXj8DX4q9U7 FMf0y/fMe7VWuVdULYRQ7qIHqiAqHxvSm0RvN/tziqyJLnu80Z/qK6/DIRDh7TwdeB3n2zpkN hQN4Tq8t/HP6CAmpo5DuqHZu+hADe0ktznB3OK/tc5TJwtET7m1UGsCiUqX3PKAj3wLv569uh o6XQjGR4upeSYjmR5idXvJ/L6/cShVxi7MsCE8AHbRiECso0UO6vgwgupC2uIajcZShqUQxQT oaTXT8hBNfNxUoqB9EgBgsFkcIcPR80Lqx73PsG/EkkDaJpyKx/6nQi6Ba5QToJIuOKfREgA8 aYWUSUEVWXR2d3EB8Soc1y8AQycGifnC+HDL3KfEHC8hq5rHSxtesh5QFjpA4GOREGY/GT/Sq nZk66EO/rPHdkPHpitzqWFE00YZE8ft9h8rGiDBM7xp+mP5g8sRWY9WUOexnpzUeEYJPx9LA5 GkFt3CagmES56AkxBD2bG69vytWcWvhj4XvwxUZ3siOohsKkXrTe5/Lf0EZjjbTDyDZytu5nr VdBBmsD+8jFaNJDY97oPQgDUR3ixrIB8ow5brQo2wbKZMST9Y76+MXU5pnKiAheYhoWYc809T ujWAXClkzLx9abc/N5Yg== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Each driver calling scsi_ioctl() gets an equivalent compat_ioctl() handler that implements the same commands by calling scsi_compat_ioctl(). The scsi_cmd_ioctl() and scsi_cmd_blk_ioctl() functions are compatible at this point, so any driver that calls those can do so for both native and compat mode, with the argument passed through compat_ptr(). With this, we can remove the entries from fs/compat_ioctl.c. The new code is larger, but should be easier to maintain and keep updated with newly added commands. Signed-off-by: Arnd Bergmann Acked-by: Stefan Hajnoczi --- drivers/block/virtio_blk.c | 3 + drivers/scsi/ch.c | 9 ++- drivers/scsi/sd.c | 50 ++++++-------- drivers/scsi/sg.c | 44 ++++++++----- drivers/scsi/sr.c | 57 ++++++++++++++-- drivers/scsi/st.c | 51 ++++++++------ fs/compat_ioctl.c | 132 +------------------------------------ 7 files changed, 142 insertions(+), 204 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 7ffd719d89de..fbbf18ac1d5d 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -405,6 +405,9 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) static const struct block_device_operations virtblk_fops = { .ioctl = virtblk_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = blkdev_compat_ptr_ioctl, +#endif .owner = THIS_MODULE, .getgeo = virtblk_getgeo, }; diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 76751d6c7f0d..ed5f4a6ae270 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -872,6 +872,10 @@ static long ch_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg) { scsi_changer *ch = file->private_data; + int retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd, + file->f_flags & O_NDELAY); + if (retval) + return retval; switch (cmd) { case CHIOGPARAMS: @@ -883,7 +887,7 @@ static long ch_ioctl_compat(struct file * file, case CHIOINITELEM: case CHIOSVOLTAG: /* compatible */ - return ch_ioctl(file, cmd, arg); + return ch_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); case CHIOGSTATUS32: { struct changer_element_status32 ces32; @@ -898,8 +902,7 @@ static long ch_ioctl_compat(struct file * file, return ch_gstatus(ch, ces32.ces_type, data); } default: - // return scsi_ioctl_compat(ch->device, cmd, (void*)arg); - return -ENOIOCTLCMD; + return scsi_compat_ioctl(ch->device, cmd, compat_ptr(arg)); } } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index cea625906440..5afb0046b12a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1465,13 +1465,12 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) * Note: most ioctls are forward onto the block subsystem or further * down in the scsi subsystem. **/ -static int sd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) +static int sd_ioctl_common(struct block_device *bdev, fmode_t mode, + unsigned int cmd, void __user *p) { struct gendisk *disk = bdev->bd_disk; struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; - void __user *p = (void __user *)arg; int error; SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, " @@ -1507,9 +1506,6 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, break; default: error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); - if (error != -ENOTTY) - break; - error = scsi_ioctl(sdp, cmd, p); break; } out: @@ -1691,39 +1687,31 @@ static void sd_rescan(struct device *dev) revalidate_disk(sdkp->disk); } +static int sd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + void __user *p = (void __user *)arg; + int ret; + + ret = sd_ioctl_common(bdev, mode, cmd, p); + if (ret != -ENOTTY) + return ret; + + return scsi_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p); +} #ifdef CONFIG_COMPAT -/* - * This gets directly called from VFS. When the ioctl - * is not recognized we go back to the other translation paths. - */ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { - struct gendisk *disk = bdev->bd_disk; - struct scsi_disk *sdkp = scsi_disk(disk); - struct scsi_device *sdev = sdkp->device; void __user *p = compat_ptr(arg); - int error; - - error = scsi_verify_blk_ioctl(bdev, cmd); - if (error < 0) - return error; + int ret; - error = scsi_ioctl_block_when_processing_errors(sdev, cmd, - (mode & FMODE_NDELAY) != 0); - if (error) - return error; + ret = sd_ioctl_common(bdev, mode, cmd, p); + if (ret != -ENOTTY) + return ret; - if (is_sed_ioctl(cmd)) - return sed_ioctl(sdkp->opal_dev, cmd, p); - - /* - * Let the static ioctl translation table take care of it. - */ - if (!sdev->host->hostt->compat_ioctl) - return -ENOIOCTLCMD; - return sdev->host->hostt->compat_ioctl(sdev, cmd, p); + return scsi_compat_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p); } #endif diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index eace8886d95a..bafeaf7b9ad8 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -911,19 +911,14 @@ static int put_compat_request_table(struct compat_sg_req_info __user *o, #endif static long -sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) +sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp, + unsigned int cmd_in, void __user *p) { - void __user *p = (void __user *)arg; int __user *ip = p; int result, val, read_only; - Sg_device *sdp; - Sg_fd *sfp; Sg_request *srp; unsigned long iflags; - if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) - return -ENXIO; - SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, "sg_ioctl: cmd=0x%x\n", (int) cmd_in)); read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); @@ -1146,29 +1141,44 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) cmd_in, filp->f_flags & O_NDELAY); if (result) return result; + + return -ENOIOCTLCMD; +} + +static long +sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) +{ + void __user *p = (void __user *)arg; + Sg_device *sdp; + Sg_fd *sfp; + int ret; + + if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) + return -ENXIO; + + ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p); + if (ret != -ENOIOCTLCMD) + return ret; + return scsi_ioctl(sdp->device, cmd_in, p); } #ifdef CONFIG_COMPAT static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) { + void __user *p = compat_ptr(arg); Sg_device *sdp; Sg_fd *sfp; - struct scsi_device *sdev; + int ret; if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - sdev = sdp->device; - if (sdev->host->hostt->compat_ioctl) { - int ret; - - ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); - + ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p); + if (ret != -ENOIOCTLCMD) return ret; - } - - return -ENOIOCTLCMD; + + return scsi_compat_ioctl(sdp->device, cmd_in, p); } #endif diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 4664fdf75c0f..6033a886c42c 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -598,6 +599,55 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, return ret; } +#ifdef CONFIG_COMPAT +static int sr_block_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, + unsigned long arg) +{ + struct scsi_cd *cd = scsi_cd(bdev->bd_disk); + struct scsi_device *sdev = cd->device; + void __user *argp = compat_ptr(arg); + int ret; + + mutex_lock(&sr_mutex); + + ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, + (mode & FMODE_NDELAY) != 0); + if (ret) + goto out; + + scsi_autopm_get_device(sdev); + + /* + * Send SCSI addressing ioctls directly to mid level, send other + * ioctls to cdrom/block level. + */ + switch (cmd) { + case SCSI_IOCTL_GET_IDLUN: + case SCSI_IOCTL_GET_BUS_NUMBER: + ret = scsi_compat_ioctl(sdev, cmd, argp); + goto put; + } + + /* + * CDROM ioctls are handled in the block layer, but + * do the scsi blk ioctls here. + */ + ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); + if (ret != -ENOTTY) + return ret; + + ret = scsi_compat_ioctl(sdev, cmd, argp); + +put: + scsi_autopm_put_device(sdev); + +out: + mutex_unlock(&sr_mutex); + return ret; + +} +#endif + static unsigned int sr_block_check_events(struct gendisk *disk, unsigned int clearing) { @@ -641,12 +691,11 @@ static const struct block_device_operations sr_bdops = .open = sr_block_open, .release = sr_block_release, .ioctl = sr_block_ioctl, +#ifdef CONFIG_COMPAT + .ioctl = sr_block_compat_ioctl, +#endif .check_events = sr_block_check_events, .revalidate_disk = sr_block_revalidate_disk, - /* - * No compat_ioctl for now because sr_block_ioctl never - * seems to pass arbitrary ioctls down to host drivers. - */ }; static int sr_open(struct cdrom_device_info *cdi, int purpose) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 9e3fff2de83e..393f3019ccac 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3501,7 +3501,7 @@ static int partition_tape(struct scsi_tape *STp, int size) /* The ioctl command */ -static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) +static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user *p) { int i, cmd_nr, cmd_type, bt; int retval = 0; @@ -3509,7 +3509,6 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) struct scsi_tape *STp = file->private_data; struct st_modedef *STm; struct st_partstat *STps; - void __user *p = (void __user *)arg; if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; @@ -3824,9 +3823,19 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) } mutex_unlock(&STp->lock); switch (cmd_in) { + case SCSI_IOCTL_STOP_UNIT: + /* unload */ + retval = scsi_ioctl(STp->device, cmd_in, p); + if (!retval) { + STp->rew_at_close = 0; + STp->ready = ST_NO_TAPE; + } + return retval; + case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: break; + default: if ((cmd_in == SG_IO || cmd_in == SCSI_IOCTL_SEND_COMMAND || @@ -3840,42 +3849,46 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) return i; break; } - retval = scsi_ioctl(STp->device, cmd_in, p); - if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { /* unload */ - STp->rew_at_close = 0; - STp->ready = ST_NO_TAPE; - } - return retval; + return -ENOTTY; out: mutex_unlock(&STp->lock); return retval; } +static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) +{ + void __user *p = (void __user *)arg; + struct scsi_tape *STp = file->private_data; + int ret; + + ret = st_ioctl_common(file, cmd_in, p); + if (ret != -ENOTTY) + return ret; + + return scsi_ioctl(STp->device, cmd_in, p); +} + #ifdef CONFIG_COMPAT static long st_compat_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) { void __user *p = compat_ptr(arg); struct scsi_tape *STp = file->private_data; - struct scsi_device *sdev = STp->device; - int ret = -ENOIOCTLCMD; + int ret; /* argument conversion is handled using put_user_mtpos/put_user_mtget */ switch (cmd_in) { - case MTIOCTOP: - return st_ioctl(file, MTIOCTOP, (unsigned long)p); case MTIOCPOS32: - return st_ioctl(file, MTIOCPOS, (unsigned long)p); + return st_ioctl_common(file, MTIOCPOS, p); case MTIOCGET32: - return st_ioctl(file, MTIOCGET, (unsigned long)p); + return st_ioctl_common(file, MTIOCGET, p); } - if (sdev->host->hostt->compat_ioctl) { + ret = st_ioctl_common(file, cmd_in, p); + if (ret != -ENOTTY) + return ret; - ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); - - } - return ret; + return scsi_compat_ioctl(STp->device, cmd_in, p); } #endif diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 358ea2ecf36b..ab4471f469e6 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -36,109 +36,11 @@ #include "internal.h" -#ifdef CONFIG_BLOCK -#include -#include -#include -#include -#include -#endif - #include #include #include - -#include - -/* - * simple reversible transform to make our table more evenly - * distributed after sorting. - */ -#define XFORM(i) (((i) ^ ((i) << 27) ^ ((i) << 17)) & 0xffffffff) - -#define COMPATIBLE_IOCTL(cmd) XFORM((u32)cmd), -static unsigned int ioctl_pointer[] = { -#ifdef CONFIG_BLOCK -/* Big S */ -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) -COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) -COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) -#endif -#ifdef CONFIG_BLOCK -/* SG stuff */ -COMPATIBLE_IOCTL(SG_IO) -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) -COMPATIBLE_IOCTL(SG_SET_TIMEOUT) -COMPATIBLE_IOCTL(SG_GET_TIMEOUT) -COMPATIBLE_IOCTL(SG_EMULATED_HOST) -COMPATIBLE_IOCTL(SG_GET_TRANSFORM) -COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_SCSI_ID) -COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) -COMPATIBLE_IOCTL(SG_GET_LOW_DMA) -COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) -COMPATIBLE_IOCTL(SG_SET_DEBUG) -COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) -COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) -COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) -COMPATIBLE_IOCTL(SG_SCSI_RESET) -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) -COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) -COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) -#endif -}; - -/* - * Convert common ioctl arguments based on their command number - * - * Please do not add any code in here. Instead, implement - * a compat_ioctl operation in the place that handleѕ the - * ioctl for the native case. - */ -static long do_ioctl_trans(unsigned int cmd, - unsigned long arg, struct file *file) -{ - return -ENOIOCTLCMD; -} - -static int compat_ioctl_check_table(unsigned int xcmd) -{ -#ifdef CONFIG_BLOCK - int i; - const int max = ARRAY_SIZE(ioctl_pointer) - 1; - - BUILD_BUG_ON(max >= (1 << 16)); - - /* guess initial offset into table, assuming a - normalized distribution */ - i = ((xcmd >> 16) * max) >> 16; - - /* do linear search up first, until greater or equal */ - while (ioctl_pointer[i] < xcmd && i < max) - i++; - - /* then do linear search down */ - while (ioctl_pointer[i] > xcmd && i > 0) - i--; - - return ioctl_pointer[i] == xcmd; -#else - return 0; -#endif -} - COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, compat_ulong_t, arg32) { @@ -216,19 +118,9 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, goto out_fput; } - if (!f.file->f_op->unlocked_ioctl) - goto do_ioctl; - break; - } - - if (compat_ioctl_check_table(XFORM(cmd))) - goto found_handler; - - error = do_ioctl_trans(cmd, arg, f.file); - if (error == -ENOIOCTLCMD) error = -ENOTTY; - - goto out_fput; + goto out_fput; + } found_handler: arg = (unsigned long)compat_ptr(arg); @@ -239,23 +131,3 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, out: return error; } - -static int __init init_sys32_ioctl_cmp(const void *p, const void *q) -{ - unsigned int a, b; - a = *(unsigned int *)p; - b = *(unsigned int *)q; - if (a > b) - return 1; - if (a < b) - return -1; - return 0; -} - -static int __init init_sys32_ioctl(void) -{ - sort(ioctl_pointer, ARRAY_SIZE(ioctl_pointer), sizeof(*ioctl_pointer), - init_sys32_ioctl_cmp, NULL); - return 0; -} -__initcall(init_sys32_ioctl); From patchwork Thu Jan 2 14:55:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315917 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0BF2D14B4 for ; Thu, 2 Jan 2020 15:03:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DEE55217F4 for ; Thu, 2 Jan 2020 15:03:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728714AbgABPDY (ORCPT ); Thu, 2 Jan 2020 10:03:24 -0500 Received: from mout.kundenserver.de ([212.227.126.187]:38279 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728571AbgABPDY (ORCPT ); Thu, 2 Jan 2020 10:03:24 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MJVY8-1j2VY31jlw-00Jvad; Thu, 02 Jan 2020 16:02:43 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Jens Axboe , Tim Waugh , Borislav Petkov , "David S. Miller" , Damien Le Moal , zhengbin , Hannes Reinecke , YueHaibing , Martin Wilck , Sergey Senozhatsky , Kefeng Wang , Mauro Carvalho Chehab , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org Subject: [PATCH v3 16/22] compat_ioctl: move cdrom commands into cdrom.c Date: Thu, 2 Jan 2020 15:55:34 +0100 Message-Id: <20200102145552.1853992-17-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:7HaNj+kg58AHuRufCpul7Uhfs08N+yeTpHJHjVcGayfYtYbvyK/ gPTfC9V0RX3Kh4qb5P9bESSKsqBmuS0QZeYKIFmBoCnu4tTgTjLk3R7+WbBhFt6kV0hxyY1 Jjso1mB8Kaykxnvjsdrvi8LSF+OW82GA9NtdSACP+37KgJ7QT2UD809QOiI7czN3j4kP3HW XNp6J1m4r7jDQV/3WWS8A== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:RE0c2PHyQfE=:ClFbXwEaGJkU0KS/r5Q+A/ eIyf/Q6YAnGOp2uglCpr1u8m4djz9Ezo7M8lfXZ1Kg3xgQPQzOJhpGFnt9P0YCX3nT9qrX4W8 tlXHEFsPDv2DsL+cOG4sAMD967fnicQYTji5yMEaK6LumDsyY+xMYC2a3B6kutmnkNKPiRzCM zaPzRGn7e7HrMwnK3BMGsWVwL8lzRHASVgNR5XKek8F20wSy0eQTxjSj20yBeMJgXGsh+OU5x aq7mYPxjrfQ34xawfAu3KHqlUebDGTX+fynFCRevnt5qFTIRMwC+48R50tKww1X9mAQabEaDs E6ka36s8cMLPWxcR7pgkL2aQSx9oGtRu0hwypIGVG93TG1KkrbJV4E5z+KwG6lTm/zOfoh9aF +2OxEW9FBlYephcGDutuk/+GR7ayUQ1/56jNOEGWiG94c9P2QnP5Q8uk1mdaXVFT3ovqoQNms eXsj1Cfm1HNZ4tQqYAXv/GcJa5LeDDNkbhJ6ESY+EyhvQClTB9DWGvLD04PlBwU/trVTFCOzP LGvljnJCQ8F8r0NKAe+QbqqFTD+AiwkJdcSbYSBefw04iyfZDNCO/3+XzmEXmbLXBCO7AUEwE hI6VWJXUwiMbWU6FPx/Xjf+khPFgqfnzcgLz1HnIL9BQAGcRfvpk0Zw6ljhQ+kceZSE6qDBxd BOhpcRRhweV57XZuxM9hfBINBXLSoMbDx1GSc55/4u520SxrvdqUbua79ZkZbzxlCnFMdlgDg d9zBaW7QINy13zc3lQbL6gW+FWUx8ZRHcJ3jTzQ3dOzpGh+U0JSbR16iXJsXfitJse6nvi2i1 QE6YyBQ0OOHbYPxKe315VC8j5h7TkmQYHNDJkxgMKjCbIDRJBbL1bxRFwVbiRjbuTXZOFJuTw N8FS7F4VdCsxqBkQwDWA== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org There is no need for the special cases for the cdrom ioctls any more now, so make sure that each cdrom driver has a .compat_ioctl() callback and calls cdrom_compat_ioctl() directly there. Signed-off-by: Arnd Bergmann --- block/compat_ioctl.c | 45 -------------------------------------- drivers/block/paride/pcd.c | 3 +++ drivers/cdrom/gdrom.c | 3 +++ drivers/ide/ide-cd.c | 37 +++++++++++++++++++++++++++++++ drivers/scsi/sr.c | 8 ++----- 5 files changed, 45 insertions(+), 51 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 91a5dcf6e36c..e1c5d07b09e5 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -160,42 +160,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, case HDIO_DRIVE_CMD: /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ case 0x330: - /* CDROM stuff */ - case CDROMPAUSE: - case CDROMRESUME: - case CDROMPLAYMSF: - case CDROMPLAYTRKIND: - case CDROMREADTOCHDR: - case CDROMREADTOCENTRY: - case CDROMSTOP: - case CDROMSTART: - case CDROMEJECT: - case CDROMVOLCTRL: - case CDROMSUBCHNL: - case CDROMMULTISESSION: - case CDROM_GET_MCN: - case CDROMRESET: - case CDROMVOLREAD: - case CDROMSEEK: - case CDROMPLAYBLK: - case CDROMCLOSETRAY: - case CDROM_DISC_STATUS: - case CDROM_CHANGER_NSLOTS: - case CDROM_GET_CAPABILITY: - case CDROM_SEND_PACKET: - /* Ignore cdrom.h about these next 5 ioctls, they absolutely do - * not take a struct cdrom_read, instead they take a struct cdrom_msf - * which is compatible. - */ - case CDROMREADMODE2: - case CDROMREADMODE1: - case CDROMREADRAW: - case CDROMREADCOOKED: - case CDROMREADALL: - /* DVD ioctls */ - case DVD_READ_STRUCT: - case DVD_WRITE_STRUCT: - case DVD_AUTH: arg = (unsigned long)compat_ptr(arg); /* These intepret arg as an unsigned long, not as a pointer, * so we must not do compat_ptr() conversion. */ @@ -211,15 +175,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, case HDIO_SET_ACOUSTIC: case HDIO_SET_BUSSTATE: case HDIO_SET_ADDRESS: - case CDROMEJECT_SW: - case CDROM_SET_OPTIONS: - case CDROM_CLEAR_OPTIONS: - case CDROM_SELECT_SPEED: - case CDROM_SELECT_DISC: - case CDROM_MEDIA_CHANGED: - case CDROM_DRIVE_STATUS: - case CDROM_LOCKDOOR: - case CDROM_DEBUG: break; default: /* unknown ioctl number */ diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 636bfea2de6f..117cfc8cd05a 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -275,6 +275,9 @@ static const struct block_device_operations pcd_bdops = { .open = pcd_block_open, .release = pcd_block_release, .ioctl = pcd_block_ioctl, +#ifdef CONFIG_COMPAT + .ioctl = blkdev_compat_ptr_ioctl, +#endif .check_events = pcd_block_check_events, }; diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 5b21dc421c94..886b2638c730 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -518,6 +518,9 @@ static const struct block_device_operations gdrom_bdops = { .release = gdrom_bdops_release, .check_events = gdrom_bdops_check_events, .ioctl = gdrom_bdops_ioctl, +#ifdef CONFIG_COMPAT + .ioctl = blkdev_compat_ptr_ioctl, +#endif }; static irqreturn_t gdrom_command_interrupt(int irq, void *dev_id) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 9d117936bee1..e09b949a7c46 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -25,6 +25,7 @@ #define IDECD_VERSION "5.00" +#include #include #include #include @@ -1710,6 +1711,39 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t mode, return ret; } +#ifdef CONFIG_COMPAT +static int idecd_locked_compat_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info); + void __user *argp = compat_ptr(arg); + int err; + + switch (cmd) { + case CDROMSETSPINDOWN: + return idecd_set_spindown(&info->devinfo, (unsigned long)argp); + case CDROMGETSPINDOWN: + return idecd_get_spindown(&info->devinfo, (unsigned long)argp); + default: + break; + } + + return cdrom_ioctl(&info->devinfo, bdev, mode, cmd, + (unsigned long)argp); +} + +static int idecd_compat_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret; + + mutex_lock(&ide_cd_mutex); + ret = idecd_locked_compat_ioctl(bdev, mode, cmd, arg); + mutex_unlock(&ide_cd_mutex); + + return ret; +} +#endif static unsigned int idecd_check_events(struct gendisk *disk, unsigned int clearing) @@ -1732,6 +1766,9 @@ static const struct block_device_operations idecd_ops = { .open = idecd_open, .release = idecd_release, .ioctl = idecd_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = idecd_compat_ioctl, +#endif .check_events = idecd_check_events, .revalidate_disk = idecd_revalidate_disk }; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index f1e7aab00ce3..0fbb8fe6e521 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -628,12 +628,8 @@ static int sr_block_compat_ioctl(struct block_device *bdev, fmode_t mode, unsign goto put; } - /* - * CDROM ioctls are handled in the block layer, but - * do the scsi blk ioctls here. - */ - ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); - if (ret != -ENOTTY) + ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, (unsigned long)argp); + if (ret != -ENOSYS) goto put; ret = scsi_compat_ioctl(sdev, cmd, argp); From patchwork Thu Jan 2 14:55:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315931 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B438B138C for ; Thu, 2 Jan 2020 15:04:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8928620848 for ; Thu, 2 Jan 2020 15:04:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728661AbgABPEf (ORCPT ); Thu, 2 Jan 2020 10:04:35 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:49789 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728735AbgABPEe (ORCPT ); Thu, 2 Jan 2020 10:04:34 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MvKGv-1jeJKC0t7p-00rKSo; Thu, 02 Jan 2020 16:04:01 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Jens Axboe , Borislav Petkov , "David S. Miller" , Damien Le Moal , Hannes Reinecke , Mauro Carvalho Chehab , Martin Wilck , Thomas Gleixner , Greg Kroah-Hartman , Heiko Carstens , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-ide@vger.kernel.org Subject: [PATCH v3 18/22] compat_ioctl: move HDIO ioctl handling into drivers/ide Date: Thu, 2 Jan 2020 15:55:36 +0100 Message-Id: <20200102145552.1853992-19-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:fkDBd9otlz69KCTrRhfhZnw2zKUhbJ5hsLRiiJ3x/MQRpXRm71q iOOGKEIaIdFfurKZAMM6afW4NASeEK+pRiREnjLF9xb1E6Fv4i2kYUqww+srpyINlXvaSrb ic0siKaTxIOU+bd+55/6/KXKAO6foDF5B3c7Ye/rZj53tyC6UB+LuqN7mKA3I2PE0OrL5WE GIcyTAu0zpx9NsGdZTYww== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:Rnc4i6anElQ=:DnrdUZwhJXRUJUE+ROE5Kv oX91nHmN0UJkeOYA2q3EHzBcNh8BX1uVbavaRXwfadfN4cgoFP3unzIh9lU1VUHTuh4NFNDyH UaerZ+JRZ4DbUoELoUt5BCDNtBrmoODrHFnX6w0R9U3nwiIYOqEXuE0DRyYXPMkufipeF7xqU cY87JsB92IL/critaJAVdk/ZMTOhYtWk/9vbM4MxCRQCcpIhEBSmx9CuksMqj8ha5W+GSDxRP z5Da6pfvxV2eDSYdkS9TUs2LawxTM7N3ZYWQxF8i4WXPtL+zmCfkJ6lrb2tbq44KnLjQn1Naz LLDvvYu3yz+hBFJbron893ud8v74nlru3/d+0bb94p4+RIL4DAUaNCjAL9568rGfy2UxDDUwD j410JUMrT3bQhtQ/l3wpi26XVgi6f7/I48TsvlS2ObKJQVyKAGcNuJShni7soBAIg+Z2sQR7t H+dimlhGn8/L0hGQhs6/t7IyNZ4uQb1eTbcf9+FZOufqzITpzyYhAD7Oy342ouV+M921ab3G8 yTT+qSWi0WCssVdO2nEjpVwGjhlsHCV+iMeEv/4eO1BcfT5W5KtUBWDFUMZ++CiT+3PX/Eqwv NfQEFgEste1OjqIU/HuTciJ6eFX32KeEwhT6BiDhxmBDoYwGIOg5BEmUyUlF+OjuWNbWs1VNZ Mh20vJhP+xplgOQhfZd4PgwylbZZ0i0zBSMFA7VOhUT3RpRgplft0IdtVF821ESCEEaim863V 74lnu8CFL0z80Qk55rU/lSoHo8W1fXl/GdF7fk/BsThShq3x1EOwGFneMnUm6MImz44yZdYrU 5fb6fLMRcHXQD7WjdNVywgvrLRbn/BsUSrfzz7PcRAEt0ljTZj1dDsT8s7KMNwGjntDAMQK+P CSkKNyEqhFYcOol+UeOA== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Most of the HDIO ioctls are only used by the obsolete drivers/ide subsystem, these can be handled by changing ide_cmd_ioctl() to be aware of compat mode and doing the correct transformations in place and using it as both native and compat handlers for all drivers. The SCSI drivers implementing the same commands are already doing this in the drivers, so the compat_blkdev_driver_ioctl() function is no longer needed now. The BLKSECTSET and HDIO_GETGEO_BIG ioctls are not implemented in any driver any more and no longer need any conversion. Signed-off-by: Arnd Bergmann --- block/compat_ioctl.c | 75 ---------------------------------- drivers/ide/ide-cd.c | 15 +++---- drivers/ide/ide-disk.c | 1 + drivers/ide/ide-floppy_ioctl.c | 7 ++-- drivers/ide/ide-ioctls.c | 47 +++++++++++++-------- drivers/ide/ide-tape.c | 11 +++++ 6 files changed, 54 insertions(+), 102 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index e1c5d07b09e5..928b917e692f 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -78,24 +78,6 @@ static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev, return ret; } -static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - unsigned long __user *p; - int error; - - p = compat_alloc_user_space(sizeof(unsigned long)); - error = __blkdev_driver_ioctl(bdev, mode, - cmd, (unsigned long)p); - if (error == 0) { - unsigned int __user *uvp = compat_ptr(arg); - unsigned long v; - if (get_user(v, p) || put_user(v, uvp)) - error = -EFAULT; - } - return error; -} - struct compat_blkpg_ioctl_arg { compat_int_t op; compat_int_t flags; @@ -129,61 +111,6 @@ static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) -static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, - unsigned cmd, unsigned long arg) -{ - switch (cmd) { - case HDIO_GET_UNMASKINTR: - case HDIO_GET_MULTCOUNT: - case HDIO_GET_KEEPSETTINGS: - case HDIO_GET_32BIT: - case HDIO_GET_NOWERR: - case HDIO_GET_DMA: - case HDIO_GET_NICE: - case HDIO_GET_WCACHE: - case HDIO_GET_ACOUSTIC: - case HDIO_GET_ADDRESS: - case HDIO_GET_BUSSTATE: - return compat_hdio_ioctl(bdev, mode, cmd, arg); - - /* - * No handler required for the ones below, we just need to - * convert arg to a 64 bit pointer. - */ - case BLKSECTSET: - /* - * 0x03 -- HD/IDE ioctl's used by hdparm and friends. - * Some need translations, these do not. - */ - case HDIO_GET_IDENTITY: - case HDIO_DRIVE_TASK: - case HDIO_DRIVE_CMD: - /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ - case 0x330: - arg = (unsigned long)compat_ptr(arg); - /* These intepret arg as an unsigned long, not as a pointer, - * so we must not do compat_ptr() conversion. */ - case HDIO_SET_MULTCOUNT: - case HDIO_SET_UNMASKINTR: - case HDIO_SET_KEEPSETTINGS: - case HDIO_SET_32BIT: - case HDIO_SET_NOWERR: - case HDIO_SET_DMA: - case HDIO_SET_PIO_MODE: - case HDIO_SET_NICE: - case HDIO_SET_WCACHE: - case HDIO_SET_ACOUSTIC: - case HDIO_SET_BUSSTATE: - case HDIO_SET_ADDRESS: - break; - default: - /* unknown ioctl number */ - return -ENOIOCTLCMD; - } - - return __blkdev_driver_ioctl(bdev, mode, cmd, arg); -} - /* Most of the generic ioctls are handled in the normal fallback path. This assumes the blkdev's low level compat_ioctl always returns ENOIOCTLCMD for unknown ioctls. */ @@ -294,8 +221,6 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) default: if (disk->fops->compat_ioctl) ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); - if (ret == -ENOIOCTLCMD) - ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg); return ret; } } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index e09b949a7c46..dcf8b51b47fd 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1711,7 +1711,6 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t mode, return ret; } -#ifdef CONFIG_COMPAT static int idecd_locked_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { @@ -1728,8 +1727,12 @@ static int idecd_locked_compat_ioctl(struct block_device *bdev, fmode_t mode, break; } - return cdrom_ioctl(&info->devinfo, bdev, mode, cmd, - (unsigned long)argp); + err = generic_ide_ioctl(info->drive, bdev, cmd, arg); + if (err == -EINVAL) + err = cdrom_ioctl(&info->devinfo, bdev, mode, cmd, + (unsigned long)argp); + + return err; } static int idecd_compat_ioctl(struct block_device *bdev, fmode_t mode, @@ -1743,7 +1746,6 @@ static int idecd_compat_ioctl(struct block_device *bdev, fmode_t mode, return ret; } -#endif static unsigned int idecd_check_events(struct gendisk *disk, unsigned int clearing) @@ -1766,9 +1768,8 @@ static const struct block_device_operations idecd_ops = { .open = idecd_open, .release = idecd_release, .ioctl = idecd_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = idecd_compat_ioctl, -#endif + .compat_ioctl = IS_ENABLED(CONFIG_COMPAT) ? + idecd_compat_ioctl : NULL, .check_events = idecd_check_events, .revalidate_disk = idecd_revalidate_disk }; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 197912af5c2f..1d3407d7e095 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -794,4 +794,5 @@ const struct ide_disk_ops ide_ata_disk_ops = { .set_doorlock = ide_disk_set_doorlock, .do_request = ide_do_rw_disk, .ioctl = ide_disk_ioctl, + .compat_ioctl = ide_disk_ioctl, }; diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c index 4fd70f804d6f..39a790ac6cc3 100644 --- a/drivers/ide/ide-floppy_ioctl.c +++ b/drivers/ide/ide-floppy_ioctl.c @@ -329,10 +329,9 @@ int ide_floppy_compat_ioctl(ide_drive_t *drive, struct block_device *bdev, if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND) err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); - /* - * there is no generic_ide_compat_ioctl(), that is handled - * through compat_blkdev_ioctl(). - */ + if (err == -ENOTTY) + err = generic_ide_ioctl(drive, bdev, cmd, arg); + out: mutex_unlock(&ide_floppy_ioctl_mutex); return err; diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index d48c17003874..09491098047b 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c @@ -3,11 +3,20 @@ * IDE ioctls handling. */ +#include #include #include #include #include +static int put_user_long(long val, unsigned long arg) +{ + if (in_compat_syscall()) + return put_user(val, (compat_long_t __user *)compat_ptr(arg)); + + return put_user(val, (long __user *)arg); +} + static const struct ide_ioctl_devset ide_ioctl_settings[] = { { HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit }, { HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, &ide_devset_keepsettings }, @@ -37,7 +46,7 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, mutex_lock(&ide_setting_mtx); err = ds->get(drive); mutex_unlock(&ide_setting_mtx); - return err >= 0 ? put_user(err, (long __user *)arg) : err; + return err >= 0 ? put_user_long(err, arg) : err; set_val: if (bdev != bdev->bd_contains) @@ -56,7 +65,7 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, EXPORT_SYMBOL_GPL(ide_setting_ioctl); static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, - unsigned long arg) + void __user *argp) { u16 *id = NULL; int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142; @@ -77,7 +86,7 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, memcpy(id, drive->id, size); ata_id_to_hd_driveid(id); - if (copy_to_user((void __user *)arg, id, size)) + if (copy_to_user(argp, id, size)) rc = -EFAULT; kfree(id); @@ -87,10 +96,10 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg) { - return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) + return put_user_long((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) << IDE_NICE_DSC_OVERLAP) | (!!(drive->dev_flags & IDE_DFLAG_NICE1) - << IDE_NICE_1), (long __user *)arg); + << IDE_NICE_1), arg); } static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) @@ -115,7 +124,7 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) return 0; } -static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) +static int ide_cmd_ioctl(ide_drive_t *drive, void __user *argp) { u8 *buf = NULL; int bufsize = 0, err = 0; @@ -123,7 +132,7 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) struct ide_cmd cmd; struct ide_taskfile *tf = &cmd.tf; - if (NULL == (void *) arg) { + if (NULL == argp) { struct request *rq; rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, 0); @@ -135,7 +144,7 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) return err; } - if (copy_from_user(args, (void __user *)arg, 4)) + if (copy_from_user(args, argp, 4)) return -EFAULT; memset(&cmd, 0, sizeof(cmd)); @@ -181,19 +190,18 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) args[1] = tf->error; args[2] = tf->nsect; abort: - if (copy_to_user((void __user *)arg, &args, 4)) + if (copy_to_user(argp, &args, 4)) err = -EFAULT; if (buf) { - if (copy_to_user((void __user *)(arg + 4), buf, bufsize)) + if (copy_to_user((argp + 4), buf, bufsize)) err = -EFAULT; kfree(buf); } return err; } -static int ide_task_ioctl(ide_drive_t *drive, unsigned long arg) +static int ide_task_ioctl(ide_drive_t *drive, void __user *p) { - void __user *p = (void __user *)arg; int err = 0; u8 args[7]; struct ide_cmd cmd; @@ -237,6 +245,10 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev, unsigned int cmd, unsigned long arg) { int err; + void __user *argp = (void __user *)arg; + + if (in_compat_syscall()) + argp = compat_ptr(arg); err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings); if (err != -EOPNOTSUPP) @@ -247,7 +259,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev, case HDIO_GET_IDENTITY: if (bdev != bdev->bd_contains) return -EINVAL; - return ide_get_identity_ioctl(drive, cmd, arg); + return ide_get_identity_ioctl(drive, cmd, argp); case HDIO_GET_NICE: return ide_get_nice_ioctl(drive, arg); case HDIO_SET_NICE: @@ -258,6 +270,9 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev, case HDIO_DRIVE_TASKFILE: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; + /* missing compat handler for HDIO_DRIVE_TASKFILE */ + if (in_compat_syscall()) + return -ENOTTY; if (drive->media == ide_disk) return ide_taskfile_ioctl(drive, arg); return -ENOMSG; @@ -265,11 +280,11 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev, case HDIO_DRIVE_CMD: if (!capable(CAP_SYS_RAWIO)) return -EACCES; - return ide_cmd_ioctl(drive, arg); + return ide_cmd_ioctl(drive, argp); case HDIO_DRIVE_TASK: if (!capable(CAP_SYS_RAWIO)) return -EACCES; - return ide_task_ioctl(drive, arg); + return ide_task_ioctl(drive, argp); case HDIO_DRIVE_RESET: if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -277,7 +292,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev, case HDIO_GET_BUSSTATE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (put_user(BUSSTATE_ON, (long __user *)arg)) + if (put_user_long(BUSSTATE_ON, arg)) return -EFAULT; return 0; case HDIO_SET_BUSSTATE: diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 3e7482695f77..6f26634b22bb 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1945,11 +1945,22 @@ static int idetape_ioctl(struct block_device *bdev, fmode_t mode, return err; } +static int idetape_compat_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + if (cmd == 0x0340 || cmd == 0x350) + arg = (unsigned long)compat_ptr(arg); + + return idetape_ioctl(bdev, mode, cmd, arg); +} + static const struct block_device_operations idetape_block_ops = { .owner = THIS_MODULE, .open = idetape_open, .release = idetape_release, .ioctl = idetape_ioctl, + .compat_ioctl = IS_ENABLED(CONFIG_COMPAT) ? + idetape_compat_ioctl : NULL, }; static int ide_tape_probe(ide_drive_t *drive) From patchwork Thu Jan 2 14:55:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315927 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 944A417EA for ; Thu, 2 Jan 2020 15:04:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5F817217F4 for ; Thu, 2 Jan 2020 15:04:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728571AbgABPEa (ORCPT ); Thu, 2 Jan 2020 10:04:30 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:45177 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728636AbgABPE3 (ORCPT ); Thu, 2 Jan 2020 10:04:29 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MWzwP-1jG2Br20ZF-00XLic; Thu, 02 Jan 2020 16:04:14 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Jens Axboe , Tejun Heo , Damien Le Moal , Jan Kara , Keith Busch , Dmitry Fomichev , Ajay Joshi , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 19/22] compat_ioctl: block: move blkdev_compat_ioctl() into ioctl.c Date: Thu, 2 Jan 2020 15:55:37 +0100 Message-Id: <20200102145552.1853992-20-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:AobWlplSlA2Whov09irGofZvBKo5W2XbOTAhppGoB4oy1w5jBuD OWmackwyrf5Kem8ektCbYUf29P5KoHwn63WLrQhMGpz3vRPi13fUgyDduV2OSpkrbxCuWrD 9bu3b67TlKPrSkhH4q71WANR6b9hJ0BGHR5rJQZsoFaCtl1A68BYkpO8k1gKzIFIkz/BGWz 9tmL4U0gUw2C+AEwjKKcA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:vlIXjwMN2sA=:DA3+nAEFxoDYj+8AxiiHQk SbtxJEaaKVJspxg0wDZ6iObIYdSyYdDuI1xMc/tAyEeo6IBiRf3ysOGNBdeInRtqcH4O5C1AU z3u2+xKsBPsOymUtNaJfIxGMlAXnMDFoSYObU59hNzf3lLN5kozASidlpfU1qhDPNZrUhbjWy qO3gRR4YMQSPrha+PoGcstu85IHHsiWvWodZCrasSi+60Cr8B3Toj02XOR3O0btbbAMNSRFMX JRo5yOPILm6m5+kiPLxNu/zU0Y3k1gVEWLwuQ+y8Lkb+vWOlWGpe1nusAhUsLG9NvO55Me6MW qqoXaABaQEpxhVr/3lOC+ul4tzqmVLhHfftxHZR82s9h3+kKtA9zMPmoeY7N8mxQ7R15GFATc M4S9A1F3vXOi2Fj3nNUtisgV2kNgBVyzrMGofvQzwpraG9z3ozl/koKZCaQb+8waMLf/vtko6 I1+NeQDbz0nKV4Ncy2LwmBdDzNdBG11xN1AfkuuSouRc1lTfBjxltFJCanYxaHHJ0y/PpZjB9 Xz5eNV3zdDChK9aLuucPzFFHWk2z7GUJ6bMKwvzN0uwe5C4GhFqnyZzkMB1e/mpZDCqnwHZS5 JW6r0mfU2B9GH1+BXOUcjUndVV8XXNyeq9M8bK/Fdz7po8IiOlB8ez8QU8vkw2yxl5Pj5+ew0 ziOASaFpgOBtSzj4MEnCO7vHPL54bWZXp8KiS4vHa4o4Y6Da4caLKQS0BQwIj2+Dx8aaGYMCA BcG0IHY+avn2+qHFwc4RID5K5Ru8mBpwxpcyuAvkibNt8eBJOmjbLVgutzYKy+34iNSARmzZv LKwYVm3mqySwSGG1637fdO6xw6uhEcmISw5qRPmbswQ17JiJ4GjoORu0BWpERVE3DVUVCp9RF 4Hk+4r/8ZjphFLbH3pFA== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Having both in the same file allows a number of simplifications to the compat path, and makes it more likely that changes to the native path get applied to the compat version as well. Signed-off-by: Arnd Bergmann --- block/Makefile | 1 - block/compat_ioctl.c | 226 ------------------------------------------- block/ioctl.c | 219 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 219 insertions(+), 227 deletions(-) delete mode 100644 block/compat_ioctl.c diff --git a/block/Makefile b/block/Makefile index 205a5f2fef17..1f70c73ea83d 100644 --- a/block/Makefile +++ b/block/Makefile @@ -25,7 +25,6 @@ obj-$(CONFIG_MQ_IOSCHED_KYBER) += kyber-iosched.o bfq-y := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o obj-$(CONFIG_IOSCHED_BFQ) += bfq.o -obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o obj-$(CONFIG_BLK_MQ_PCI) += blk-mq-pci.o diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c deleted file mode 100644 index 928b917e692f..000000000000 --- a/block/compat_ioctl.c +++ /dev/null @@ -1,226 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int compat_put_ushort(unsigned long arg, unsigned short val) -{ - return put_user(val, (unsigned short __user *)compat_ptr(arg)); -} - -static int compat_put_int(unsigned long arg, int val) -{ - return put_user(val, (compat_int_t __user *)compat_ptr(arg)); -} - -static int compat_put_uint(unsigned long arg, unsigned int val) -{ - return put_user(val, (compat_uint_t __user *)compat_ptr(arg)); -} - -static int compat_put_long(unsigned long arg, long val) -{ - return put_user(val, (compat_long_t __user *)compat_ptr(arg)); -} - -static int compat_put_ulong(unsigned long arg, compat_ulong_t val) -{ - return put_user(val, (compat_ulong_t __user *)compat_ptr(arg)); -} - -static int compat_put_u64(unsigned long arg, u64 val) -{ - return put_user(val, (compat_u64 __user *)compat_ptr(arg)); -} - -struct compat_hd_geometry { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - u32 start; -}; - -static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev, - struct compat_hd_geometry __user *ugeo) -{ - struct hd_geometry geo; - int ret; - - if (!ugeo) - return -EINVAL; - if (!disk->fops->getgeo) - return -ENOTTY; - - memset(&geo, 0, sizeof(geo)); - /* - * We need to set the startsect first, the driver may - * want to override it. - */ - geo.start = get_start_sect(bdev); - ret = disk->fops->getgeo(bdev, &geo); - if (ret) - return ret; - - ret = copy_to_user(ugeo, &geo, 4); - ret |= put_user(geo.start, &ugeo->start); - if (ret) - ret = -EFAULT; - - return ret; -} - -struct compat_blkpg_ioctl_arg { - compat_int_t op; - compat_int_t flags; - compat_int_t datalen; - compat_caddr_t data; -}; - -static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) -{ - struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); - compat_caddr_t udata; - compat_int_t n; - int err; - - err = get_user(n, &ua32->op); - err |= put_user(n, &a->op); - err |= get_user(n, &ua32->flags); - err |= put_user(n, &a->flags); - err |= get_user(n, &ua32->datalen); - err |= put_user(n, &a->datalen); - err |= get_user(udata, &ua32->data); - err |= put_user(compat_ptr(udata), &a->data); - if (err) - return err; - - return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a); -} - -#define BLKBSZGET_32 _IOR(0x12, 112, int) -#define BLKBSZSET_32 _IOW(0x12, 113, int) -#define BLKGETSIZE64_32 _IOR(0x12, 114, int) - -/* Most of the generic ioctls are handled in the normal fallback path. - This assumes the blkdev's low level compat_ioctl always returns - ENOIOCTLCMD for unknown ioctls. */ -long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) -{ - int ret = -ENOIOCTLCMD; - struct inode *inode = file->f_mapping->host; - struct block_device *bdev = inode->i_bdev; - struct gendisk *disk = bdev->bd_disk; - fmode_t mode = file->f_mode; - loff_t size; - unsigned int max_sectors; - - /* - * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have - * to updated it before every ioctl. - */ - if (file->f_flags & O_NDELAY) - mode |= FMODE_NDELAY; - else - mode &= ~FMODE_NDELAY; - - switch (cmd) { - case HDIO_GETGEO: - return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); - case BLKPBSZGET: - return compat_put_uint(arg, bdev_physical_block_size(bdev)); - case BLKIOMIN: - return compat_put_uint(arg, bdev_io_min(bdev)); - case BLKIOOPT: - return compat_put_uint(arg, bdev_io_opt(bdev)); - case BLKALIGNOFF: - return compat_put_int(arg, bdev_alignment_offset(bdev)); - case BLKDISCARDZEROES: - return compat_put_uint(arg, 0); - case BLKFLSBUF: - case BLKROSET: - case BLKDISCARD: - case BLKSECDISCARD: - case BLKZEROOUT: - /* - * the ones below are implemented in blkdev_locked_ioctl, - * but we call blkdev_ioctl, which gets the lock for us - */ - case BLKRRPART: - case BLKREPORTZONE: - case BLKRESETZONE: - case BLKOPENZONE: - case BLKCLOSEZONE: - case BLKFINISHZONE: - case BLKGETZONESZ: - case BLKGETNRZONES: - return blkdev_ioctl(bdev, mode, cmd, - (unsigned long)compat_ptr(arg)); - case BLKBSZSET_32: - return blkdev_ioctl(bdev, mode, BLKBSZSET, - (unsigned long)compat_ptr(arg)); - case BLKPG: - return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg)); - case BLKRAGET: - case BLKFRAGET: - if (!arg) - return -EINVAL; - return compat_put_long(arg, - (bdev->bd_bdi->ra_pages * PAGE_SIZE) / 512); - case BLKROGET: /* compatible */ - return compat_put_int(arg, bdev_read_only(bdev) != 0); - case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */ - return compat_put_int(arg, block_size(bdev)); - case BLKSSZGET: /* get block device hardware sector size */ - return compat_put_int(arg, bdev_logical_block_size(bdev)); - case BLKSECTGET: - max_sectors = min_t(unsigned int, USHRT_MAX, - queue_max_sectors(bdev_get_queue(bdev))); - return compat_put_ushort(arg, max_sectors); - case BLKROTATIONAL: - return compat_put_ushort(arg, - !blk_queue_nonrot(bdev_get_queue(bdev))); - case BLKRASET: /* compatible, but no compat_ptr (!) */ - case BLKFRASET: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE; - return 0; - case BLKGETSIZE: - size = i_size_read(bdev->bd_inode); - if ((size >> 9) > ~0UL) - return -EFBIG; - return compat_put_ulong(arg, size >> 9); - - case BLKGETSIZE64_32: - return compat_put_u64(arg, i_size_read(bdev->bd_inode)); - - case BLKTRACESETUP32: - case BLKTRACESTART: /* compatible */ - case BLKTRACESTOP: /* compatible */ - case BLKTRACETEARDOWN: /* compatible */ - ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); - return ret; - case IOC_PR_REGISTER: - case IOC_PR_RESERVE: - case IOC_PR_RELEASE: - case IOC_PR_PREEMPT: - case IOC_PR_PREEMPT_ABORT: - case IOC_PR_CLEAR: - return blkdev_ioctl(bdev, mode, cmd, - (unsigned long)compat_ptr(arg)); - default: - if (disk->fops->compat_ioctl) - ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); - return ret; - } -} diff --git a/block/ioctl.c b/block/ioctl.c index e728331d1a5b..f8c4e2649335 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -269,6 +269,38 @@ static int put_u64(unsigned long arg, u64 val) return put_user(val, (u64 __user *)arg); } +#ifdef CONFIG_COMPAT +static int compat_put_ushort(unsigned long arg, unsigned short val) +{ + return put_user(val, (unsigned short __user *)compat_ptr(arg)); +} + +static int compat_put_int(unsigned long arg, int val) +{ + return put_user(val, (compat_int_t __user *)compat_ptr(arg)); +} + +static int compat_put_uint(unsigned long arg, unsigned int val) +{ + return put_user(val, (compat_uint_t __user *)compat_ptr(arg)); +} + +static int compat_put_long(unsigned long arg, long val) +{ + return put_user(val, (compat_long_t __user *)compat_ptr(arg)); +} + +static int compat_put_ulong(unsigned long arg, compat_ulong_t val) +{ + return put_user(val, (compat_ulong_t __user *)compat_ptr(arg)); +} + +static int compat_put_u64(unsigned long arg, u64 val) +{ + return put_user(val, (compat_u64 __user *)compat_ptr(arg)); +} +#endif + int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { @@ -476,6 +508,44 @@ static int blkdev_getgeo(struct block_device *bdev, return 0; } +#ifdef CONFIG_COMPAT +struct compat_hd_geometry { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + u32 start; +}; + +static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev, + struct compat_hd_geometry __user *ugeo) +{ + struct hd_geometry geo; + int ret; + + if (!ugeo) + return -EINVAL; + if (!disk->fops->getgeo) + return -ENOTTY; + + memset(&geo, 0, sizeof(geo)); + /* + * We need to set the startsect first, the driver may + * want to override it. + */ + geo.start = get_start_sect(bdev); + ret = disk->fops->getgeo(bdev, &geo); + if (ret) + return ret; + + ret = copy_to_user(ugeo, &geo, 4); + ret |= put_user(geo.start, &ugeo->start); + if (ret) + ret = -EFAULT; + + return ret; +} +#endif + /* set the logical block size */ static int blkdev_bszset(struct block_device *bdev, fmode_t mode, int __user *argp) @@ -604,3 +674,152 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, } } EXPORT_SYMBOL_GPL(blkdev_ioctl); + +#ifdef CONFIG_COMPAT +struct compat_blkpg_ioctl_arg { + compat_int_t op; + compat_int_t flags; + compat_int_t datalen; + compat_caddr_t data; +}; + +static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) +{ + struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); + compat_caddr_t udata; + compat_int_t n; + int err; + + err = get_user(n, &ua32->op); + err |= put_user(n, &a->op); + err |= get_user(n, &ua32->flags); + err |= put_user(n, &a->flags); + err |= get_user(n, &ua32->datalen); + err |= put_user(n, &a->datalen); + err |= get_user(udata, &ua32->data); + err |= put_user(compat_ptr(udata), &a->data); + if (err) + return err; + + return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a); +} + +#define BLKBSZGET_32 _IOR(0x12, 112, int) +#define BLKBSZSET_32 _IOW(0x12, 113, int) +#define BLKGETSIZE64_32 _IOR(0x12, 114, int) + +/* Most of the generic ioctls are handled in the normal fallback path. + This assumes the blkdev's low level compat_ioctl always returns + ENOIOCTLCMD for unknown ioctls. */ +long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + int ret = -ENOIOCTLCMD; + struct inode *inode = file->f_mapping->host; + struct block_device *bdev = inode->i_bdev; + struct gendisk *disk = bdev->bd_disk; + fmode_t mode = file->f_mode; + loff_t size; + unsigned int max_sectors; + + /* + * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have + * to updated it before every ioctl. + */ + if (file->f_flags & O_NDELAY) + mode |= FMODE_NDELAY; + else + mode &= ~FMODE_NDELAY; + + switch (cmd) { + case HDIO_GETGEO: + return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); + case BLKPBSZGET: + return compat_put_uint(arg, bdev_physical_block_size(bdev)); + case BLKIOMIN: + return compat_put_uint(arg, bdev_io_min(bdev)); + case BLKIOOPT: + return compat_put_uint(arg, bdev_io_opt(bdev)); + case BLKALIGNOFF: + return compat_put_int(arg, bdev_alignment_offset(bdev)); + case BLKDISCARDZEROES: + return compat_put_uint(arg, 0); + case BLKFLSBUF: + case BLKROSET: + case BLKDISCARD: + case BLKSECDISCARD: + case BLKZEROOUT: + /* + * the ones below are implemented in blkdev_locked_ioctl, + * but we call blkdev_ioctl, which gets the lock for us + */ + case BLKRRPART: + case BLKREPORTZONE: + case BLKRESETZONE: + case BLKOPENZONE: + case BLKCLOSEZONE: + case BLKFINISHZONE: + case BLKGETZONESZ: + case BLKGETNRZONES: + return blkdev_ioctl(bdev, mode, cmd, + (unsigned long)compat_ptr(arg)); + case BLKBSZSET_32: + return blkdev_ioctl(bdev, mode, BLKBSZSET, + (unsigned long)compat_ptr(arg)); + case BLKPG: + return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg)); + case BLKRAGET: + case BLKFRAGET: + if (!arg) + return -EINVAL; + return compat_put_long(arg, + (bdev->bd_bdi->ra_pages * PAGE_SIZE) / 512); + case BLKROGET: /* compatible */ + return compat_put_int(arg, bdev_read_only(bdev) != 0); + case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */ + return compat_put_int(arg, block_size(bdev)); + case BLKSSZGET: /* get block device hardware sector size */ + return compat_put_int(arg, bdev_logical_block_size(bdev)); + case BLKSECTGET: + max_sectors = min_t(unsigned int, USHRT_MAX, + queue_max_sectors(bdev_get_queue(bdev))); + return compat_put_ushort(arg, max_sectors); + case BLKROTATIONAL: + return compat_put_ushort(arg, + !blk_queue_nonrot(bdev_get_queue(bdev))); + case BLKRASET: /* compatible, but no compat_ptr (!) */ + case BLKFRASET: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE; + return 0; + case BLKGETSIZE: + size = i_size_read(bdev->bd_inode); + if ((size >> 9) > ~0UL) + return -EFBIG; + return compat_put_ulong(arg, size >> 9); + + case BLKGETSIZE64_32: + return compat_put_u64(arg, i_size_read(bdev->bd_inode)); + + case BLKTRACESETUP32: + case BLKTRACESTART: /* compatible */ + case BLKTRACESTOP: /* compatible */ + case BLKTRACETEARDOWN: /* compatible */ + ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); + return ret; + case IOC_PR_REGISTER: + case IOC_PR_RESERVE: + case IOC_PR_RELEASE: + case IOC_PR_PREEMPT: + case IOC_PR_PREEMPT_ABORT: + case IOC_PR_CLEAR: + return blkdev_ioctl(bdev, mode, cmd, + (unsigned long)compat_ptr(arg)); + default: + if (disk->fops->compat_ioctl) + ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); + return ret; + } +} +#endif From patchwork Thu Jan 2 14:55:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315929 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 37CFE14B4 for ; Thu, 2 Jan 2020 15:04:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1578B2072C for ; Thu, 2 Jan 2020 15:04:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728753AbgABPEh (ORCPT ); Thu, 2 Jan 2020 10:04:37 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:34611 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728745AbgABPEh (ORCPT ); Thu, 2 Jan 2020 10:04:37 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MA7b8-1it7cR1DjO-00BZs1; Thu, 02 Jan 2020 16:04:25 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Jens Axboe , Jan Kara , Hans Holmberg , Chaitanya Kulkarni , Ajay Joshi , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 20/22] compat_ioctl: block: simplify compat_blkpg_ioctl() Date: Thu, 2 Jan 2020 15:55:38 +0100 Message-Id: <20200102145552.1853992-21-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:l3+5zbd4lrbw4tzQblHwKZzHCHX3uYKJ+57JHSO7m7iTNY7IOEM Yy069NpLdeHeOMEiF3xar5cgusQ397iBTWnVGx6VGMtXKZUZ4bo9wW43SIyXi61v3w3PZpj nVHeTCHtXQ1vhS5hTzRWLv/Ok4iUqwKr+anhilMAKd3/yHip4vPJsX/NVOK7G4U/bBEPEPe N8OwSazo3DlmxRxuVVLgQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:vZkgOPk0SmE=:UUaFhhZiT8Vbhirn0LsbAo DHnOaaqxmEnaJOqdy7gDh4Yh7W3WBSbzPp0eNZo28MBdVQiuO1hRkvAtozlI9Ehn32VcQCsqB gVQv05f++A/BIo7ffzCqCriJo4h0CvohJCf8B0asn71wSVmg1ydyYcAb8J5xVU8JkkL7P5R6M 9rW++tUp7NBf/kIGiOMwDXxXJCztzngQ1LC3CTvnzi80QFl7eyYIHbhB/qZHRVtYx/59WjWWg zBXV5BDg+HpyrNovRvSYQbLZn9i5ztNfp8gTkjfA5t2x/20Uoa58WIEvbaZ8N7jNMHSPmnJHh 2QaoadHCHAxvPav3Y9LZh5jkhhymPSbog0KTnN2zX5RnLapEb3ejYEjdoMtw8B5d9MPhDx+l0 A59yUlKApXvZNZpQcObhknCw2V2lVFYsbr8ECw88zRTkCl0FSSYno0gdhS84OuaIRqA0rQitR /BPSzagNKB7phFkPPG7Ctd9KINoKaOyvgIQWSElKQoqgbND73EmsbJBaY9TWEWmf6yH2+XlrE N19Hz65Ryo+Ek7HOTInYkUS6OmxvcLq0y8ylQzX8fjQ8TEIKZ0yAC3T+EC1NfV9SbJPYylG2N daLJCd3K3ST9IM73tYcBQM3NVKDIMePGZQ/a/8OpoN9YnsT6bpzS89pFGYeuKG/unMa8iZWuo GOMrn+Xkns9h0LdL4KSnnwzQsQiHIveijqkp+SsGUpvxaeWAo/0phbGlIfFRX188sfBVkDBXn qzNiBobFvz9pf8A/4teSnsmxUvfJgUVVSjtaAXiB8NQq8tcJG4DJTGcw821tBw5vpHX9yhGCu ilx5PikHGgtqbpvtALY8exNNtanX3OEUHv6FQoNqlikcRJODn2PEg6zVyox9GrjZ53uSQ+9v3 C0JPfJxloAvsnWjrCLXA== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org There is no need to go through a compat_alloc_user_space() copy any more, just wrap the function in a small helper that works the same way for native and compat mode. Signed-off-by: Arnd Bergmann --- block/ioctl.c | 74 ++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/block/ioctl.c b/block/ioctl.c index f8c4e2649335..d6911a1149f5 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -12,12 +12,12 @@ #include #include -static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) +static int blkpg_do_ioctl(struct block_device *bdev, + struct blkpg_partition __user *upart, int op) { struct block_device *bdevp; struct gendisk *disk; struct hd_struct *part, *lpart; - struct blkpg_ioctl_arg a; struct blkpg_partition p; struct disk_part_iter piter; long long start, length; @@ -25,9 +25,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg))) - return -EFAULT; - if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) + if (copy_from_user(&p, upart, sizeof(struct blkpg_partition))) return -EFAULT; disk = bdev->bd_disk; if (bdev != bdev->bd_contains) @@ -35,7 +33,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user partno = p.pno; if (partno <= 0) return -EINVAL; - switch (a.op) { + switch (op) { case BLKPG_ADD_PARTITION: start = p.start >> 9; length = p.length >> 9; @@ -156,6 +154,39 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user } } +static int blkpg_ioctl(struct block_device *bdev, + struct blkpg_ioctl_arg __user *arg) +{ + struct blkpg_partition __user *udata; + int op; + + if (get_user(op, &arg->op) || get_user(udata, &arg->data)) + return -EFAULT; + + return blkpg_do_ioctl(bdev, udata, op); +} + +#ifdef CONFIG_COMPAT +struct compat_blkpg_ioctl_arg { + compat_int_t op; + compat_int_t flags; + compat_int_t datalen; + compat_caddr_t data; +}; + +static int compat_blkpg_ioctl(struct block_device *bdev, + struct compat_blkpg_ioctl_arg __user *arg) +{ + compat_caddr_t udata; + int op; + + if (get_user(op, &arg->op) || get_user(udata, &arg->data)) + return -EFAULT; + + return blkpg_do_ioctl(bdev, compat_ptr(udata), op); +} +#endif + static int blkdev_reread_part(struct block_device *bdev) { int ret; @@ -676,35 +707,6 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, EXPORT_SYMBOL_GPL(blkdev_ioctl); #ifdef CONFIG_COMPAT -struct compat_blkpg_ioctl_arg { - compat_int_t op; - compat_int_t flags; - compat_int_t datalen; - compat_caddr_t data; -}; - -static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) -{ - struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); - compat_caddr_t udata; - compat_int_t n; - int err; - - err = get_user(n, &ua32->op); - err |= put_user(n, &a->op); - err |= get_user(n, &ua32->flags); - err |= put_user(n, &a->flags); - err |= get_user(n, &ua32->datalen); - err |= put_user(n, &a->datalen); - err |= get_user(udata, &ua32->data); - err |= put_user(compat_ptr(udata), &a->data); - if (err) - return err; - - return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a); -} - #define BLKBSZGET_32 _IOR(0x12, 112, int) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) @@ -767,7 +769,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) return blkdev_ioctl(bdev, mode, BLKBSZSET, (unsigned long)compat_ptr(arg)); case BLKPG: - return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg)); + return compat_blkpg_ioctl(bdev, compat_ptr(arg)); case BLKRAGET: case BLKFRAGET: if (!arg) From patchwork Thu Jan 2 14:55:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11315935 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A611D14B4 for ; Thu, 2 Jan 2020 15:04:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 79CD221835 for ; Thu, 2 Jan 2020 15:04:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728723AbgABPEt (ORCPT ); Thu, 2 Jan 2020 10:04:49 -0500 Received: from mout.kundenserver.de ([212.227.126.130]:56953 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728655AbgABPEt (ORCPT ); Thu, 2 Jan 2020 10:04:49 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1MvazO-1jcNUc31vC-00siAv; Thu, 02 Jan 2020 16:04:32 +0100 From: Arnd Bergmann To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: Arnd Bergmann , Jens Axboe , Jan Kara , Chaitanya Kulkarni , =?utf-8?q?Javier_Gonz=C3=A1lez?= , Ajay Joshi , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 21/22] compat_ioctl: simplify up block/ioctl.c Date: Thu, 2 Jan 2020 15:55:39 +0100 Message-Id: <20200102145552.1853992-22-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200102145552.1853992-1-arnd@arndb.de> References: <20200102145552.1853992-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:B4Fh0GjnWw4L91lIqSeGoYU/IDbi9IpD5S0mu86IQo8id2AcYHQ T2kPry3perMpHqhDWFKLXuP/pr6xUTF7uaa2TxDIxavXMjf3SXj6Vwq6zg8FnJPGi0p72/C dbMLZ+fLowuN90CSEzcc2b226j2NNbSDmK5t9HbpYYBlWwgOo+l/EjJtE02E8E+omB6WGzN +5SmvPJYvzsPKz4XisoQg== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:DxkPszahlxI=:H95Wx14ZxHniHx35fHkqqk 24yzenpzgTQKx58QV0bw4Fma0ZfQFOjNt3+GFeqrf1ymxg/Tnet1S7GuR2zQUh3JjTGN38Fit MwwY6oDSwQserGKWVCTTkAHf2iHgcHIvQCh/B9N6g8FPW3/0SD8WN+v92sJm3ouzP2fheN/0j OgU07mqXo16oDR1vMrNauWNqvp8Doy9FCdl3tUyjJQ1DOVhi+RD+pY3E+iJfaLe1OS/6EdR3d nNwaZ5HlTeITHJw4d8TFyBPyCNmElV/mAgjrMeYniKYO2WPpV4nur2mXyRHWc414GJAbRcLvh j6SndLSOnZgrUlrq/MIO8hK2NPJ7dRA9YqnkHRasvqPMrDFdRgHZHzb6EAVtziv1FM++MHNUx QhdQA+t0PvkzsJMAAU6FOgChOuOPTGqD3Pe8seaiM3ueUAq1uj9vckWxa6BVUtntHffKf4CXf C8C4O0NhECwo0AF94fpQvUcMDxvPjL1FGKG2l+Agu0NwmKECPm82VuSaXj2Jgai5VExPhiV38 hQkkPwiyEj3YkFNHe+sld2aR4G2kKsdUo1i5l9EkDUrocVRv4nbsxof1lQf/wNNU+4IfasxTJ Het71rcx5lM793gyZfJm142RZtMcDbvKwXL/egHkbV2+ZwT/p4BajTABfU5UHrDaUk3tAC9kt tUekkgQ2QimImvEOFW+YaEqiK18PN23cJx/zWFyqSLthio76f2QbJUQQMi0BPl1oLY/l5y8+/ gffvFGpjl3vHCDMLfVyR8r07zcJ2EPc9CYQh0KyNa7uMC3HE0Kbse/g55PsxXdU9D5weMXQFJ m1ZBWO68Jf9AUY7G2C07d0vXxOKb+LJjj2hBqYTNc7R6z9ReTDgdPbEPvkUzuAQEkhIdsdIvh ENgi58A1Qu+3Cdlz5DUA== Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Having separate implementations of blkdev_ioctl() often leads to these getting out of sync, despite the comment at the top. Since most of the ioctl commands are compatible, and we try very hard not to add any new incompatible ones, move all the common bits into a shared function and leave only the ones that are historically different in separate functions for native/compat mode. To deal with the compat_ptr() conversion, pass both the integer argument and the pointer argument into the new blkdev_common_ioctl() and make sure to always use the correct one of these. blkdev_ioctl() is now only kept as a separate exported interfact for drivers/char/raw.c, which lacks a compat_ioctl variant. We should probably either move raw.c to staging if there are no more users, or export blkdev_compat_ioctl() as well. Signed-off-by: Arnd Bergmann --- block/ioctl.c | 269 ++++++++++++++++++++++---------------------------- 1 file changed, 117 insertions(+), 152 deletions(-) diff --git a/block/ioctl.c b/block/ioctl.c index d6911a1149f5..127194b9f9bd 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -270,65 +270,45 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, BLKDEV_ZERO_NOUNMAP); } -static int put_ushort(unsigned long arg, unsigned short val) +static int put_ushort(unsigned short __user *argp, unsigned short val) { - return put_user(val, (unsigned short __user *)arg); + return put_user(val, argp); } -static int put_int(unsigned long arg, int val) +static int put_int(int __user *argp, int val) { - return put_user(val, (int __user *)arg); + return put_user(val, argp); } -static int put_uint(unsigned long arg, unsigned int val) +static int put_uint(unsigned int __user *argp, unsigned int val) { - return put_user(val, (unsigned int __user *)arg); + return put_user(val, argp); } -static int put_long(unsigned long arg, long val) +static int put_long(long __user *argp, long val) { - return put_user(val, (long __user *)arg); + return put_user(val, argp); } -static int put_ulong(unsigned long arg, unsigned long val) +static int put_ulong(unsigned long __user *argp, unsigned long val) { - return put_user(val, (unsigned long __user *)arg); + return put_user(val, argp); } -static int put_u64(unsigned long arg, u64 val) +static int put_u64(u64 __user *argp, u64 val) { - return put_user(val, (u64 __user *)arg); + return put_user(val, argp); } #ifdef CONFIG_COMPAT -static int compat_put_ushort(unsigned long arg, unsigned short val) +static int compat_put_long(compat_long_t *argp, long val) { - return put_user(val, (unsigned short __user *)compat_ptr(arg)); + return put_user(val, argp); } -static int compat_put_int(unsigned long arg, int val) +static int compat_put_ulong(compat_ulong_t *argp, compat_ulong_t val) { - return put_user(val, (compat_int_t __user *)compat_ptr(arg)); -} - -static int compat_put_uint(unsigned long arg, unsigned int val) -{ - return put_user(val, (compat_uint_t __user *)compat_ptr(arg)); -} - -static int compat_put_long(unsigned long arg, long val) -{ - return put_user(val, (compat_long_t __user *)compat_ptr(arg)); -} - -static int compat_put_ulong(unsigned long arg, compat_ulong_t val) -{ - return put_user(val, (compat_ulong_t __user *)compat_ptr(arg)); -} - -static int compat_put_u64(unsigned long arg, u64 val) -{ - return put_user(val, (compat_u64 __user *)compat_ptr(arg)); + return put_user(val, argp); } #endif @@ -547,9 +527,10 @@ struct compat_hd_geometry { u32 start; }; -static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev, - struct compat_hd_geometry __user *ugeo) +static int compat_hdio_getgeo(struct block_device *bdev, + struct compat_hd_geometry __user *ugeo) { + struct gendisk *disk = bdev->bd_disk; struct hd_geometry geo; int ret; @@ -603,13 +584,13 @@ static int blkdev_bszset(struct block_device *bdev, fmode_t mode, } /* - * always keep this in sync with compat_blkdev_ioctl() + * Common commands that are handled the same way on native and compat + * user space. Note the separate arg/argp parameters that are needed + * to deal with the compat_ptr() conversion. */ -int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, - unsigned long arg) +static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode, + unsigned cmd, unsigned long arg, void __user *argp) { - void __user *argp = (void __user *)arg; - loff_t size; unsigned int max_sectors; switch (cmd) { @@ -632,60 +613,39 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, case BLKFINISHZONE: return blkdev_zone_mgmt_ioctl(bdev, mode, cmd, arg); case BLKGETZONESZ: - return put_uint(arg, bdev_zone_sectors(bdev)); + return put_uint(argp, bdev_zone_sectors(bdev)); case BLKGETNRZONES: - return put_uint(arg, blkdev_nr_zones(bdev->bd_disk)); - case HDIO_GETGEO: - return blkdev_getgeo(bdev, argp); - case BLKRAGET: - case BLKFRAGET: - if (!arg) - return -EINVAL; - return put_long(arg, (bdev->bd_bdi->ra_pages*PAGE_SIZE) / 512); + return put_uint(argp, blkdev_nr_zones(bdev->bd_disk)); case BLKROGET: - return put_int(arg, bdev_read_only(bdev) != 0); - case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */ - return put_int(arg, block_size(bdev)); + return put_int(argp, bdev_read_only(bdev) != 0); case BLKSSZGET: /* get block device logical block size */ - return put_int(arg, bdev_logical_block_size(bdev)); + return put_int(argp, bdev_logical_block_size(bdev)); case BLKPBSZGET: /* get block device physical block size */ - return put_uint(arg, bdev_physical_block_size(bdev)); + return put_uint(argp, bdev_physical_block_size(bdev)); case BLKIOMIN: - return put_uint(arg, bdev_io_min(bdev)); + return put_uint(argp, bdev_io_min(bdev)); case BLKIOOPT: - return put_uint(arg, bdev_io_opt(bdev)); + return put_uint(argp, bdev_io_opt(bdev)); case BLKALIGNOFF: - return put_int(arg, bdev_alignment_offset(bdev)); + return put_int(argp, bdev_alignment_offset(bdev)); case BLKDISCARDZEROES: - return put_uint(arg, 0); + return put_uint(argp, 0); case BLKSECTGET: max_sectors = min_t(unsigned int, USHRT_MAX, queue_max_sectors(bdev_get_queue(bdev))); - return put_ushort(arg, max_sectors); + return put_ushort(argp, max_sectors); case BLKROTATIONAL: - return put_ushort(arg, !blk_queue_nonrot(bdev_get_queue(bdev))); + return put_ushort(argp, !blk_queue_nonrot(bdev_get_queue(bdev))); case BLKRASET: case BLKFRASET: if(!capable(CAP_SYS_ADMIN)) return -EACCES; bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE; return 0; - case BLKBSZSET: - return blkdev_bszset(bdev, mode, argp); - case BLKPG: - return blkpg_ioctl(bdev, argp); case BLKRRPART: return blkdev_reread_part(bdev); - case BLKGETSIZE: - size = i_size_read(bdev->bd_inode); - if ((size >> 9) > ~0UL) - return -EFBIG; - return put_ulong(arg, size >> 9); - case BLKGETSIZE64: - return put_u64(arg, i_size_read(bdev->bd_inode)); case BLKTRACESTART: case BLKTRACESTOP: - case BLKTRACESETUP: case BLKTRACETEARDOWN: return blk_trace_ioctl(bdev, cmd, argp); case IOC_PR_REGISTER: @@ -701,12 +661,67 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, case IOC_PR_CLEAR: return blkdev_pr_clear(bdev, argp); default: - return __blkdev_driver_ioctl(bdev, mode, cmd, arg); + return -ENOIOCTLCMD; } } -EXPORT_SYMBOL_GPL(blkdev_ioctl); + +/* + * Always keep this in sync with compat_blkdev_ioctl() + * to handle all incompatible commands in both functions. + * + * New commands must be compatible and go into blkdev_common_ioctl + */ +int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, + unsigned long arg) +{ + int ret; + loff_t size; + void __user *argp = (void __user *)arg; + + switch (cmd) { + /* These need separate implementations for the data structure */ + case HDIO_GETGEO: + return blkdev_getgeo(bdev, argp); + case BLKPG: + return blkpg_ioctl(bdev, argp); + + /* Compat mode returns 32-bit data instead of 'long' */ + case BLKRAGET: + case BLKFRAGET: + if (!argp) + return -EINVAL; + return put_long(argp, (bdev->bd_bdi->ra_pages*PAGE_SIZE) / 512); + case BLKGETSIZE: + size = i_size_read(bdev->bd_inode); + if ((size >> 9) > ~0UL) + return -EFBIG; + return put_ulong(argp, size >> 9); + + /* The data is compatible, but the command number is different */ + case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */ + return put_int(argp, block_size(bdev)); + case BLKBSZSET: + return blkdev_bszset(bdev, mode, argp); + case BLKGETSIZE64: + return put_u64(argp, i_size_read(bdev->bd_inode)); + + /* Incompatible alignment on i386 */ + case BLKTRACESETUP: + return blk_trace_ioctl(bdev, cmd, argp); + default: + break; + } + + ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp); + if (ret == -ENOIOCTLCMD) + return __blkdev_driver_ioctl(bdev, mode, cmd, arg); + + return ret; +} +EXPORT_SYMBOL_GPL(blkdev_ioctl); /* for /dev/raw */ #ifdef CONFIG_COMPAT + #define BLKBSZGET_32 _IOR(0x12, 112, int) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) @@ -716,13 +731,13 @@ EXPORT_SYMBOL_GPL(blkdev_ioctl); ENOIOCTLCMD for unknown ioctls. */ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) { - int ret = -ENOIOCTLCMD; + int ret; + void __user *argp = compat_ptr(arg); struct inode *inode = file->f_mapping->host; struct block_device *bdev = inode->i_bdev; struct gendisk *disk = bdev->bd_disk; fmode_t mode = file->f_mode; loff_t size; - unsigned int max_sectors; /* * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have @@ -734,94 +749,44 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) mode &= ~FMODE_NDELAY; switch (cmd) { + /* These need separate implementations for the data structure */ case HDIO_GETGEO: - return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); - case BLKPBSZGET: - return compat_put_uint(arg, bdev_physical_block_size(bdev)); - case BLKIOMIN: - return compat_put_uint(arg, bdev_io_min(bdev)); - case BLKIOOPT: - return compat_put_uint(arg, bdev_io_opt(bdev)); - case BLKALIGNOFF: - return compat_put_int(arg, bdev_alignment_offset(bdev)); - case BLKDISCARDZEROES: - return compat_put_uint(arg, 0); - case BLKFLSBUF: - case BLKROSET: - case BLKDISCARD: - case BLKSECDISCARD: - case BLKZEROOUT: - /* - * the ones below are implemented in blkdev_locked_ioctl, - * but we call blkdev_ioctl, which gets the lock for us - */ - case BLKRRPART: - case BLKREPORTZONE: - case BLKRESETZONE: - case BLKOPENZONE: - case BLKCLOSEZONE: - case BLKFINISHZONE: - case BLKGETZONESZ: - case BLKGETNRZONES: - return blkdev_ioctl(bdev, mode, cmd, - (unsigned long)compat_ptr(arg)); - case BLKBSZSET_32: - return blkdev_ioctl(bdev, mode, BLKBSZSET, - (unsigned long)compat_ptr(arg)); + return compat_hdio_getgeo(bdev, argp); case BLKPG: - return compat_blkpg_ioctl(bdev, compat_ptr(arg)); + return compat_blkpg_ioctl(bdev, argp); + + /* Compat mode returns 32-bit data instead of 'long' */ case BLKRAGET: case BLKFRAGET: - if (!arg) + if (!argp) return -EINVAL; - return compat_put_long(arg, + return compat_put_long(argp, (bdev->bd_bdi->ra_pages * PAGE_SIZE) / 512); - case BLKROGET: /* compatible */ - return compat_put_int(arg, bdev_read_only(bdev) != 0); - case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */ - return compat_put_int(arg, block_size(bdev)); - case BLKSSZGET: /* get block device hardware sector size */ - return compat_put_int(arg, bdev_logical_block_size(bdev)); - case BLKSECTGET: - max_sectors = min_t(unsigned int, USHRT_MAX, - queue_max_sectors(bdev_get_queue(bdev))); - return compat_put_ushort(arg, max_sectors); - case BLKROTATIONAL: - return compat_put_ushort(arg, - !blk_queue_nonrot(bdev_get_queue(bdev))); - case BLKRASET: /* compatible, but no compat_ptr (!) */ - case BLKFRASET: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE; - return 0; case BLKGETSIZE: size = i_size_read(bdev->bd_inode); if ((size >> 9) > ~0UL) return -EFBIG; - return compat_put_ulong(arg, size >> 9); + return compat_put_ulong(argp, size >> 9); + /* The data is compatible, but the command number is different */ + case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */ + return put_int(argp, bdev_logical_block_size(bdev)); + case BLKBSZSET_32: + return blkdev_bszset(bdev, mode, argp); case BLKGETSIZE64_32: - return compat_put_u64(arg, i_size_read(bdev->bd_inode)); + return put_u64(argp, i_size_read(bdev->bd_inode)); + /* Incompatible alignment on i386 */ case BLKTRACESETUP32: - case BLKTRACESTART: /* compatible */ - case BLKTRACESTOP: /* compatible */ - case BLKTRACETEARDOWN: /* compatible */ - ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); - return ret; - case IOC_PR_REGISTER: - case IOC_PR_RESERVE: - case IOC_PR_RELEASE: - case IOC_PR_PREEMPT: - case IOC_PR_PREEMPT_ABORT: - case IOC_PR_CLEAR: - return blkdev_ioctl(bdev, mode, cmd, - (unsigned long)compat_ptr(arg)); + return blk_trace_ioctl(bdev, cmd, argp); default: - if (disk->fops->compat_ioctl) - ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); - return ret; + break; } + + ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp); + if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl) + ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); + + return ret; } #endif