All of lore.kernel.org
 help / color / mirror / Atom feed
From: Miao Xie <miaox@cn.fujitsu.com>
To: <linux-btrfs@vger.kernel.org>
Subject: [PATCH 14/18] Btrfs: fix use-after-free problem of the device during device replace
Date: Wed, 3 Sep 2014 21:35:43 +0800	[thread overview]
Message-ID: <1409751347-5296-14-git-send-email-miaox@cn.fujitsu.com> (raw)
In-Reply-To: <1409751347-5296-1-git-send-email-miaox@cn.fujitsu.com>

The problem is:
	Task0(device scan task)		Task1(device replace task)
	scan_one_device()
	mutex_lock(&uuid_mutex)
	device = find_device()
					mutex_lock(&device_list_mutex)
					lock_chunk()
					rm_and_free_source_device
					unlock_chunk()
					mutex_unlock(&device_list_mutex)
	check device

Destroying the target device if device replace fails also has the same problem.

We fix this problem by locking uuid_mutex during destroying source device or
target device, just like the device remove operation.

It is a temporary solution, we can fix this problem and make the code more
clear by atomic counter in the future.

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 fs/btrfs/dev-replace.c | 3 +++
 fs/btrfs/volumes.c     | 4 +++-
 fs/btrfs/volumes.h     | 2 ++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index aa4c828..e9cbbdb 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -509,6 +509,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
 	ret = btrfs_commit_transaction(trans, root);
 	WARN_ON(ret);
 
+	mutex_lock(&uuid_mutex);
 	/* keep away write_all_supers() during the finishing procedure */
 	mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
 	mutex_lock(&root->fs_info->chunk_mutex);
@@ -536,6 +537,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
 		btrfs_dev_replace_unlock(dev_replace);
 		mutex_unlock(&root->fs_info->chunk_mutex);
 		mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
+		mutex_unlock(&uuid_mutex);
 		if (tgt_device)
 			btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device);
 		mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
@@ -591,6 +593,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
 	 */
 	mutex_unlock(&root->fs_info->chunk_mutex);
 	mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
+	mutex_unlock(&uuid_mutex);
 
 	/* write back the superblocks */
 	trans = btrfs_start_transaction(root, 0);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index f0173b1..24d7001 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -50,7 +50,7 @@ static void __btrfs_reset_dev_stats(struct btrfs_device *dev);
 static void btrfs_dev_stat_print_on_error(struct btrfs_device *dev);
 static void btrfs_dev_stat_print_on_load(struct btrfs_device *device);
 
-static DEFINE_MUTEX(uuid_mutex);
+DEFINE_MUTEX(uuid_mutex);
 static LIST_HEAD(fs_uuids);
 
 static void lock_chunks(struct btrfs_root *root)
@@ -1867,6 +1867,7 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
 {
 	struct btrfs_device *next_device;
 
+	mutex_lock(&uuid_mutex);
 	WARN_ON(!tgtdev);
 	mutex_lock(&fs_info->fs_devices->device_list_mutex);
 	if (tgtdev->bdev) {
@@ -1886,6 +1887,7 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
 	call_rcu(&tgtdev->rcu, free_device);
 
 	mutex_unlock(&fs_info->fs_devices->device_list_mutex);
+	mutex_unlock(&uuid_mutex);
 }
 
 static int btrfs_find_device_by_path(struct btrfs_root *root, char *device_path,
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 76600a3..2b37da3 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -24,6 +24,8 @@
 #include <linux/btrfs.h>
 #include "async-thread.h"
 
+extern struct mutex uuid_mutex;
+
 #define BTRFS_STRIPE_LEN	(64 * 1024)
 
 struct buffer_head;
-- 
1.9.3


  parent reply	other threads:[~2014-09-03 13:34 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-03 13:35 [PATCH 01/18] Btrfs: cleanup unused num_can_discard in fs_devices Miao Xie
2014-09-03 13:35 ` [PATCH 02/18] Btrfs: cleanup double assignment of device->bytes_used when device replace finishes Miao Xie
2014-09-03 13:35 ` [PATCH 03/18] Btrfs: fix unprotected assignment of the target device Miao Xie
2014-09-03 13:35 ` [PATCH 04/18] Btrfs: fix wrong disk size when writing super blocks Miao Xie
2014-09-03 13:35 ` [PATCH 05/18] Btrfs: fix wrong device bytes_used in the super block Miao Xie
2014-09-03 13:35 ` [PATCH 06/18] Btrfs: Fix wrong free_chunk_space assignment during removing a device Miao Xie
2014-09-03 13:35 ` [PATCH 07/18] Btrfs: fix unprotected device->bytes_used update Miao Xie
2014-09-03 13:35 ` [PATCH 08/18] Btrfs: update free_chunk_space during allocting a new chunk Miao Xie
2014-09-03 13:35 ` [PATCH 09/18] Btrfs: fix unprotected device's variants on 32bits machine Miao Xie
2014-09-03 13:35 ` [PATCH 10/18] Btrfs: fix unprotected system chunk array insertion Miao Xie
2014-09-03 13:35 ` [PATCH 11/18] Btrfs: fix unprotected device list access when getting the fs information Miao Xie
2014-09-03 13:35 ` [PATCH 12/18] Btrfs: Fix misuse of chunk mutex Miao Xie
2014-09-11 15:39   ` Chris Mason
2014-09-03 13:35 ` [PATCH 13/18] Btrfs: fix unprotected device list access when cloning fs devices Miao Xie
2014-09-03 13:35 ` Miao Xie [this message]
2014-09-03 13:35 ` [PATCH 15/18] Btrfs: make the logic of source device removing more clear Miao Xie
2014-09-03 13:35 ` [PATCH 16/18] Btrfs: stop mounting the fs if the non-ENOENT errors happen when opening seed fs Miao Xie
2014-09-03 13:35 ` [PATCH 17/18] Btrfs: move the missing device to its own fs device list Miao Xie
2014-09-03 13:35 ` [PATCH 18/18] Btrfs: modify rw_devices counter under chunk_mutex context Miao Xie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1409751347-5296-14-git-send-email-miaox@cn.fujitsu.com \
    --to=miaox@cn.fujitsu.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.