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 */
/* 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);
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);
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
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");
}
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
--- /dev/null
+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