linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Goffredo Baroncelli <kreijack@libero.it>
To: Chris Mason <chris.mason@oracle.com>
Cc: Yan Zheng <zheng.yan@oracle.com>,
	M G Berberich <btrfs@oss.m-berberich.de>,
	linux-btrfs@vger.kernel.org
Subject: [RESPOST][BTRFS-PROGS][PATCH] btrfs_read_dev_super(): uninitialized variable
Date: Tue, 11 Sep 2012 19:31:46 +0200	[thread overview]
Message-ID: <504F7582.8040902@libero.it> (raw)
In-Reply-To: <50410BBE.6030601@libero.it>

[-- Attachment #1: Type: text/plain, Size: 3471 bytes --]

This is a repost because I rebased the change. The first attempt was 
done with the email "[BTRFS-PROGS][BUG][PATCH] Incorrect detection of a 
removed device  [was Re: “Bug”-report: inconsistency kernel <-> tools]" 
dated 08/31/2012.

In the function btrfs_read_dev_super() it is possible to use the 
variable fsid without initialisation.

In btrfs_read_dev_super(), during the scan of the superblock the 
variable fsid is initialised with the value of fsid of the first 
superblock. But if the first superblock contains an incorrect signature 
this initialisation is skipped.

int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 
sb_bytenr)
{
          u8 fsid[BTRFS_FSID_SIZE];
[...]

line 933:

          for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
                  bytenr = btrfs_sb_offset(i);
                  ret = pread64(fd, &buf, sizeof(buf), bytenr);
                  if (ret < sizeof(buf))
                          break;

                  if (btrfs_super_bytenr(&buf) != bytenr ||
                      strncmp((char *)(&buf.magic), BTRFS_MAGIC,
                              sizeof(buf.magic)))
                          continue;

                  if (i == 0)
                          memcpy(fsid, buf.fsid, sizeof(fsid));
                  else if (memcmp(fsid, buf.fsid, sizeof(fsid)))
                          continue;

                 [...]
          }

This bug could be triggered by the command "btrfs device delete", which 
zeros the signature of the first superblock.

The enclosed patch corrects the initialisation of the fsid variable; 
moreover if the fsid are different between the superblocks (the original 
one and its backups) the function fails because the device cannot be 
trusted. Finally it is handled the special case when the magic fields is 
zeroed in the *first* superblock. In this case the device is skipped.

Please apply, thank.

You can pull from
	http://cassiopea.homelinux.net/git/btrfs-progs-unstable.git
branch
	btrfs_read_dev_super-bug
	

BR
G.Baroncelli

-- 
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>

diff --git a/disk-io.c b/disk-io.c
index b21a87f..82fc3b8 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -910,6 +910,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char 
*path, u64 sb_bytenr,
  int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 
sb_bytenr)
  {
  	u8 fsid[BTRFS_FSID_SIZE];
+	int fsid_is_initialized = 0;
  	struct btrfs_super_block buf;
  	int i;
  	int ret;
@@ -936,15 +937,26 @@ int btrfs_read_dev_super(int fd, struct 
btrfs_super_block *sb, u64 sb_bytenr)
  		if (ret < sizeof(buf))
  			break;

-		if (btrfs_super_bytenr(&buf) != bytenr ||
-		    strncmp((char *)(&buf.magic), BTRFS_MAGIC,
+		if (btrfs_super_bytenr(&buf) != bytenr )
+			continue;
+		/* if magic is NULL, the device was removed */
+		if (buf.magic == 0 && i==0)
+			return -1;
+		if (strncmp((char *)(&buf.magic), BTRFS_MAGIC,
  			    sizeof(buf.magic)))
  			continue;

-		if (i == 0)
+		if (!fsid_is_initialized){
  			memcpy(fsid, buf.fsid, sizeof(fsid));
-		else if (memcmp(fsid, buf.fsid, sizeof(fsid)))
-			continue;
+			fsid_is_initialized = 1;
+		} else if (memcmp(fsid, buf.fsid, sizeof(fsid))) {
+			/*
+			 * the superblocks (the original one and
+			 * its backups) contain data of different
+			 * filesystems -> the disk cannot be trusted
+			 */
+			return -1;
+		}

  		if (btrfs_super_generation(&buf) > transid) {
  			memcpy(sb, &buf, sizeof(*sb));

[-- Attachment #2: btrfs_read_dev_super-bug.diff --]
[-- Type: text/x-patch, Size: 1362 bytes --]

diff --git a/disk-io.c b/disk-io.c
index b21a87f..82fc3b8 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -910,6 +910,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
 int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
 {
 	u8 fsid[BTRFS_FSID_SIZE];
+	int fsid_is_initialized = 0;
 	struct btrfs_super_block buf;
 	int i;
 	int ret;
@@ -936,15 +937,26 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
 		if (ret < sizeof(buf))
 			break;
 
-		if (btrfs_super_bytenr(&buf) != bytenr ||
-		    strncmp((char *)(&buf.magic), BTRFS_MAGIC,
+		if (btrfs_super_bytenr(&buf) != bytenr )
+			continue;
+		/* if magic is NULL, the device was removed */
+		if (buf.magic == 0 && i==0)
+			return -1;
+		if (strncmp((char *)(&buf.magic), BTRFS_MAGIC,
 			    sizeof(buf.magic)))
 			continue;
 
-		if (i == 0)
+		if (!fsid_is_initialized){
 			memcpy(fsid, buf.fsid, sizeof(fsid));
-		else if (memcmp(fsid, buf.fsid, sizeof(fsid)))
-			continue;
+			fsid_is_initialized = 1;
+		} else if (memcmp(fsid, buf.fsid, sizeof(fsid))) {
+			/* 
+			 * the superblocks (the original one and
+			 * its backups) contain data of different
+			 * filesystems -> the disk cannot be trusted
+			 */
+			return -1;
+		}
 
 		if (btrfs_super_generation(&buf) > transid) {
 			memcpy(sb, &buf, sizeof(*sb));

      parent reply	other threads:[~2012-09-11 17:30 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-28 19:52 “Bug”-report: inconsistency kernel <-> tools M G Berberich
2012-08-30 18:24 ` Goffredo Baroncelli
2012-08-30 18:37   ` Hugo Mills
2012-08-31 19:08   ` Goffredo Baroncelli
2012-08-31 21:37     ` [BTRFS-PROGS][BUG][PATCH] Incorrect detection of a removed device [was Re: “Bug”-report: inconsistency kernel <-> tools] Goffredo Baroncelli
2012-09-11 17:31     ` Goffredo Baroncelli [this message]

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=504F7582.8040902@libero.it \
    --to=kreijack@libero.it \
    --cc=btrfs@oss.m-berberich.de \
    --cc=chris.mason@oracle.com \
    --cc=kreijack@inwind.it \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=zheng.yan@oracle.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).