Add latest patches
[ext4-patch-queue.git] / add-range-checking-to-ext4_xattr_find_entry
blobc7977a283a31677283a59e0749426caf9a95f8c3
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
5 scanning for a match.
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>
11 Cc: stable@kernel.org
13 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
14 index 014cada27131..9b9ba7c85f7a 100644
15 --- a/fs/ext4/xattr.c
16 +++ b/fs/ext4/xattr.c
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__)
20  static int
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)
25  {
26 -       struct ext4_xattr_entry *entry;
27 +       struct ext4_xattr_entry *entry, *next;
28         size_t name_len;
29         int cmp = 1;
31         if (name == NULL)
32                 return -EINVAL;
33         name_len = strlen(name);
34 -       entry = *pentry;
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;
41 +               }
42                 cmp = name_index - entry->e_name_index;
43                 if (!cmp)
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;
48         size_t size;
49 +       void *end;
50         int error;
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,
54                 goto cleanup;
55         ext4_xattr_block_cache_insert(ea_block_cache, bh);
56         entry = BFIRST(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);
60         if (error)
61                 goto cleanup;
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,
64         if (error)
65                 goto cleanup;
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);
69         if (error)
70                 goto cleanup;
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,
77 -                                             i->name, 1);
78 +               error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
79 +                                        i->name_index, i->name, 1);
80                 if (error && error != -ENODATA)
81                         goto cleanup;
82                 bs->s.not_found = error;
83 @@ -2169,8 +2175,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
84                 if (error)
85                         return error;
86                 /* Find the named attribute. */
87 -               error = ext4_xattr_find_entry(&is->s.here, i->name_index,
88 -                                             i->name, 0);
89 +               error = xattr_find_entry(inode, &is->s.here, is->s.end,
90 +                                        i->name_index, i->name, 0);
91                 if (error && error != -ENODATA)
92                         return error;
93                 is->s.not_found = error;