From patchwork Fri Sep 29 19:44:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 9978559 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 ADDF260311 for ; Fri, 29 Sep 2017 19:44:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A0BB0298AB for ; Fri, 29 Sep 2017 19:44:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 95949298AD; Fri, 29 Sep 2017 19:44:39 +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 00C10298AB for ; Fri, 29 Sep 2017 19:44:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752584AbdI2Toh (ORCPT ); Fri, 29 Sep 2017 15:44:37 -0400 Received: from mail-qk0-f193.google.com ([209.85.220.193]:37366 "EHLO mail-qk0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752557AbdI2Toe (ORCPT ); Fri, 29 Sep 2017 15:44:34 -0400 Received: by mail-qk0-f193.google.com with SMTP id z143so402447qkb.4 for ; Fri, 29 Sep 2017 12:44:34 -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:in-reply-to:references; bh=3YZtUcTrZJldwLE7TTpk+buHFufYrpGqCAVEVS+bPxc=; b=WSGiWAs2jZDHQ5yMFlrESvXDcLixtfVcGz4FqJPxHEYvBQuKXcBdvfMEh2uKD0JIIj Qw3gd3dwQ/pBsDx4gaYFkpzS5NnQpKfs+kwAygrhv1pruk1YLsOTGGPPWV+nXFcm3LT9 s5HyWukahLMTvW3JEf2WS9NscBJ4mjFl0qF3cgmgvblin/jFobpz+LnLMM4zoX1uVpmF yiR2suQbpJKC5vTD7SmhidqW0eHtJElra8BtPfuYarvwesMW28IgDy5V5fhwZi24xOmY W4VXS+ZNM9lLthkdWPA9P9JiNjOj89u58UvJPsYXHPZCMaWUaYpFg3+X0n1b95eQv9rX qwyA== 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:in-reply-to :references; bh=3YZtUcTrZJldwLE7TTpk+buHFufYrpGqCAVEVS+bPxc=; b=fjFH8wZbUMEItKHXlDlhbewKIWbqrz2zeOmHlmf5PGNzIG5TfVg0CAUglbGGwd1tdX KFQXwFGglY9VOOgXAApbZbfFP2Kjkmew5dMMSFulX2tI7qWfIHIE9pFYHf6hAAWnj+0W B6+fTrCqmuUrIki0Az6ADqJd+W4Bose723cRKFfRM4bWvEHq43RNkV2M7Qhb9e6vAiz9 ONk4djwDCFGj+k4TWbYz30LJ2RKPS+XWWu5ukFfXt3v+HgRp4+zIgXcvXFLnA4J/Ql7g rm/pwxK0EaAjdd0rioT72LeBDO0rB6RYMmOhY5Gwp7PlcojeXK+lMb5fpKwg+DXMIilv EgxQ== X-Gm-Message-State: AMCzsaWeGmTBUnzdshj7oQOJgaIa941lWSkGgPVIa19BJqXpoSpYkXHD BKk1Y2SqUTUPVVUzxbRbzYgiaw== X-Google-Smtp-Source: AOwi7QD2TvOmJp0eU6lvO5CU9duaUltGoaaUlVc4LwsJ4GuHxUqG7N/275soqTBYiW+yHWeA2i3Slw== X-Received: by 10.55.166.131 with SMTP id p125mr4978248qke.264.1506714273841; Fri, 29 Sep 2017 12:44:33 -0700 (PDT) Received: from localhost ([2606:a000:4381:1201:225:22ff:feb3:e51a]) by smtp.gmail.com with ESMTPSA id m6sm3221088qkh.90.2017.09.29.12.44.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 29 Sep 2017 12:44:33 -0700 (PDT) From: Josef Bacik X-Google-Original-From: Josef Bacik To: kernel-team@fb.com, linux-btrfs@vger.kernel.org Subject: [PATCH 18/21] btrfs: fix send ioctl on 32bit with 64bit kernel Date: Fri, 29 Sep 2017 15:44:02 -0400 Message-Id: <1506714245-23072-19-git-send-email-jbacik@fb.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1506714245-23072-1-git-send-email-jbacik@fb.com> References: <1506714245-23072-1-git-send-email-jbacik@fb.com> 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 --- 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 398495f79c83..6a07d4e12fd2 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -5464,6 +5464,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) { @@ -5569,7 +5616,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 0746eda7231d..d9ddcdbdd2e7 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" @@ -6371,13 +6372,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; @@ -6413,13 +6413,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 @@ -6660,7 +6653,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