Skip to content

Commit 9496005

Browse files
committed
ext4: add bounds checking to ext4_xattr_find_entry()
Add some paranoia checks to make sure we don't stray beyond the end of the valid memory region containing ext4 xattr entries while we are scanning for a match. Also rename the function to xattr_find_entry() since it is static and thus only used in fs/ext4/xattr.c Signed-off-by: Theodore Ts'o <[email protected]> Cc: [email protected]
1 parent de05ca8 commit 9496005

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

fs/ext4/xattr.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -276,18 +276,22 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
276276
__xattr_check_inode((inode), (header), (end), __func__, __LINE__)
277277

278278
static int
279-
ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index,
280-
const char *name, int sorted)
279+
xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
280+
void *end, int name_index, const char *name, int sorted)
281281
{
282-
struct ext4_xattr_entry *entry;
282+
struct ext4_xattr_entry *entry, *next;
283283
size_t name_len;
284284
int cmp = 1;
285285

286286
if (name == NULL)
287287
return -EINVAL;
288288
name_len = strlen(name);
289-
entry = *pentry;
290-
for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
289+
for (entry = *pentry; !IS_LAST_ENTRY(entry); entry = next) {
290+
next = EXT4_XATTR_NEXT(entry);
291+
if ((void *) next >= end) {
292+
EXT4_ERROR_INODE(inode, "corrupted xattr entries");
293+
return -EFSCORRUPTED;
294+
}
291295
cmp = name_index - entry->e_name_index;
292296
if (!cmp)
293297
cmp = name_len - entry->e_name_len;
@@ -509,6 +513,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
509513
struct buffer_head *bh = NULL;
510514
struct ext4_xattr_entry *entry;
511515
size_t size;
516+
void *end;
512517
int error;
513518
struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
514519

@@ -530,7 +535,8 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
530535
goto cleanup;
531536
ext4_xattr_block_cache_insert(ea_block_cache, bh);
532537
entry = BFIRST(bh);
533-
error = ext4_xattr_find_entry(&entry, name_index, name, 1);
538+
end = bh->b_data + bh->b_size;
539+
error = xattr_find_entry(inode, &entry, end, name_index, name, 1);
534540
if (error)
535541
goto cleanup;
536542
size = le32_to_cpu(entry->e_value_size);
@@ -579,7 +585,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
579585
if (error)
580586
goto cleanup;
581587
entry = IFIRST(header);
582-
error = ext4_xattr_find_entry(&entry, name_index, name, 0);
588+
error = xattr_find_entry(inode, &entry, end, name_index, name, 0);
583589
if (error)
584590
goto cleanup;
585591
size = le32_to_cpu(entry->e_value_size);
@@ -1808,8 +1814,8 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
18081814
bs->s.first = BFIRST(bs->bh);
18091815
bs->s.end = bs->bh->b_data + bs->bh->b_size;
18101816
bs->s.here = bs->s.first;
1811-
error = ext4_xattr_find_entry(&bs->s.here, i->name_index,
1812-
i->name, 1);
1817+
error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
1818+
i->name_index, i->name, 1);
18131819
if (error && error != -ENODATA)
18141820
goto cleanup;
18151821
bs->s.not_found = error;
@@ -2168,8 +2174,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
21682174
if (error)
21692175
return error;
21702176
/* Find the named attribute. */
2171-
error = ext4_xattr_find_entry(&is->s.here, i->name_index,
2172-
i->name, 0);
2177+
error = xattr_find_entry(inode, &is->s.here, is->s.end,
2178+
i->name_index, i->name, 0);
21732179
if (error && error != -ENODATA)
21742180
return error;
21752181
is->s.not_found = error;

0 commit comments

Comments
 (0)