From patchwork Wed Dec 11 20:42:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11286323 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 CC7BB14E3 for ; Wed, 11 Dec 2019 20:46:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AC887222C4 for ; Wed, 11 Dec 2019 20:46:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726901AbfLKUqG (ORCPT ); Wed, 11 Dec 2019 15:46:06 -0500 Received: from mout.kundenserver.de ([212.227.17.13]:40797 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726890AbfLKUqE (ORCPT ); Wed, 11 Dec 2019 15:46:04 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue108 [212.227.15.145]) with ESMTPA (Nemesis) id 1Mzhf5-1hjio20Ph3-00vbw4; Wed, 11 Dec 2019 21:44:23 +0100 From: Arnd Bergmann To: Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Douglas Gilbert , Arnd Bergmann Cc: linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Steffen Maier , linux-scsi@vger.kernel.org, Chaitanya Kulkarni , Greg Kroah-Hartman , Thomas Gleixner , linux-block@vger.kernel.org Subject: [PATCH 02/24] compat: scsi: sg: fix v3 compat read/write interface Date: Wed, 11 Dec 2019 21:42:36 +0100 Message-Id: <20191211204306.1207817-3-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191211204306.1207817-1-arnd@arndb.de> References: <20191211204306.1207817-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:DlM8/RSZOaYg5JzO7DSn/knKPUvnvQmVJDNmgl9LouBnU4D8Xp1 /K/nZQCkejcMwqd34K2Q2OBGVdjrDhpVh8FPdUh0byRt9SW3BLbCX0oUB4xrMRk2xwLEfnB RlZHYWzNGZ9YtHMdiUUn1opDUpu7tCIjKc27WFY9HYeiSanGdlq9NRJjwNv7rVKJxk32BCY AE8eyDTr8OCkKgIhZDYog== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:57TTBnsP064=:xol5gk1SJmTe2qSSdWnL0w 3a3nqIlxgWVtGDMKinfkP6M90bf9xUBEtxuQBD88/UGfqgJAYOiM7L3PPdvTmo9lkvzTpZQu0 aUTZ4eiVwRshqensZ4GKhfWdBPld8QbYTSY9AVe0TMeyObvH+y9LetKeAUGCABADtnS5Qkw5G EcSoZvnK5Lh3Epls01CDs91roWqGa/ZaB1C5nZLdrpsVFCSavlzMrMmw9kK5LCanpNY/QQACE obCPL+eBF62x1XXEBpYGO8jj61UjgoLj5JcB1en4jh6StDSuF4kmBkDPiRKfFH/4Ny7uCuau9 IBq38vB01H0aEfl268UwWIhsAkmlYXh5yab5jslBPHtuXVZSHql+g6klZ2QWwISYO+TIbWmIG 5g9r0L3ulEJvK/xWDYygijvQo87e6JaMDPWEfVegNznVpasGpwDFZbpn6jq6BKlAee1nL/Aee F8iDOJ6oHpHeDJ+Eu+Z39lV64O9xRSJnuwiFTjIA0agfWveVlmVDoAE8X1t9EcG48N0TRFAqQ Gboa2XdlGNmU4keGeZkZmppSFyE43e/M2U4qftHy1xXmF8xIVVmLRIPp80G1F1A7JvaYLKCCq exaZWu1X5Bj8e8K5pTct5soi2v5F6KiJSu0rOxoIqd4Wvntn9bIrtn8sYFqtnYMphzH6FmHUB XY0X4+deX3vRvsf8L5WE89BH8edm6St/YYxJM2hqRjUIg4Y1x/H+vfQx01oxzSZSpRrExc8v4 L3VXA8er+Zo+OFOvu4LSXOhlYxpXUf/nzl2mA8g6uFBRVQJIxz9vpVSXs9O7Csk/l762+jDUa JAewa1xpYzvxig7e+Gw4SqhYNWc2KYC3u7/Amh+SzvE+r0Zdg4ZchYXdUubg2vH0DZ5gAGXr6 zbeTPLkZhfhYLYWMIQfQ== Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@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 | 125 +++++++++++++++++++++------------------------ include/scsi/sg.h | 30 +++++++++++ 3 files changed, 89 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..985546aac236 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -198,6 +198,7 @@ static void sg_device_destroy(struct kref *kref); #define SZ_SG_HEADER sizeof(struct sg_header) #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t) +#define SZ_COMPAT_SG_IO_HDR sizeof(struct compat_sg_io_hdr) #define SZ_SG_IOVEC sizeof(sg_iovec_t) #define SZ_SG_REQ_INFO sizeof(sg_req_info_t) @@ -405,6 +406,36 @@ 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) + goto unknown_id; + + /* 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 >= SZ_COMPAT_SG_IO_HDR) { + struct compat_sg_io_hdr __user *hp = buf; + return get_user(*pack_id, &hp->pack_id); + } + + if (count >= SZ_SG_IO_HDR) { + struct sg_io_hdr __user *hp = buf; + return get_user(*pack_id, &hp->pack_id); + } + +unknown_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 +444,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 +460,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 +561,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 < SZ_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 Wed Dec 11 20:42:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11286335 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 D0C0414E3 for ; Wed, 11 Dec 2019 20:47:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BAE6621556 for ; Wed, 11 Dec 2019 20:47:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726494AbfLKUrQ (ORCPT ); Wed, 11 Dec 2019 15:47:16 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:53299 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726345AbfLKUrQ (ORCPT ); Wed, 11 Dec 2019 15:47:16 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue108 [212.227.15.145]) with ESMTPA (Nemesis) id 1N7Qt9-1heGB12Xy1-017l1U; Wed, 11 Dec 2019 21:47:02 +0100 From: Arnd Bergmann To: Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro Cc: linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Arnd Bergmann , Hannes Reinecke , linux-scsi@vger.kernel.org Subject: [PATCH 12/24] compat_ioctl: add scsi_compat_ioctl Date: Wed, 11 Dec 2019 21:42:46 +0100 Message-Id: <20191211204306.1207817-13-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191211204306.1207817-1-arnd@arndb.de> References: <20191211204306.1207817-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:K9j2t2hRIDN1s24Qc+2ApYId+NR70I0ahQXZVZus7eh7p5W3KwC BexL4HNQXEGo1mU+/z+mF+nWOdFPvBBNu+B3O+hhRy6chSEBu6VtLmq6zXb4gdu/3JIZkWp fxlku3lFgKF/LiyPgpzzL8FHeSh1jnUjSLS5XVoRw4PLA0ipNO8wXuf5fhuEbAVIaJ5e9cD Xp7cjFIB9kwrj12+7CkmA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:iCPMOUwnMGU=:56ma4IjE+C5v8tJDupanbg ffaWXakkoowFJced4omf+RzDDMZK7NMo9/Q1isuFrGMdxbOrbBfPNB4zVP292J9Lbze6z2vby 06MP9oMvdo6eX2EQ+g6AyzUwrOXltJyuT/hOYV6Su2QTSINt/C4WWoqEXtdSge4uz7tfCyCfM NAUvMG9TLvoWOo7S8XMZgeW9VdarpO8Z6RaMpJWsAqIEFK7gKubRgL8PBHYuUNrnT6DkeHy6Y D2RgrNSWuI3nI0AUGGni+g0HZzWgwLC5QtKsxsQj9gSQytfqAuiY5q/RIT/0Jd5MHcv6ouf+x EEB3nJoKwgCYlh8Lx79x5uuRLFOQpSySmOqaD7P17FrJWT2sby0FrSqCrNx82EaFhOFk0y8B1 eVwHci2CU8wKbf3Tt2N3rLVN+DK/ozFKAXNYPJbwcpoQRIHtcXAuCVgELFDqYsGkUa+ql2gvC I32A8I4uzEqukJM7Z9b+D9DNGfOl2HZvnkR/ZhmtObpEo5/pUFMfj11wTiSsTYebpdrhG8+HY 8c/NxNufKbs+tpi1t5B/poXDjXurDqYNvg+E5zjGn8xLXJivGVlsSEEEwwvZU94xH2RO97qTk sd9kyb/N8K8jMfqZqEz8RnBPgNlLtXMRO04cU0ns0ZvRQbc6aumAItMheTcPj+ZUIQPfCTPWK oAVIFgY8NprWEIdqZfjvA01MQ2v5Zo3hXfyOGYaXQlRWV74VXSf4th8Xzis0k/650QKI8mrDK cQqX4kJHyT/K3IX6moEX6stv8hy4WfiXEZf8ZfqNZXgEK9idm51FpDCc6gyFKsAtIGdDb4bZ5 uVs5sguZu62Bjex2nnONT0YwfyPyRwY1tNjMH6PcTOBj5p2/ohWqRAkR/T3GTfRVOUcCbpZ1w vdIHEV5oDXVh+MX6OPeA== Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org In order to move the compat handling for SCSI ioctl commands out of fs/compat_ioctl.c into the individual drivers, we need a helper function first to match the native ioctl handler called by sd, sr, st, etc. Signed-off-by: Arnd Bergmann --- drivers/scsi/scsi_ioctl.c | 54 +++++++++++++++++++++++++++++---------- include/scsi/scsi_ioctl.h | 1 + 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 57bcd05605bf..8f3af87b6bb0 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -189,17 +189,7 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg) } -/** - * scsi_ioctl - Dispatch ioctl to scsi device - * @sdev: scsi device receiving ioctl - * @cmd: which ioctl is it - * @arg: data associated with ioctl - * - * Description: The scsi_ioctl() function differs from most ioctls in that it - * does not take a major/minor number as the dev field. Rather, it takes - * a pointer to a &struct scsi_device. - */ -int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) +static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg) { char scsi_cmd[MAX_COMMAND_SIZE]; struct scsi_sense_hdr sense_hdr; @@ -266,14 +256,50 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) return scsi_ioctl_get_pci(sdev, arg); case SG_SCSI_RESET: return scsi_ioctl_reset(sdev, arg); - default: - if (sdev->host->hostt->ioctl) - return sdev->host->hostt->ioctl(sdev, cmd, arg); } + return -ENOIOCTLCMD; +} + +/** + * scsi_ioctl - Dispatch ioctl to scsi device + * @sdev: scsi device receiving ioctl + * @cmd: which ioctl is it + * @arg: data associated with ioctl + * + * Description: The scsi_ioctl() function differs from most ioctls in that it + * does not take a major/minor number as the dev field. Rather, it takes + * a pointer to a &struct scsi_device. + */ +int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) +{ + int ret = scsi_ioctl_common(sdev, cmd, arg); + + if (ret != -ENOIOCTLCMD) + return ret; + + if (sdev->host->hostt->ioctl) + return sdev->host->hostt->ioctl(sdev, cmd, arg); + return -EINVAL; } EXPORT_SYMBOL(scsi_ioctl); +#ifdef CONFIG_COMPAT +int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) +{ + int ret = scsi_ioctl_common(sdev, cmd, arg); + + if (ret != -ENOIOCTLCMD) + return ret; + + if (sdev->host->hostt->compat_ioctl) + return sdev->host->hostt->compat_ioctl(sdev, cmd, arg); + + return ret; +} +EXPORT_SYMBOL(scsi_compat_ioctl); +#endif + /* * We can process a reset even when a device isn't fully operable. */ diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h index 5101e987c0ef..4fe69d863b5d 100644 --- a/include/scsi/scsi_ioctl.h +++ b/include/scsi/scsi_ioctl.h @@ -44,6 +44,7 @@ typedef struct scsi_fctargaddress { int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, int cmd, bool ndelay); extern int scsi_ioctl(struct scsi_device *, int, void __user *); +extern int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg); #endif /* __KERNEL__ */ #endif /* _SCSI_IOCTL_H */ From patchwork Wed Dec 11 20:42:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11286339 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 2DE7514E3 for ; Wed, 11 Dec 2019 20:47:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0CDF02054F for ; Wed, 11 Dec 2019 20:47:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726874AbfLKUrZ (ORCPT ); Wed, 11 Dec 2019 15:47:25 -0500 Received: from mout.kundenserver.de ([217.72.192.75]:44493 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726368AbfLKUrZ (ORCPT ); Wed, 11 Dec 2019 15:47:25 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue108 [212.227.15.145]) with ESMTPA (Nemesis) id 1MYNS0-1iAqRJ0S8I-00VNnz; Wed, 11 Dec 2019 21:47:11 +0100 From: Arnd Bergmann To: Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , FUJITA Tomonori Cc: linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Arnd Bergmann , Chaitanya Kulkarni , Benjamin Block , linux-scsi@vger.kernel.org, linux-block@vger.kernel.org Subject: [PATCH 13/24] compat_ioctl: bsg: add handler Date: Wed, 11 Dec 2019 21:42:47 +0100 Message-Id: <20191211204306.1207817-14-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191211204306.1207817-1-arnd@arndb.de> References: <20191211204306.1207817-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:9E//4H5jUjxcz88C86R1AD+v07xscBKEn+U5T2BAdtLUAnLN0TR pJgxkACJ2VOrwR21uFSKt045qw16CVFBKgxXRjl0wRXdIi5qvgtMPA2iOaEdMhuh+mWULCt EUPuHtjCDvcR/p3/P41WVjN3SGzN2XxCq0aarb5ncSCwLZiBPEKJmhY3WKVzezophJM9sQp yCYgZnaFk6bm8zt5Q8ozA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:v55hPGbeD1k=:IimA31h3OAuyU1W0DDaoVL g3OvsSmdNHSaEs4Gs3UxXci2k4RCJNRBJKKffYXVlD10ugWEUY706Wsw/XVqt2dVNSIGEVXhA dvGgAN0AuKEfOq5Nr0oXoiJqkxCe44UFhuA7h+Sy4+bZja7QiweCUAynaH7Ek7yIHCu928Ez3 CvDvPNgttFkSqonwZYX3/RnPO1a3iQbOW1/vN6ND6tFLN8A/OYn4HidUrtseO+1mkmyG8FcnA iJXScjWKnL4tqXgMvrfRQkEFrOEGgf6UW7eKKIEr8ngL2bZmpuI197iNv5aTI1Pp+b+44SUs3 mQD4jJ0xqPv+j11bZNqRawcLFtm1spFQNnWb3tidW3guiC8lrJSajAlCE6/kvkRxmen5rxvrq XBhbze+FZfygxhggJERbbk+41YUTfg55I2gJVbXCrIkkTTnN0Od+/lQUkCQtMxYapqX7MIToa Em/vHawJc2dL4FVsupr2V+/H6OEcgHZfb4RMYLMdhqCUaJ31tesvtmvDd51l4SPNPhLznfeIy 7OVhdD05wE7GN98NgSBQBh0IYZOE82NOU3tvk9NScW44ZETUBByBOOavsTmG8xKUakgx8mMR6 exaE4zh0EwsTfnwNR7e7G+cS01mRpVT2XaIp1GTxEI3XptQRkiGak5XEQhVzoLtQlejkQEIF2 EeHI58uWrmr5WVkixR8GE95knlczX1j0ZOAnfGn/08CEylXQCV6hqKOlEGXq6rHu7qraoR0Mv sBXSSOxLCkiH35xBBwc8Fr0dMR9d9uAu4ubde7KiPPNX+5R5TRjsGYer3bj96/L5SAVl604vB r/PrNrfEq0chmpD/BedGKE5ayZasUml2ioBCsX2dmqJ+l8mZySv68q8O4gjp8CakeUK7DZsZc d0oG+rl2zmJMClUdj1yw== Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@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 Wed Dec 11 20:42:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11286373 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 74D3215AB for ; Wed, 11 Dec 2019 20:49:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4A4A32173E for ; Wed, 11 Dec 2019 20:49:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727314AbfLKUte (ORCPT ); Wed, 11 Dec 2019 15:49:34 -0500 Received: from mout.kundenserver.de ([212.227.17.13]:42825 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726831AbfLKUte (ORCPT ); Wed, 11 Dec 2019 15:49:34 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue108 [212.227.15.145]) with ESMTPA (Nemesis) id 1M42b8-1if8um20TA-0005Wv; Wed, 11 Dec 2019 21:48:56 +0100 From: Arnd Bergmann To: Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , "Michael S. Tsirkin" , Jason Wang , Doug Gilbert , =?utf-8?q?Kai_M=C3=A4kisara?= Cc: linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Arnd Bergmann , Paolo Bonzini , Stefan Hajnoczi , Bart Van Assche , Hannes Reinecke , Damien Le Moal , John Garry , virtualization@lists.linux-foundation.org, linux-block@vger.kernel.org, linux-scsi@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 15/24] compat_ioctl: scsi: move ioctl handling into drivers Date: Wed, 11 Dec 2019 21:42:49 +0100 Message-Id: <20191211204306.1207817-16-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191211204306.1207817-1-arnd@arndb.de> References: <20191211204306.1207817-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:BaNM5i3rFNToDWp9jqn98bS6gnJlc1tUHYGa076M37t4numkmEH rmgMewG1Vi+BsQ/z8r6JFumNEzJhwXbkY93w78CnKNhOKnoChx4VrIkfSPo2MoO3z82l4VB J4KPCeRZLRCn0RIC0yEceOWO4NbMkkcX4eSx2TVmRsLJ70LxQTgVEu92Y4ycBBUW/GNlT9b VCNWFpOoJ+xrP9oEfE68w== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:U6GIxbucmvM=:2VfssZVNDAhPiU7N9HwQPZ PCmC7/SVP5XheKAB6Hw9XDyg+6C/vuTLprB69lkl2LruWKv7lTayTvXMmc/x63Qix9mHc2eUj hZQwOEvWYbFrBIozvkET+/y0P9TsC735E9LmTXywAr3yOjfz8hMoA6w5jrTidIHTH/MlF6R/l X35huqxBnekp87Sv73Eed2nQAGwOlVvquGQXWgb9SBd4rCMvhKdCrg2D96A8TNan3cl3YEtzf jrWokUNDC+CYqFL+YHp+6cYm+/4WuNoeF/6fzixpeheuc2v85u/+/QNBSa2gEtj29DGri86eT /wETNUAM9Yh4EWqj68xNOrdiEDgAt1RhMvHF5uEVpYbbIFhJuy19g+OdC1pLU8vVOTJ8UU3dI mmzRTEJDklVDi4yFDYF8T2PjwAMdgWjKLT97pOo47LYi5ohyXhU+pInkeUIMfk6kPa8X92e93 SD1K9xWLlMCKeM8Y1DHp5c/8pR1x7lgKPsApQiZaFFfwav/igamRrpQMTB89yOOQQBM9vlFRi u3tioDUOgZ7snHqyDzp7b493e6kQK9gYIQ6/4RYYjcnByHyiNNlh0suiObzAcgFOTcfCK3TPa SJtLmB3K2HOmQp/1kkUaiTyUHeWMU5lkXAaWIT1L30+FpJH3IxYnYrhJZqVglL0OlS6BEAFKH 04ngRIAWr9G00f2BAlnvNgObxSUUg4hbUnAKZFOW3r7nW7ZpcOQk6q5cWwsJuw+hqxXf+pzpK dp5cYF834e9IhpREH1CamKSH7TaALhrqE2qXxMvplAHcUX4UYrvJWzzla5in9RqDjCeRGaGr3 PoMNxOjDo+uzozEBY9V+dW6WXEEn7bfYXO1tCogxKRg203EBa9xjS5JgtuTLlT313bVGDMz0s ZeB2jEMeV7pnZW2S7tpQ== Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@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: Michael S. Tsirkin --- 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 985546aac236..08efcee7a34d 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -910,19 +910,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)); @@ -1145,29 +1140,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 Wed Dec 11 20:42:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11286385 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 D1EC714E3 for ; Wed, 11 Dec 2019 20:50:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B1778222C4 for ; Wed, 11 Dec 2019 20:50:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727041AbfLKUum (ORCPT ); Wed, 11 Dec 2019 15:50:42 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:56963 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726368AbfLKUum (ORCPT ); Wed, 11 Dec 2019 15:50:42 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue108 [212.227.15.145]) with ESMTPA (Nemesis) id 1MLz7f-1iNCZv1Qiv-00HtOe; Wed, 11 Dec 2019 21:50:18 +0100 From: Arnd Bergmann To: Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Tim Waugh , Borislav Petkov , "David S. Miller" Cc: linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Arnd Bergmann , Hannes Reinecke , linux-block@vger.kernel.org, linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org Subject: [PATCH 18/24] compat_ioctl: move cdrom commands into cdrom.c Date: Wed, 11 Dec 2019 21:42:52 +0100 Message-Id: <20191211204306.1207817-19-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191211204306.1207817-1-arnd@arndb.de> References: <20191211204306.1207817-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:YCC/4Cjm3aDYhGrVvv4vw+/A3W06RkJIX2vxsyaBWOwABLnpSY0 RA84rLENvr6GZ+SZrzgiGodaxTM+m2zHv3jC9nZ8PvrEgP8TU/0gCkO5D18uiAal4+0hFFX jiegrBrTxABAqlc+aLlM3EscQFWgbVf0ARY6eFMRjNjOwndlfTuEaI40MMv7h4v9UeeEbxl VP6Uq+ZvyoT7YYcZT9kjw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:9xEE4g5+y1E=:Hp3/3rN4TA2XdTQ/ZzXAp4 glzcY9TOBSffEXTuRYc+dcmHJcrbZ1Ab3/tuAZkfYu333ipdoJTFtSo6lNpNhw4crqPOdVqLN j9YyG25B9AFvowzc7CnNFLuuqoLimhcP6XpF1yHYBHGh34IxMThn6VFzdR4l4Lj2zPKRVhKCJ E6L5QZwADcGrpq1Eu6dULOLqU+3oSDvKHt7UtiqrTqi0edht+RxPSyuy0nF/EkBdC+5fJTech U/Snv0uPIaKE5ctkJC+gqh3DhM85vd0t9PGFy4sHDKTQ88N/QPnkQ4QoFBJrCXhqeir6Rrrn+ L+2DLl4DYXaFjcQlPqiCtgYajpR+LyzAszZFeETOEpCXJo9uozCMFOfvyfksQiXPwtDn1Q5v5 l3zsAgiBHMMR23H6Uzwtn8SuWQIUMlG0t65UDQIHn76EMu6r0ivfx0cUl8arB23+ejKyMJ6XR Y1MdzkFHwTGMi+MWNVyRY7yBkVPza6h6wBE0pfZitdd5ELziQbA3T9rgS1p51eZjee7DDQ2yT szzl3/5Nwbjtl+fKDwLeQM2uFkYNM9WzpWLsZ2c1jYYyxc32w7sKepB3Fp5V0vcqXOEZ/pSNT xnBnq0oxtC9mG+cLRI8JJIBoLbC446PHO/nRGNPYeY6LqswkFVXZE8Uli3sMNgocJEaVlBvdv jY71lV/obi6/1Gk6bhSftJ1ztMGw4ePxgEnfVBDoBN/IA4nqbwy7QXtjeUuOPqlg9iPlqtWvW BFruKHq0q3mTkhQyuAnYIFqeKBPLawr7DdtOXL/Br/Bq/JqZIdyLWjxKCRtaO+zhINgjy/W/O 8HA4p80/KqA6pkRfIkbE2l7kclxzRZMo7EoNUuEaZuD+1w1OMvLgmE+5jejt0zE1D0ehy166M 1XyCth261VtdB0xAEmow== Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@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 | 36 ++++++++++++++++++++++++++++++ drivers/scsi/sr.c | 10 +++------ 5 files changed, 45 insertions(+), 52 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index cf136bc2c9fc..7cb534d6e767 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -159,42 +159,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. */ @@ -210,15 +174,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..2de6e8ace957 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,38 @@ 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); + int err; + + switch (cmd) { + case CDROMSETSPINDOWN: + return idecd_set_spindown(&info->devinfo, arg); + case CDROMGETSPINDOWN: + return idecd_get_spindown(&info->devinfo, arg); + default: + break; + } + + return cdrom_ioctl(&info->devinfo, bdev, mode, cmd, + (unsigned long)compat_ptr(arg)); +} + +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 +1765,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 6033a886c42c..0fbb8fe6e521 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -628,13 +628,9 @@ 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) - return ret; + 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 Wed Dec 11 20:42:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11286387 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 21B9F112B for ; Wed, 11 Dec 2019 20:51:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F418A21556 for ; Wed, 11 Dec 2019 20:51:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726718AbfLKUvu (ORCPT ); Wed, 11 Dec 2019 15:51:50 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:45853 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726494AbfLKUvt (ORCPT ); Wed, 11 Dec 2019 15:51:49 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue108 [212.227.15.145]) with ESMTPA (Nemesis) id 1N4R0a-1hhIFG2CJi-011RMZ; Wed, 11 Dec 2019 21:51:32 +0100 From: Arnd Bergmann To: Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , John Garry , Brian King , Intel SCU Linux support , Artur Paszkiewicz , Jack Wang Cc: linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Arnd Bergmann , Hannes Reinecke , linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org Subject: [PATCH 19/24] compat_ioctl: scsi: handle HDIO commands from drivers Date: Wed, 11 Dec 2019 21:42:53 +0100 Message-Id: <20191211204306.1207817-20-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191211204306.1207817-1-arnd@arndb.de> References: <20191211204306.1207817-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:VLpQgUZjxMkjb5YR1h3oCFegmEv0coXfNiTrkHDQbxAgyNP2E6r MhXP2DgggU3oHmH6OM02Nk4EdkpfukoiVoudcNxW0gfqQQUukVExLJ7qPeUaC3clym7QDC0 nxat+UUyfjMPDoRwh/vX8d4K73OhBvOqGwqCeFzy/lYeu2qwmuA9trb2+GROu1JTOt3YvxB MLF8IJwkJNZW0Nm7LIFpw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:Px569MvALqc=:ysQLWqqciSyF15brchKM3I AbgC7DJI/etNcD+NoccD2d9MqjmlCKi5QZwvOSVw3d5aEnupRdMueWRTKTtD0L/Gr8TRj3Y72 iSBCbkqGkDo9MTm1JFmOcpGjOGvXfaysP0YDObPqS7ydxwRCxsfpE7hTcmwswcvBl5iQfrjhu eKLPypYh9ZvSyzYcB3mZkDpPngBv6/lCuW9PX9VMtpb5aoj0T4k9M1lqHBVTdiOUMc5CvcAjR mcUHXeEJvTsU03QjrFBk+VT3A0Hlsaw9UvkIYfK74sBafee67riQ0pcmXlw+HYzF4gDuoDtZI Jt6AhxBwKxun6NVYFVjTkJlsIDsEm6bBQU8ZH1267i8g7SgZucFxe7Ix8cfgdh9JZS0m0Gxdc mQsnRZPAxsSS64lpve3Is6NbsTN9AiORby8p0ywPyvZWYFS0DJoV2gbbx9Fv7lkUa3DiKNung X9ASeZFO3SP2nNFfwTpE4M5dy04rABfp+TP7ymdgx6Npw3jvzEYMJRbaFqdcgI4SfO6BrgbZR uF7gIhgrSKYmunLQ7S3JU+NbclFRBThXEPe81WzG3q/o6LR6RchCoSiQtqCgpDHQvK6R+W72D 8htJh+GZOeT7VW3gyPgN6Pns/RBZuCRJvFsbVBKI5oNXNZyt5+nmlGk6CG4lTm5jCzCrG8b5n T9iHACHK0zsazU8SackkzxZkdJXhU5jrxwL2CQqeMlcIit9bWKIYIfcBjcnGEhjBKaosW7PFS PvI7Vp1Bm6nCKKDOQMMg3wWYXZcu1ljfBPF+W+1becYC/U0WLm6L91VeAQv6GFQ6I+HopLzkJ TTnWy3eGhD4EZBkg/3QdrcNxVcufdDAKajSMPDmwzy6Vo8bVL8QzKfKQFu/AhtH0qHPyJE7vZ KDXp5oroB2gZemEXwXBQ== Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org The ata_sas_scsi_ioctl() function implements a number of HDIO_* commands for SCSI devices, it is used by all libata drivers as well as a few drivers that support SAS attached SATA drives. The only command that is not safe for compat ioctls here is HDIO_GET_32BIT. Change the implementation to check for in_compat_syscall() in order to do both cases correctly, and change all callers to use it as both native and compat callback pointers, including the indirect callers through sas_ioctl and ata_scsi_ioctl. Signed-off-by: Arnd Bergmann --- drivers/ata/libata-scsi.c | 9 +++++++++ drivers/scsi/aic94xx/aic94xx_init.c | 3 +++ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 +++ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +++ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +++ drivers/scsi/ipr.c | 3 +++ drivers/scsi/isci/init.c | 3 +++ drivers/scsi/mvsas/mv_init.c | 3 +++ drivers/scsi/pm8001/pm8001_init.c | 3 +++ include/linux/libata.h | 6 ++++++ 10 files changed, 39 insertions(+) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 58e09ffe8b9c..eb2eb599e602 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -17,6 +17,7 @@ * - http://www.t13.org/ */ +#include #include #include #include @@ -761,6 +762,10 @@ static int ata_ioc32(struct ata_port *ap) return 0; } +/* + * This handles both native and compat commands, so anything added + * here must have a compatible argument, or check in_compat_syscall() + */ int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev, unsigned int cmd, void __user *arg) { @@ -773,6 +778,10 @@ int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev, spin_lock_irqsave(ap->lock, flags); val = ata_ioc32(ap); spin_unlock_irqrestore(ap->lock, flags); +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) + return put_user(val, (compat_ulong_t __user *)arg); +#endif return put_user(val, (unsigned long __user *)arg); case HDIO_SET_32BIT: diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index f5781e31f57c..d022407e5645 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -54,6 +54,9 @@ static struct scsi_host_template aic94xx_sht = { .eh_target_reset_handler = sas_eh_target_reset_handler, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sas_ioctl, +#endif .track_queue_depth = 1, }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 3af53cc42bd6..fa25766502a2 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1772,6 +1772,9 @@ static struct scsi_host_template sht_v1_hw = { .eh_target_reset_handler = sas_eh_target_reset_handler, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sas_ioctl, +#endif .shost_attrs = host_attrs_v1_hw, .host_reset = hisi_sas_host_reset, }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 61b1e2693b08..545eaff5f3ee 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -3551,6 +3551,9 @@ static struct scsi_host_template sht_v2_hw = { .eh_target_reset_handler = sas_eh_target_reset_handler, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sas_ioctl, +#endif .shost_attrs = host_attrs_v2_hw, .host_reset = hisi_sas_host_reset, }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index bf5d5f138437..fa05e612d85a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3075,6 +3075,9 @@ static struct scsi_host_template sht_v3_hw = { .eh_target_reset_handler = sas_eh_target_reset_handler, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sas_ioctl, +#endif .shost_attrs = host_attrs_v3_hw, .tag_alloc_policy = BLK_TAG_ALLOC_RR, .host_reset = hisi_sas_host_reset, diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 079c04bc448a..ae45cbe98ae2 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -6727,6 +6727,9 @@ static struct scsi_host_template driver_template = { .name = "IPR", .info = ipr_ioa_info, .ioctl = ipr_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ipr_ioctl, +#endif .queuecommand = ipr_queuecommand, .eh_abort_handler = ipr_eh_abort, .eh_device_reset_handler = ipr_eh_dev_reset, diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 1727d0c71b12..b48aac8dfcb8 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -168,6 +168,9 @@ static struct scsi_host_template isci_sht = { .eh_target_reset_handler = sas_eh_target_reset_handler, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sas_ioctl, +#endif .shost_attrs = isci_host_attrs, .track_queue_depth = 1, }; diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index da719b0694dc..7af9173c4925 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -47,6 +47,9 @@ static struct scsi_host_template mvs_sht = { .eh_target_reset_handler = sas_eh_target_reset_handler, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sas_ioctl, +#endif .shost_attrs = mvst_host_attrs, .track_queue_depth = 1, }; diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index ff618ad80ebd..3c6076e4c6d2 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -101,6 +101,9 @@ static struct scsi_host_template pm8001_sht = { .eh_target_reset_handler = sas_eh_target_reset_handler, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sas_ioctl, +#endif .shost_attrs = pm8001_host_attrs, .track_queue_depth = 1, }; diff --git a/include/linux/libata.h b/include/linux/libata.h index d3bbfddf616a..e68d05febe5a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1109,6 +1109,11 @@ extern void ata_host_init(struct ata_host *, struct device *, struct ata_port_op extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, unsigned int cmd, void __user *arg); +#ifdef CONFIG_COMPAT +#define ATA_SCSI_COMPAT_IOCTL .compat_ioctl = ata_scsi_ioctl, +#else +#define ATA_SCSI_COMPAT_IOCTL /* empty */ +#endif extern int ata_scsi_queuecmd(struct Scsi_Host *h, struct scsi_cmnd *cmd); extern int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *dev, unsigned int cmd, void __user *arg); @@ -1340,6 +1345,7 @@ extern struct device_attribute *ata_common_sdev_attrs[]; .module = THIS_MODULE, \ .name = drv_name, \ .ioctl = ata_scsi_ioctl, \ + ATA_SCSI_COMPAT_IOCTL \ .queuecommand = ata_scsi_queuecmd, \ .can_queue = ATA_DEF_QUEUE, \ .tag_alloc_policy = BLK_TAG_ALLOC_RR, \