@@ -2493,6 +2493,7 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
char * end;
struct ext2_ext_attr_header *header;
struct ext2_ext_attr_entry *first, *entry;
+ unsigned int remain;
blk64_t quota_blocks = EXT2FS_C2B(fs, 1);
__u64 quota_inodes = 0;
region_t region = 0;
@@ -2630,10 +2631,19 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
first = (struct ext2_ext_attr_entry *)(header+1);
end = block_buf + fs->blocksize;
+ /* take finish entry 0UL into account */
+ remain = end - (char *)first - sizeof(__u32);
entry = first;
- while ((char *)entry < end && *(__u32 *)entry) {
+ while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
__u32 hash;
+ /* entry->e_name_len is within the first four bytes */
+ if (EXT2_EXT_ATTR_LEN(entry->e_name_len) > remain) {
+ if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
+ goto clear_extattr;
+ break;
+ }
+ remain -= EXT2_EXT_ATTR_LEN(entry->e_name_len);
if (region_allocate(region, (char *)entry - (char *)header,
EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
@@ -2649,13 +2659,12 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
break;
}
if (entry->e_value_inum == 0) {
- if (entry->e_value_size > EXT2_XATTR_SIZE_MAX ||
- (entry->e_value_offs + entry->e_value_size >
- fs->blocksize)) {
+ if (EXT2_EXT_ATTR_SIZE(entry->e_value_size) > remain) {
if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
goto clear_extattr;
break;
}
+ remain -= EXT2_EXT_ATTR_SIZE(entry->e_value_size);
if (entry->e_value_size &&
region_allocate(region, entry->e_value_offs,
EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
@@ -2697,7 +2706,7 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
entry = EXT2_EXT_ATTR_NEXT(entry);
}
- if (region_allocate(region, (char *)entry - (char *)header, 4)) {
+ if (region_allocate(region, (char *)entry - (char *)header, sizeof(__u32))) {
if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
goto clear_extattr;
}