From patchwork Wed Sep 27 14:43:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 9974195 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2836460365 for ; Wed, 27 Sep 2017 14:43:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1C86328894 for ; Wed, 27 Sep 2017 14:43:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1155F291F0; Wed, 27 Sep 2017 14:43:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6DC6F28894 for ; Wed, 27 Sep 2017 14:43:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751850AbdI0OnQ (ORCPT ); Wed, 27 Sep 2017 10:43:16 -0400 Received: from mail-qk0-f195.google.com ([209.85.220.195]:34949 "EHLO mail-qk0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751548AbdI0OnP (ORCPT ); Wed, 27 Sep 2017 10:43:15 -0400 Received: by mail-qk0-f195.google.com with SMTP id o77so8946029qke.2 for ; Wed, 27 Sep 2017 07:43:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id; bh=T52xECzrPPaRv4znbR062pZpjGecLDv+aATfRFnwZVA=; b=GSSqTMkKHWjkki6ZoRaCZMhLhwUMNKc+QOIWPdrHLUnGNO4416FagnOcJViR4NEXUq L6dDKXg+OGuG7E7kl88vVJgzLVMykhBPkWBKjoagG7tPWiJQCo1Tq+nzj21zZ10vr8+y PndjjBQl7UO24ThVxug2s8ortC7ZzjMSOZ6SJIkb09TzhqrmNW0gjVoL0p0u9EL/ugRk CQcCnEouMWnIBQoAuCXao7XYmwQhN0dQG4xc8CltRUM0Msr9HXflnqdCxTzJW3Ho/T2q kqkIirFoXC0daQIrAZX1AOYJAI22RhWgMC9ufm3bj3jTNeaUY7HTYHLm1qEzJ53GU9w1 uT+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=T52xECzrPPaRv4znbR062pZpjGecLDv+aATfRFnwZVA=; b=HfyvbDuanj85SQuSccDKiGIG5VyiI5Tc9j3Uls6lwQHpqkKHdo3xVGvGzPbpJ7uyNf NaaYOpfR9VxwT0yJPKZDuAOYbFTMB/1Lx3oSXpzL3JK4ESGo+x9+o+sbjKKs0pvCh9H/ YHPMcrnXe0d4s8uSILiFbIUIDes6KhLRvH+SrsPJU0DnKQJke9RlZgXxesmEi1H39cBe 5gz1SyReKF/jFyDFUyi2LoY/yDdv9ARUWHyzWVLuNllXx0Jhf2P8B6e3J/3837E+Au34 h62MDxK0fAN9gJ3QQFq6oU0OPOVd2ZcI+ICTEuHgpOTNeOhSMl1Htq76w0crHU9QaOBB Hslw== X-Gm-Message-State: AHPjjUiC3FKdQB8zJlN6a6e7Bjpiq1k4UgvLbRskr36hisRa0NX/bVPA hu2/v7a54mBF9i1vV4voi6G1BtNs X-Google-Smtp-Source: AOwi7QAXzgQoi++94R1n11nHq9jLdrXzJd8/oNBPO+MplA/tV2GBYXab2kOXqcvrLYHFJd7yNzTk3Q== X-Received: by 10.55.20.78 with SMTP id e75mr1308807qkh.250.1506523394804; Wed, 27 Sep 2017 07:43:14 -0700 (PDT) Received: from localhost ([2606:a000:4381:1201:225:22ff:feb3:e51a]) by smtp.gmail.com with ESMTPSA id w23sm9008318qtj.0.2017.09.27.07.43.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Sep 2017 07:43:14 -0700 (PDT) From: Josef Bacik X-Google-Original-From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH][v2] btrfs: fix send ioctl on 32bit with 64bit kernel Date: Wed, 27 Sep 2017 10:43:13 -0400 Message-Id: <1506523393-9542-1-git-send-email-jbacik@fb.com> X-Mailer: git-send-email 2.7.4 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We pass in a pointer in our send arg struct, this means the struct size doesn't match with 32bit user space and 64bit kernel space. Fix this by adding a compat mode and doing the appropriate conversion. Signed-off-by: Josef Bacik Reviewed-by: David Sterba --- - move the args_32 out of the uapi header, they don't need it. - fix compile problems with CONFIG_32BIT and !CONFIG_COMPAT fs/btrfs/ioctl.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- fs/btrfs/send.c | 12 ++---------- fs/btrfs/send.h | 2 +- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 050d2d9c5533..75a686a886bc 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -5489,6 +5489,53 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg) return ret; } +#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) +struct btrfs_ioctl_send_args_32 { + __s64 send_fd; /* in */ + __u64 clone_sources_count; /* in */ + compat_uptr_t clone_sources; /* in */ + __u64 parent_root; /* in */ + __u64 flags; /* in */ + __u64 reserved[4]; /* in */ +} __attribute__ ((__packed__)); +#define BTRFS_IOC_SEND_32 _IOW(BTRFS_IOCTL_MAGIC, 38, \ + struct btrfs_ioctl_send_args_32) +#endif + +static int _btrfs_ioctl_send(struct file *file, void __user *argp, bool compat) +{ + struct btrfs_ioctl_send_args *arg; + int ret; + + if (compat) { +#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) + struct btrfs_ioctl_send_args_32 args32; + ret = copy_from_user(&args32, argp, sizeof(args32)); + if (ret) + return -EFAULT; + arg = kzalloc(sizeof(*arg), GFP_KERNEL); + if (!arg) + return -ENOMEM; + arg->send_fd = args32.send_fd; + arg->clone_sources_count = args32.clone_sources_count; + arg->clone_sources = compat_ptr(args32.clone_sources); + arg->parent_root = args32.parent_root; + arg->flags = args32.flags; + memcpy(arg->reserved, args32.reserved, + sizeof(args32.reserved)); +#else + return -ENOTTY; +#endif + } else { + arg = memdup_user(argp, sizeof(*arg)); + if (IS_ERR(arg)) + return PTR_ERR(arg); + } + ret = btrfs_ioctl_send(file, arg); + kfree(arg); + return ret; +} + long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -5594,7 +5641,11 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_set_received_subvol_32(file, argp); #endif case BTRFS_IOC_SEND: - return btrfs_ioctl_send(file, argp); + return _btrfs_ioctl_send(file, argp, false); +#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) + case BTRFS_IOC_SEND_32: + return _btrfs_ioctl_send(file, argp, true); +#endif case BTRFS_IOC_GET_DEV_STATS: return btrfs_ioctl_get_dev_stats(fs_info, argp); case BTRFS_IOC_QUOTA_CTL: diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 32b043ef8ac9..d5019035ad06 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "send.h" #include "backref.h" @@ -6365,13 +6366,12 @@ static void btrfs_root_dec_send_in_progress(struct btrfs_root* root) spin_unlock(&root->root_item_lock); } -long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_) +long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) { int ret = 0; struct btrfs_root *send_root = BTRFS_I(file_inode(mnt_file))->root; struct btrfs_fs_info *fs_info = send_root->fs_info; struct btrfs_root *clone_root; - struct btrfs_ioctl_send_args *arg = NULL; struct btrfs_key key; struct send_ctx *sctx = NULL; u32 i; @@ -6407,13 +6407,6 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_) goto out; } - arg = memdup_user(arg_, sizeof(*arg)); - if (IS_ERR(arg)) { - ret = PTR_ERR(arg); - arg = NULL; - goto out; - } - /* * Check that we don't overflow at later allocations, we request * clone_sources_count + 1 items, and compare to unsigned long inside @@ -6654,7 +6647,6 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_) if (sctx && !IS_ERR_OR_NULL(sctx->parent_root)) btrfs_root_dec_send_in_progress(sctx->parent_root); - kfree(arg); kvfree(clone_sources_tmp); if (sctx) { diff --git a/fs/btrfs/send.h b/fs/btrfs/send.h index 02e00166c4da..3aa4bc55754f 100644 --- a/fs/btrfs/send.h +++ b/fs/btrfs/send.h @@ -130,5 +130,5 @@ enum { #define BTRFS_SEND_A_MAX (__BTRFS_SEND_A_MAX - 1) #ifdef __KERNEL__ -long btrfs_ioctl_send(struct file *mnt_file, void __user *arg); +long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg); #endif