From patchwork Fri Jul 27 00:04:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naohiro Aota X-Patchwork-Id: 10546531 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 457CC139A for ; Fri, 27 Jul 2018 00:05:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 333A62B801 for ; Fri, 27 Jul 2018 00:05:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 23A3E2B84E; Fri, 27 Jul 2018 00:05:14 +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=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,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 707BB2B801 for ; Fri, 27 Jul 2018 00:05:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731839AbeG0BYV (ORCPT ); Thu, 26 Jul 2018 21:24:21 -0400 Received: from mail-pl0-f67.google.com ([209.85.160.67]:37438 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731630AbeG0BYU (ORCPT ); Thu, 26 Jul 2018 21:24:20 -0400 Received: by mail-pl0-f67.google.com with SMTP id 31-v6so1510997plc.4 for ; Thu, 26 Jul 2018 17:05:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id; bh=Hlwt80u2GmlOxixCVqU/Wz+bIzHMHxasKsFmb/zMz+g=; b=o+8RWfq3zsFjDKpesC4M/XXJ0xwG4UKGH6mQKcQff9cg6fhZU4fTuAdv4z1SoQTxk9 YRpSn6oyKOTlvptIWnmgFp+Qh+YYrVWMsalwnnLb4lrPQ1DEdm1kWXlV2HtZnNHp5NbR /RSxfig6XTt7ZVOKMZHue/Wah79kjnQRUTrfGKomxxuQ7mcsf6wZTsXJghPG/TX/Xo3t hygAMHPk22qjXi+XDLtb4sUJxQSfXXeSXl5mU77ImUyX8mnE3lW55mqvEIY33J4SRyk5 Y8rf3HPbIYLpwbnSPtjRlIcj0Cpodxq2Rz4YUCE5DWg7+knpWMq6W+jRPooQOkyRn8oN BIWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id; bh=Hlwt80u2GmlOxixCVqU/Wz+bIzHMHxasKsFmb/zMz+g=; b=oXF3cR09SJlM8wC7EQstlklrXYbhMfvXPPjjGnD87O59dilJtzgIELRvwadNkZT8vq 1y8GPPy8e8Vae0DGw8MQ8YY5kfRMiYYC3jgaywe56BSJ6UHLky1L8yQ+wi+uJpJOOaQ4 KN7j4bE57kJ2NeOrYuOzAOwnQKxYIV2uB6aZpaZ8th744KTTKeFk7RxS4ZUlWzOl4dg5 UdFjIzWeGC/ZjeyMABjElotw+GJQk+XYR22SfArVVR4xpz7H7am5OU6ijVmS+vVHT7us Zg36WqKA3ZY48EpfMcDChESPEmwAAkdll8DGIxfAphNVVopnkL5Cmq/+eVkzv5DGqi9K U8ew== X-Gm-Message-State: AOUpUlHXMak6IY9NFxzTzQFA5WckXdDKrGZyzdDKDjF86ZZTTdMqjr8n m1hQWzK3LiM0BTadwtGKfcTouAWZ X-Google-Smtp-Source: AAOMgpf7WI3nAfeBZdT62Z8tXHLFs9Q7WL3Q8N9w0oX/wdyLgtewAwZtr478oPa/djBSKhBBauwRAg== X-Received: by 2002:a17:902:a60b:: with SMTP id u11-v6mr3799731plq.158.1532649910156; Thu, 26 Jul 2018 17:05:10 -0700 (PDT) Received: from ako.hgst.com ([199.255.47.11]) by smtp.gmail.com with ESMTPSA id u13-v6sm3216008pfm.121.2018.07.26.17.05.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 26 Jul 2018 17:05:09 -0700 (PDT) From: Naohiro Aota To: linux-btrfs@vger.kernel.org, dsterba@suse.com Cc: jbacik@fb.com, clm@fb.com, Naohiro Aota Subject: [PATCH] btrfs: revert fs_devices state on error of btrfs_init_new_device() Date: Fri, 27 Jul 2018 09:04:55 +0900 Message-Id: <20180727000455.2647-1-naota@elisp.net> X-Mailer: git-send-email 2.18.0 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 When btrfs hits error after modifying fs_devices in btrfs_init_new_device() (such as btrfs_add_dev_item() returns error), it leaves everything as is, but frees allocated btrfs_device. As a result, fs_devices->devices and fs_devices->alloc_list contain already freed btrfs_device, leading to later use-after-free bug. Error path also messes the things like ->num_devices. While they go backs to the original value by unscanning btrfs devices, it is safe to revert them here. Fixes: 79787eaab461 ("btrfs: replace many BUG_ONs with proper error handling") Signed-off-by: Naohiro Aota Reviewed-by: Filipe Manana --- fs/btrfs/volumes.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) This patch applies on master, but not on kdave/for-next because of 74b9f4e186eb ("btrfs: declare fs_devices in btrfs_init_new_device()") diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 1da162928d1a..5f0512fffa52 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2410,7 +2410,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path struct list_head *devices; struct super_block *sb = fs_info->sb; struct rcu_string *name; - u64 tmp; + u64 orig_super_total_bytes, orig_super_num_devices; int seeding_dev = 0; int ret = 0; bool unlocked = false; @@ -2509,12 +2509,14 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path if (!blk_queue_nonrot(q)) fs_info->fs_devices->rotating = 1; - tmp = btrfs_super_total_bytes(fs_info->super_copy); + orig_super_total_bytes = btrfs_super_total_bytes(fs_info->super_copy); btrfs_set_super_total_bytes(fs_info->super_copy, - round_down(tmp + device->total_bytes, fs_info->sectorsize)); + round_down(orig_super_total_bytes + device->total_bytes, + fs_info->sectorsize)); - tmp = btrfs_super_num_devices(fs_info->super_copy); - btrfs_set_super_num_devices(fs_info->super_copy, tmp + 1); + orig_super_num_devices = btrfs_super_num_devices(fs_info->super_copy); + btrfs_set_super_num_devices(fs_info->super_copy, + orig_super_num_devices + 1); /* add sysfs device entry */ btrfs_sysfs_add_device_link(fs_info->fs_devices, device); @@ -2594,6 +2596,22 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path error_sysfs: btrfs_sysfs_rm_device_link(fs_info->fs_devices, device); + mutex_lock(&fs_info->fs_devices->device_list_mutex); + mutex_lock(&fs_info->chunk_mutex); + list_del_rcu(&device->dev_list); + list_del(&device->dev_alloc_list); + fs_info->fs_devices->num_devices--; + fs_info->fs_devices->open_devices--; + fs_info->fs_devices->rw_devices--; + fs_info->fs_devices->total_devices--; + fs_info->fs_devices->total_rw_bytes -= device->total_bytes; + atomic64_sub(device->total_bytes, &fs_info->free_chunk_space); + btrfs_set_super_total_bytes(fs_info->super_copy, + orig_super_total_bytes); + btrfs_set_super_num_devices(fs_info->super_copy, + orig_super_num_devices); + mutex_unlock(&fs_info->chunk_mutex); + mutex_unlock(&fs_info->fs_devices->device_list_mutex); error_trans: if (seeding_dev) sb->s_flags |= SB_RDONLY;