Skip to content

Commit 6460f9a

Browse files
hclee1Naim
authored andcommitted
ntfs: harden ntfs_ea_lookup against malformed EA entries
Validate p_ea->ea_name_length tightly, and the used entry size for every EA. Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
1 parent 275911e commit 6460f9a

1 file changed

Lines changed: 17 additions & 19 deletions

File tree

fs/ntfs/ea.c

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ static int ntfs_write_ea(struct ntfs_inode *ni, __le32 type, char *value, s64 ea
4646
}
4747

4848
static int ntfs_ea_lookup(char *ea_buf, s64 ea_buf_size, const char *name,
49-
int name_len, s64 *ea_offset, s64 *ea_size)
49+
int name_len, s64 *ea_offset, s64 *ea_size)
5050
{
5151
const struct ea_attr *p_ea;
52-
s64 offset;
52+
size_t actual_size;
53+
loff_t offset, p_ea_size;
5354
unsigned int next;
5455

5556
if (ea_buf_size < sizeof(struct ea_attr))
@@ -59,36 +60,33 @@ static int ntfs_ea_lookup(char *ea_buf, s64 ea_buf_size, const char *name,
5960
do {
6061
p_ea = (const struct ea_attr *)&ea_buf[offset];
6162
next = le32_to_cpu(p_ea->next_entry_offset);
63+
p_ea_size = next ? next : (ea_buf_size - offset);
6264

63-
if (offset + next > ea_buf_size ||
64-
((1 + p_ea->ea_name_length) > (ea_buf_size - offset)))
65+
if (p_ea_size < sizeof(struct ea_attr) ||
66+
offset + p_ea_size > ea_buf_size)
67+
break;
68+
69+
if ((s64)p_ea->ea_name_length + 1 >
70+
p_ea_size - offsetof(struct ea_attr, ea_name))
71+
break;
72+
73+
actual_size = ALIGN(struct_size(p_ea, ea_name, 1 + p_ea->ea_name_length +
74+
le16_to_cpu(p_ea->ea_value_length)), 4);
75+
if (actual_size > p_ea_size)
6576
break;
6677

6778
if (p_ea->ea_name_length == name_len &&
6879
!memcmp(p_ea->ea_name, name, name_len)) {
6980
*ea_offset = offset;
70-
if (next)
71-
*ea_size = next;
72-
else {
73-
unsigned int ea_len = 1 + p_ea->ea_name_length +
74-
le16_to_cpu(p_ea->ea_value_length);
75-
76-
if ((ea_buf_size - offset) < ea_len)
77-
goto out;
78-
79-
*ea_size = ALIGN(struct_size(p_ea, ea_name,
80-
1 + p_ea->ea_name_length +
81-
le16_to_cpu(p_ea->ea_value_length)), 4);
82-
}
81+
*ea_size = next ? next : actual_size;
8382

8483
if (ea_buf_size < *ea_offset + *ea_size)
8584
goto out;
8685

8786
return 0;
8887
}
8988
offset += next;
90-
} while (next > 0 && offset < ea_buf_size &&
91-
sizeof(struct ea_attr) < (ea_buf_size - offset));
89+
} while (next > 0 && offset < ea_buf_size);
9290

9391
out:
9492
return -ENOENT;

0 commit comments

Comments
 (0)