mirror of https://github.com/vitalif/e2fsprogs
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@mit.edu>bitmap-optimize
parent
7dca4c88f1
commit
7518c17686
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue