From patchwork Sat Aug 29 02:12:36 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Norris X-Patchwork-Id: 7094221 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4B08F9F1CD for ; Sat, 29 Aug 2015 02:13:41 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3F23620A37 for ; Sat, 29 Aug 2015 02:13:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 234B620A35 for ; Sat, 29 Aug 2015 02:13:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751389AbbH2CM7 (ORCPT ); Fri, 28 Aug 2015 22:12:59 -0400 Received: from mail-pa0-f51.google.com ([209.85.220.51]:35116 "EHLO mail-pa0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750896AbbH2CM6 (ORCPT ); Fri, 28 Aug 2015 22:12:58 -0400 Received: by pacdd16 with SMTP id dd16so79545479pac.2; Fri, 28 Aug 2015 19:12:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=YoaTZi47W2MUmimCMnud7czh70ojcy/LUov7Zqo3m9E=; b=h32kT1dRdyOiwD36Km0XW5rl1MXE1oJ6h6sGDivnq/E/hp/Lx8LXW264z5qUWW6c6F dmVgYXMgmOhk4ZOQDs0RWUUbNiqKF9bglKaB/WHaHJXXbvYDRXFOe554QMHV0E/Jp1lh y7crmEOSP6Q2JLmdaqZcEbY58U+sG0CZ3xxI0g7s4vAcq8C6xh7dpMj/1r/iHPgezdZu XqowwwWZ5pep2ZR09Drav3q71EtavXRfIHvd16bRWOdB35tZr/nfQe5t06orz53/Nhd4 nFnsyWMBiucRm96mA0yCB2VLEB7iFQeqxU96C7Ie0JTmV+JoKZX49rGlpT9A3cuIzXbj OZJQ== X-Received: by 10.68.249.101 with SMTP id yt5mr20664373pbc.6.1440814378105; Fri, 28 Aug 2015 19:12:58 -0700 (PDT) Received: from ban.mtv.corp.google.com ([172.22.64.120]) by smtp.gmail.com with ESMTPSA id x3sm7125128pdr.43.2015.08.28.19.12.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 28 Aug 2015 19:12:57 -0700 (PDT) From: Brian Norris To: linux-kernel@vger.kernel.org Cc: Brian Norris , David Woodhouse , linux-mtd@lists.infradead.org, linux-fsdevel@vger.kernel.org, Jens Axboe , Alexander Viro Subject: [RFC / BUG] mtd: provide proper 32/64-bit compat_ioctl() support for BLKPG Date: Fri, 28 Aug 2015 19:12:36 -0700 Message-Id: <1440814356-52070-1-git-send-email-computersforpeace@gmail.com> X-Mailer: git-send-email 2.5.0.457.gab17608 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-8.2 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP After a bit of poking around wondering why my 32-bit user-space can't seem to send a proper ioctl(BLKPG) to an MTD on my 64-bit kernel (ARM64), I noticed that struct blkpg_ioctl_arg is actually pretty unsuitable for use in the ioctl() ABI, due to its use of raw pointers, and its lack of alignment/packing restrictions (32-bit arch'es tend to pack the 4 fields into 4 32-bit words, whereas 64-bit arch'es would add padding after the third int, and make this 6 32-bit words). Anyway, this means BLKPG deserves some special compat_ioctl handling. Do the conversion in a small shim for MTD. The same bug applies to block/ioctl.c, but I wanted to get some comments first. I can send a non-RFC with the same approach for the block subsystem. But then: which tree should it go in? Tested only on MTD, with an ARM32 user space on an ARM64 kernel. Signed-off-by: Brian Norris --- drivers/mtd/mtdchar.c | 42 +++++++++++++++++++++++++++++++++--------- include/uapi/linux/blkpg.h | 10 ++++++++++ 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 55fa27ecf4e1..bf966be09e79 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -498,21 +498,17 @@ static int shrink_ecclayout(const struct nand_ecclayout *from, } static int mtdchar_blkpg_ioctl(struct mtd_info *mtd, - struct blkpg_ioctl_arg __user *arg) + struct blkpg_ioctl_arg *arg) { - struct blkpg_ioctl_arg a; struct blkpg_partition p; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg))) + if (copy_from_user(&p, arg->data, sizeof(p))) return -EFAULT; - if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) - return -EFAULT; - - switch (a.op) { + switch (arg->op) { case BLKPG_ADD_PARTITION: /* Only master mtd device must be used to add partitions */ @@ -966,8 +962,13 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) case BLKPG: { - ret = mtdchar_blkpg_ioctl(mtd, - (struct blkpg_ioctl_arg __user *)arg); + struct blkpg_ioctl_arg __user *blk_arg = argp; + struct blkpg_ioctl_arg a; + + if (copy_from_user(&a, blk_arg, sizeof(a))) + ret = -EFAULT; + else + ret = mtdchar_blkpg_ioctl(mtd, &a); break; } @@ -1046,6 +1047,29 @@ static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd, &buf_user->start); break; } + + case BLKPG: + { + /* Convert from blkpg_compat_ioctl_arg to blkpg_ioctl_arg */ + struct blkpg_compat_ioctl_arg __user *uarg = argp; + struct blkpg_compat_ioctl_arg arg; + struct blkpg_ioctl_arg a; + + if (copy_from_user(&arg, uarg, sizeof(arg))) { + ret = -EFAULT; + break; + } + + memset(&a, 0, sizeof(a)); + a.op = arg.op; + a.flags = arg.flags; + a.datalen = arg.datalen; + a.data = compat_ptr(arg.data); + + ret = mtdchar_blkpg_ioctl(mtd, &a); + break; + } + default: ret = mtdchar_ioctl(file, cmd, (unsigned long)argp); } diff --git a/include/uapi/linux/blkpg.h b/include/uapi/linux/blkpg.h index a8519446c111..0574147f4490 100644 --- a/include/uapi/linux/blkpg.h +++ b/include/uapi/linux/blkpg.h @@ -26,6 +26,7 @@ */ #include #include +#include #define BLKPG _IO(0x12,105) @@ -37,6 +38,15 @@ struct blkpg_ioctl_arg { void __user *data; }; +#ifdef CONFIG_COMPAT +struct blkpg_compat_ioctl_arg { + compat_int_t op; + compat_int_t flags; + compat_int_t datalen; + compat_uptr_t data; +}; +#endif + /* The subfunctions (for the op field) */ #define BLKPG_ADD_PARTITION 1 #define BLKPG_DEL_PARTITION 2