1 ext4: add bounds checking to ext4_xattr_find_entry()
3 Add some paranoia checks to make sure we don't stray beyond the end of
4 the valid memory region containing ext4 xattr entries while we are
7 Also rename the function to xattr_find_entry() since it is static and
8 thus only used in fs/ext4/xattr.c
10 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
13 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
14 index 014cada27131..9b9ba7c85f7a 100644
17 @@ -277,18 +277,22 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
18 __xattr_check_inode((inode), (header), (end), __func__, __LINE__)
21 -ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index,
22 - const char *name, int sorted)
23 +xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
24 + void *end, int name_index, const char *name, int sorted)
26 - struct ext4_xattr_entry *entry;
27 + struct ext4_xattr_entry *entry, *next;
33 name_len = strlen(name);
35 - for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
36 + for (entry = *pentry; !IS_LAST_ENTRY(entry); entry = next) {
37 + next = EXT4_XATTR_NEXT(entry);
38 + if ((void *) next >= end) {
39 + EXT4_ERROR_INODE(inode, "corrupted xattr entries");
40 + return -EFSCORRUPTED;
42 cmp = name_index - entry->e_name_index;
44 cmp = name_len - entry->e_name_len;
45 @@ -510,6 +514,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
46 struct buffer_head *bh = NULL;
47 struct ext4_xattr_entry *entry;
51 struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
53 @@ -531,7 +536,8 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
55 ext4_xattr_block_cache_insert(ea_block_cache, bh);
57 - error = ext4_xattr_find_entry(&entry, name_index, name, 1);
58 + end = bh->b_data + bh->b_size;
59 + error = xattr_find_entry(inode, &entry, end, name_index, name, 1);
62 size = le32_to_cpu(entry->e_value_size);
63 @@ -580,7 +586,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
66 entry = IFIRST(header);
67 - error = ext4_xattr_find_entry(&entry, name_index, name, 0);
68 + error = xattr_find_entry(inode, &entry, end, name_index, name, 0);
71 size = le32_to_cpu(entry->e_value_size);
72 @@ -1809,8 +1815,8 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
73 bs->s.first = BFIRST(bs->bh);
74 bs->s.end = bs->bh->b_data + bs->bh->b_size;
75 bs->s.here = bs->s.first;
76 - error = ext4_xattr_find_entry(&bs->s.here, i->name_index,
78 + error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
79 + i->name_index, i->name, 1);
80 if (error && error != -ENODATA)
82 bs->s.not_found = error;
83 @@ -2169,8 +2175,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
86 /* Find the named attribute. */
87 - error = ext4_xattr_find_entry(&is->s.here, i->name_index,
89 + error = xattr_find_entry(inode, &is->s.here, is->s.end,
90 + i->name_index, i->name, 0);
91 if (error && error != -ENODATA)
93 is->s.not_found = error;