mirror of https://github.com/vitalif/e2fsprogs
e2fsck: check ea-in-inode regions for overlap
Ensure that the various blobs in the in-inode EA region do not overlap. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>crypto
parent
657f508cbf
commit
78c666b832
|
@ -286,15 +286,17 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
|
||||||
struct ext2_super_block *sb = ctx->fs->super;
|
struct ext2_super_block *sb = ctx->fs->super;
|
||||||
struct ext2_inode_large *inode;
|
struct ext2_inode_large *inode;
|
||||||
struct ext2_ext_attr_entry *entry;
|
struct ext2_ext_attr_entry *entry;
|
||||||
char *start;
|
char *start, *header;
|
||||||
unsigned int storage_size, remain;
|
unsigned int storage_size, remain;
|
||||||
problem_t problem = 0;
|
problem_t problem = 0;
|
||||||
|
region_t region = 0;
|
||||||
|
|
||||||
inode = (struct ext2_inode_large *) pctx->inode;
|
inode = (struct ext2_inode_large *) pctx->inode;
|
||||||
storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
|
storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
|
||||||
inode->i_extra_isize;
|
inode->i_extra_isize;
|
||||||
start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
|
header = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
|
||||||
inode->i_extra_isize + sizeof(__u32);
|
inode->i_extra_isize;
|
||||||
|
start = header + sizeof(__u32);
|
||||||
entry = (struct ext2_ext_attr_entry *) start;
|
entry = (struct ext2_ext_attr_entry *) start;
|
||||||
|
|
||||||
/* scan all entry's headers first */
|
/* scan all entry's headers first */
|
||||||
|
@ -302,10 +304,28 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
|
||||||
/* take finish entry 0UL into account */
|
/* take finish entry 0UL into account */
|
||||||
remain = storage_size - sizeof(__u32);
|
remain = storage_size - sizeof(__u32);
|
||||||
|
|
||||||
|
region = region_create(0, storage_size);
|
||||||
|
if (!region) {
|
||||||
|
fix_problem(ctx, PR_1_EA_ALLOC_REGION_ABORT, pctx);
|
||||||
|
problem = 0;
|
||||||
|
ctx->flags |= E2F_FLAG_ABORT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (region_allocate(region, 0, sizeof(__u32))) {
|
||||||
|
problem = PR_1_INODE_EA_ALLOC_COLLISION;
|
||||||
|
goto fix;
|
||||||
|
}
|
||||||
|
|
||||||
while (remain >= sizeof(struct ext2_ext_attr_entry) &&
|
while (remain >= sizeof(struct ext2_ext_attr_entry) &&
|
||||||
!EXT2_EXT_IS_LAST_ENTRY(entry)) {
|
!EXT2_EXT_IS_LAST_ENTRY(entry)) {
|
||||||
__u32 hash;
|
__u32 hash;
|
||||||
|
|
||||||
|
if (region_allocate(region, (char *)entry - (char *)header,
|
||||||
|
EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
|
||||||
|
problem = PR_1_INODE_EA_ALLOC_COLLISION;
|
||||||
|
goto fix;
|
||||||
|
}
|
||||||
|
|
||||||
/* header eats this space */
|
/* header eats this space */
|
||||||
remain -= sizeof(struct ext2_ext_attr_entry);
|
remain -= sizeof(struct ext2_ext_attr_entry);
|
||||||
|
|
||||||
|
@ -333,6 +353,13 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
|
||||||
goto fix;
|
goto fix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry->e_value_size &&
|
||||||
|
region_allocate(region, sizeof(__u32) + entry->e_value_offs,
|
||||||
|
EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
|
||||||
|
problem = PR_1_INODE_EA_ALLOC_COLLISION;
|
||||||
|
goto fix;
|
||||||
|
}
|
||||||
|
|
||||||
hash = ext2fs_ext_attr_hash_entry(entry,
|
hash = ext2fs_ext_attr_hash_entry(entry,
|
||||||
start + entry->e_value_offs);
|
start + entry->e_value_offs);
|
||||||
|
|
||||||
|
@ -347,7 +374,15 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
|
||||||
|
|
||||||
entry = EXT2_EXT_ATTR_NEXT(entry);
|
entry = EXT2_EXT_ATTR_NEXT(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (region_allocate(region, (char *)entry - (char *)header,
|
||||||
|
sizeof(__u32))) {
|
||||||
|
problem = PR_1_INODE_EA_ALLOC_COLLISION;
|
||||||
|
goto fix;
|
||||||
|
}
|
||||||
fix:
|
fix:
|
||||||
|
if (region)
|
||||||
|
region_free(region);
|
||||||
/*
|
/*
|
||||||
* it seems like a corruption. it's very unlikely we could repair
|
* it seems like a corruption. it's very unlikely we could repair
|
||||||
* EA(s) in automatic fashion -bzzz
|
* EA(s) in automatic fashion -bzzz
|
||||||
|
@ -356,7 +391,7 @@ fix:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* simply remove all possible EA(s) */
|
/* simply remove all possible EA(s) */
|
||||||
*((__u32 *)start) = 0UL;
|
*((__u32 *)header) = 0UL;
|
||||||
e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
|
e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
|
||||||
EXT2_INODE_SIZE(sb), "pass1");
|
EXT2_INODE_SIZE(sb), "pass1");
|
||||||
}
|
}
|
||||||
|
|
|
@ -977,6 +977,11 @@ static struct e2fsck_problem problem_table[] = {
|
||||||
N_("@i %i passes checks, but checksum does not match @i. "),
|
N_("@i %i passes checks, but checksum does not match @i. "),
|
||||||
PROMPT_FIX, PR_PREEN_OK },
|
PROMPT_FIX, PR_PREEN_OK },
|
||||||
|
|
||||||
|
/* Inode extended attribute is corrupt (allocation collision) */
|
||||||
|
{ PR_1_INODE_EA_ALLOC_COLLISION,
|
||||||
|
N_("@i %i @a is corrupt (allocation collision). "),
|
||||||
|
PROMPT_CLEAR, 0},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inode extent block passes checks, but checksum does not match
|
* Inode extent block passes checks, but checksum does not match
|
||||||
* extent
|
* extent
|
||||||
|
|
|
@ -577,6 +577,9 @@ struct problem_context {
|
||||||
/* inode passes checks, but checksum does not match inode */
|
/* inode passes checks, but checksum does not match inode */
|
||||||
#define PR_1_INODE_ONLY_CSUM_INVALID 0x010068
|
#define PR_1_INODE_ONLY_CSUM_INVALID 0x010068
|
||||||
|
|
||||||
|
/* Inode EA allocation collision */
|
||||||
|
#define PR_1_INODE_EA_ALLOC_COLLISION 0x010069
|
||||||
|
|
||||||
/* extent block passes checks, but checksum does not match extent block */
|
/* extent block passes checks, but checksum does not match extent block */
|
||||||
#define PR_1_EXTENT_ONLY_CSUM_INVALID 0x01006A
|
#define PR_1_EXTENT_ONLY_CSUM_INVALID 0x01006A
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
Pass 1: Checking inodes, blocks, and sizes
|
||||||
|
Inode 12 extended attribute is corrupt (allocation collision). Clear? yes
|
||||||
|
|
||||||
|
Inode 13 extended attribute is corrupt (allocation collision). Clear? yes
|
||||||
|
|
||||||
|
Inode 14 extended attribute is corrupt (allocation collision). Clear? yes
|
||||||
|
|
||||||
|
Pass 2: Checking directory structure
|
||||||
|
Pass 3: Checking directory connectivity
|
||||||
|
Pass 4: Checking reference counts
|
||||||
|
Pass 5: Checking group summary information
|
||||||
|
|
||||||
|
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
|
||||||
|
test_filesys: 14/128 files (0.0% non-contiguous), 18/512 blocks
|
||||||
|
Exit status is 1
|
|
@ -0,0 +1,7 @@
|
||||||
|
Pass 1: Checking inodes, blocks, and sizes
|
||||||
|
Pass 2: Checking directory structure
|
||||||
|
Pass 3: Checking directory connectivity
|
||||||
|
Pass 4: Checking reference counts
|
||||||
|
Pass 5: Checking group summary information
|
||||||
|
test_filesys: 14/128 files (0.0% non-contiguous), 18/512 blocks
|
||||||
|
Exit status is 0
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
collisions in the inode ea area
|
Loading…
Reference in New Issue