lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20081226035756.GL9871@mit.edu>
Date:	Thu, 25 Dec 2008 22:57:56 -0500
From:	Theodore Tso <tytso@....EDU>
To:	Matteo Croce <technoboy85@...il.com>,
	Paul Collins <paul@...ly.ondioline.org>
Cc:	linux-ext4@...r.kernel.org
Subject: Re: Massive filesystem corruption

On Sun, Dec 21, 2008 at 03:05:49AM +0100, Matteo Croce wrote:
> > > Pass 1: Checking inodes, blocks, and sizes
> > > Error1: Corrupt extent header on inode 107192
> > > [New Thread 0xb7e46700 (LWP 12878)]

The following patch to e2fsprogs will fix e2fsck's inability to deal
with a corrupted interior node in the extent tree.  It will be in the
next maintenance release of e2fsprogs, and it should address the
problem you've pointed out.

Regards,

						- Ted


commit 7518c176867099eb529502103106501861a71280
Author: Theodore Ts'o <tytso@....edu>
Date:   Thu Dec 25 22:42:38 2008 -0500

    e2fsck: Fix an unhandled corruption case in scan_extent_node()
    
    A corrupted interior node in an extent tree would cause e2fsck to
    crash with the error message:
    
    Error1: Corrupt extent header on inode 107192
    Aborted (core dumped)
    
    Handle this and related failures when scanning an inode's extent tree
    more robustly.
    
    Signed-off-by: "Theodore Ts'o" <tytso@....edu>

diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 2619272..04aeb26 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -1655,6 +1655,7 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
 			problem = PR_1_EXTENT_ENDS_BEYOND;
 
 		if (problem) {
+		report_problem:
 			pctx->blk = extent.e_pblk;
 			pctx->blk2 = extent.e_lblk;
 			pctx->num = extent.e_len;
@@ -1662,11 +1663,7 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
 				pctx->errcode =
 					ext2fs_extent_delete(ehandle, 0);
 				if (pctx->errcode) {
-					fix_problem(ctx,
-						    PR_1_EXTENT_DELETE_FAIL,
-						    pctx);
-					/* Should never get here */
-					ctx->flags |= E2F_FLAG_ABORT;
+					pctx->str = "ext2fs_extent_delete";
 					return;
 				}
 				pctx->errcode = ext2fs_extent_get(ehandle,
@@ -1682,23 +1679,27 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
 		}
 
 		if (!is_leaf) {
-			mark_block_used(ctx, extent.e_pblk);
-			pb->num_blocks++;
+			blk = extent.e_pblk;
 			pctx->errcode = ext2fs_extent_get(ehandle,
 						  EXT2_EXTENT_DOWN, &extent);
 			if (pctx->errcode) {
-				printf("Error1: %s on inode %u\n",
-					error_message(pctx->errcode), pctx->ino);
-				abort();
+				pctx->str = "EXT2_EXTENT_DOWN";
+				problem = PR_1_EXTENT_HEADER_INVALID;
+				if (pctx->errcode == EXT2_ET_EXTENT_HEADER_BAD)
+					goto report_problem;
+				return;
 			}
 			scan_extent_node(ctx, pctx, pb, extent.e_lblk, ehandle);
+			if (pctx->errcode)
+				return;
 			pctx->errcode = ext2fs_extent_get(ehandle,
 						  EXT2_EXTENT_UP, &extent);
 			if (pctx->errcode) {
-				printf("Error1: %s on inode %u\n",
-					error_message(pctx->errcode), pctx->ino);
-				abort();
+				pctx->str = "EXT2_EXTENT_UP";
+				return;
 			}
+			mark_block_used(ctx, blk);
+			pb->num_blocks++;
 			goto next;
 		}
 
@@ -1780,7 +1781,14 @@ static void check_blocks_extents(e2fsck_t ctx, struct problem_context *pctx,
 	}
 
 	scan_extent_node(ctx, pctx, pb, 0, ehandle);
-
+	if (pctx->errcode &&
+	    fix_problem(ctx, PR_1_EXTENT_ITERATE_FAILURE, pctx)) {
+		pb->num_blocks = 0;
+		inode->i_blocks = 0;
+		e2fsck_clear_inode(ctx, ino, inode, E2F_FLAG_RESTART,
+				   "check_blocks_extents");
+		pctx->errcode = 0;
+	}
 	ext2fs_extent_free(ehandle);
 }
 
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 19e8719..9cb3094 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -823,10 +823,11 @@ static struct e2fsck_problem problem_table[] = {
 	  N_("Error while reading over @x tree in @i %i: %m\n"),
 	  PROMPT_CLEAR_INODE, 0 },
 
-	/* Error deleting a bogus extent */
-	{ PR_1_EXTENT_DELETE_FAIL,
-	  N_("Error while deleting extent: %m\n"),
-	  PROMPT_ABORT, 0 },
+	/* Failure to iterate extents */
+	{ PR_1_EXTENT_ITERATE_FAILURE,
+	  N_("Failed to iterate extents in @i %i\n"
+	     "\t(op %s, blk %b, lblk %c): %m\n"),
+	  PROMPT_CLEAR_INODE, 0 },
 
 	/* Bad starting block in extent */
 	{ PR_1_EXTENT_BAD_START_BLK,
@@ -863,6 +864,10 @@ static struct e2fsck_problem problem_table[] = {
 	  N_("@i %i has out of order extents\n\t(@n logical @b %c, physical @b %b, len %N)\n"),
 	  PROMPT_CLEAR, 0 },
 
+	{ PR_1_EXTENT_HEADER_INVALID,
+	  N_("@i %i has an invalid extent node (blk %b, lblk %c)\n"),
+	  PROMPT_CLEAR, 0 },
+
 	/* Pass 1b errors */
 
 	/* Pass 1B: Rescan for duplicate/bad blocks */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 815b37c..1cb054c 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -479,8 +479,8 @@ struct problem_context {
 /* Error while reading extent tree */
 #define PR_1_READ_EXTENT		0x010056
 
-/* Error deleting a bogus extent */
-#define PR_1_EXTENT_DELETE_FAIL		0x010057
+/* Failure to iterate extents */
+#define PR_1_EXTENT_ITERATE_FAILURE	0x010057
 
 /* Bad starting block in extent */
 #define PR_1_EXTENT_BAD_START_BLK	0x010058
@@ -503,6 +503,9 @@ struct problem_context {
 /* Extents are out of order */
 #define PR_1_OUT_OF_ORDER_EXTENTS	0x01005E
 
+/* Extent node header invalid */
+#define PR_1_EXTENT_HEADER_INVALID	0x01005F
+
 /*
  * Pass 1b errors
  */
diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c
index 929e5cd..5545a94 100644
--- a/lib/ext2fs/extent.c
+++ b/lib/ext2fs/extent.c
@@ -441,8 +441,10 @@ retry:
 		eh = (struct ext3_extent_header *) newpath->buf;
 
 		retval = ext2fs_extent_header_verify(eh, handle->fs->blocksize);
-		if (retval)
+		if (retval) {
+			handle->level--;
 			return retval;
+		}
 
 		newpath->left = newpath->entries =
 			ext2fs_le16_to_cpu(eh->eh_entries);
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ