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_inode_large *inode;
|
||||
struct ext2_ext_attr_entry *entry;
|
||||
char *start;
|
||||
char *start, *header;
|
||||
unsigned int storage_size, remain;
|
||||
problem_t problem = 0;
|
||||
region_t region = 0;
|
||||
|
||||
inode = (struct ext2_inode_large *) pctx->inode;
|
||||
storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
|
||||
inode->i_extra_isize;
|
||||
start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
|
||||
inode->i_extra_isize + sizeof(__u32);
|
||||
header = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
|
||||
inode->i_extra_isize;
|
||||
start = header + sizeof(__u32);
|
||||
entry = (struct ext2_ext_attr_entry *) start;
|
||||
|
||||
/* 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 */
|
||||
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) &&
|
||||
!EXT2_EXT_IS_LAST_ENTRY(entry)) {
|
||||
__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 */
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
if (region_allocate(region, (char *)entry - (char *)header,
|
||||
sizeof(__u32))) {
|
||||
problem = PR_1_INODE_EA_ALLOC_COLLISION;
|
||||
goto fix;
|
||||
}
|
||||
fix:
|
||||
if (region)
|
||||
region_free(region);
|
||||
/*
|
||||
* it seems like a corruption. it's very unlikely we could repair
|
||||
* EA(s) in automatic fashion -bzzz
|
||||
|
@ -356,7 +391,7 @@ fix:
|
|||
return;
|
||||
|
||||
/* simply remove all possible EA(s) */
|
||||
*((__u32 *)start) = 0UL;
|
||||
*((__u32 *)header) = 0UL;
|
||||
e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
|
||||
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. "),
|
||||
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
|
||||
* extent
|
||||
|
|
|
@ -577,6 +577,9 @@ struct problem_context {
|
|||
/* inode passes checks, but checksum does not match inode */
|
||||
#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 */
|
||||
#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