Qu Wenruo 10952e
From a9261d4125c97ce8624e9941b75dee1b43ad5df9 Mon Sep 17 00:00:00 2001
Qu Wenruo 10952e
Patch-mainline: v5.1
Qu Wenruo 10952e
References: bsc#1134973
Qu Wenruo 10952e
Git-commit: a9261d4125c97ce8624e9941b75dee1b43ad5df9
Qu Wenruo 10952e
From: Anand Jain <anand.jain@oracle.com>
Qu Wenruo 10952e
Date: Mon, 15 Oct 2018 10:45:17 +0800
Qu Wenruo 10952e
Subject: [PATCH] btrfs: harden agaist duplicate fsid on scanned devices
Qu Wenruo 10952e
Qu Wenruo 10952e
It's not that impossible to imagine that a device OR a btrfs image is
Qu Wenruo 10952e
copied just by using the dd or the cp command. Which in case both the
Qu Wenruo 10952e
copies of the btrfs will have the same fsid. If on the system with
Qu Wenruo 10952e
automount enabled, the copied FS gets scanned.
Qu Wenruo 10952e
Qu Wenruo 10952e
We have a known bug in btrfs, that we let the device path be changed
Qu Wenruo 10952e
after the device has been mounted. So using this loop hole the new
Qu Wenruo 10952e
copied device would appears as if its mounted immediately after it's
Qu Wenruo 10952e
been copied.
Qu Wenruo 10952e
Qu Wenruo 10952e
For example:
Qu Wenruo 10952e
Qu Wenruo 10952e
Initially.. /dev/mmcblk0p4 is mounted as /
Qu Wenruo 10952e
Qu Wenruo 10952e
  $ lsblk
Qu Wenruo 10952e
  NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
Qu Wenruo 10952e
  mmcblk0     179:0    0 29.2G  0 disk
Qu Wenruo 10952e
  |-mmcblk0p4 179:4    0    4G  0 part /
Qu Wenruo 10952e
  |-mmcblk0p2 179:2    0  500M  0 part /boot
Qu Wenruo 10952e
  |-mmcblk0p3 179:3    0  256M  0 part [SWAP]
Qu Wenruo 10952e
  `-mmcblk0p1 179:1    0  256M  0 part /boot/efi
Qu Wenruo 10952e
Qu Wenruo 10952e
  $ btrfs fi show
Qu Wenruo 10952e
     Label: none  uuid: 07892354-ddaa-4443-90ea-f76a06accaba
Qu Wenruo 10952e
     Total devices 1 FS bytes used 1.40GiB
Qu Wenruo 10952e
     devid    1 size 4.00GiB used 3.00GiB path /dev/mmcblk0p4
Qu Wenruo 10952e
Qu Wenruo 10952e
Copy mmcblk0 to sda
Qu Wenruo 10952e
Qu Wenruo 10952e
  $ dd if=/dev/mmcblk0 of=/dev/sda
Qu Wenruo 10952e
Qu Wenruo 10952e
And immediately after the copy completes the change in the device
Qu Wenruo 10952e
superblock is notified which the automount scans using btrfs device scan
Qu Wenruo 10952e
and the new device sda becomes the mounted root device.
Qu Wenruo 10952e
Qu Wenruo 10952e
  $ lsblk
Qu Wenruo 10952e
  NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
Qu Wenruo 10952e
  sda           8:0    1 14.9G  0 disk
Qu Wenruo 10952e
  |-sda4        8:4    1    4G  0 part /
Qu Wenruo 10952e
  |-sda2        8:2    1  500M  0 part
Qu Wenruo 10952e
  |-sda3        8:3    1  256M  0 part
Qu Wenruo 10952e
  `-sda1        8:1    1  256M  0 part
Qu Wenruo 10952e
  mmcblk0     179:0    0 29.2G  0 disk
Qu Wenruo 10952e
  |-mmcblk0p4 179:4    0    4G  0 part
Qu Wenruo 10952e
  |-mmcblk0p2 179:2    0  500M  0 part /boot
Qu Wenruo 10952e
  |-mmcblk0p3 179:3    0  256M  0 part [SWAP]
Qu Wenruo 10952e
  `-mmcblk0p1 179:1    0  256M  0 part /boot/efi
Qu Wenruo 10952e
Qu Wenruo 10952e
  $ btrfs fi show /
Qu Wenruo 10952e
    Label: none  uuid: 07892354-ddaa-4443-90ea-f76a06accaba
Qu Wenruo 10952e
    Total devices 1 FS bytes used 1.40GiB
Qu Wenruo 10952e
    devid    1 size 4.00GiB used 3.00GiB path /dev/sda4
Qu Wenruo 10952e
Qu Wenruo 10952e
The bug is quite nasty that you can't either unmount /dev/sda4 or
Qu Wenruo 10952e
/dev/mmcblk0p4. And the problem does not get solved until you take sda
Qu Wenruo 10952e
out of the system on to another system to change its fsid using the
Qu Wenruo 10952e
'btrfstune -u' command.
Qu Wenruo 10952e
Qu Wenruo 10952e
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Qu Wenruo 10952e
Reviewed-by: David Sterba <dsterba@suse.com>
Qu Wenruo 10952e
Signed-off-by: David Sterba <dsterba@suse.com>
Qu Wenruo 10952e
Signed-off-by: Qu Wenruo <wqu@suse.com>
Qu Wenruo 10952e
---
Qu Wenruo 10952e
 fs/btrfs/volumes.c |   29 +++++++++++++++++++++++++++++
Qu Wenruo 10952e
 1 file changed, 29 insertions(+)
Qu Wenruo 10952e
Qu Wenruo 10952e
--- a/fs/btrfs/volumes.c
Qu Wenruo 10952e
+++ b/fs/btrfs/volumes.c
Qu Wenruo 10952e
@@ -641,6 +641,35 @@ static noinline int device_list_add(cons
Qu Wenruo 10952e
 			return PTR_ERR(device);
Qu Wenruo 10952e
 		}
Qu Wenruo 10952e
 
Qu Wenruo 10952e
+		/*
Qu Wenruo 10952e
+		 * We are going to replace the device path for a given devid,
Qu Wenruo 10952e
+		 * make sure it's the same device if the device is mounted
Qu Wenruo 10952e
+		 */
Qu Wenruo 10952e
+		if (device->bdev) {
Qu Wenruo 10952e
+			struct block_device *path_bdev;
Qu Wenruo 10952e
+
Qu Wenruo 10952e
+			path_bdev = lookup_bdev(path);
Qu Wenruo 10952e
+			if (IS_ERR(path_bdev)) {
Qu Wenruo 10952e
+				mutex_unlock(&fs_devices->device_list_mutex);
Qu Wenruo 752785
+				return PTR_ERR(path_bdev);
Qu Wenruo 10952e
+			}
Qu Wenruo 10952e
+
Qu Wenruo 10952e
+			if (device->bdev != path_bdev) {
Qu Wenruo 10952e
+				bdput(path_bdev);
Qu Wenruo 10952e
+				mutex_unlock(&fs_devices->device_list_mutex);
Qu Wenruo 10952e
+				btrfs_warn_in_rcu(device->fs_info,
Qu Wenruo 10952e
+			"duplicate device fsid:devid for %pU:%llu old:%s new:%s",
Qu Wenruo 10952e
+					disk_super->fsid, devid,
Qu Wenruo 10952e
+					rcu_str_deref(device->name), path);
Qu Wenruo 752785
+				return -EEXIST;
Qu Wenruo 10952e
+			}
Qu Wenruo 10952e
+			bdput(path_bdev);
Qu Wenruo 10952e
+			btrfs_info_in_rcu(device->fs_info,
Qu Wenruo 10952e
+				"device fsid %pU devid %llu moved old:%s new:%s",
Qu Wenruo 10952e
+				disk_super->fsid, devid,
Qu Wenruo 10952e
+				rcu_str_deref(device->name), path);
Qu Wenruo 10952e
+		}
Qu Wenruo 10952e
+
Qu Wenruo 10952e
 		name = rcu_string_strdup(path, GFP_NOFS);
Qu Wenruo 10952e
 		if (!name) {
Qu Wenruo 10952e
 			kfree(device);