]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
ext4: add bounds checking to ext4_xattr_find_entry()
authorTheodore Ts'o <tytso@mit.edu>
Sat, 31 Mar 2018 00:00:56 +0000 (20:00 -0400)
committerKhalid Elmously <khalid.elmously@canonical.com>
Wed, 6 Jun 2018 15:48:53 +0000 (11:48 -0400)
BugLink: http://bugs.launchpad.net/bugs/1773233
commit 9496005d6ca4cf8f5ee8f828165a8956872dc59d upstream.

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 <tytso@mit.edu>
Cc: stable@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Acked-by: Khalid Elmously <khalid.elmously@canonical.com>
Acked-by: Brad Figg <brad.figg@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
fs/ext4/xattr.c

index 4bc3217fa03808d29d0db69a026f67ad68edf81f..88544d6f2cb3a9a25492234e5e545aa9fdbddf84 100644 (file)
@@ -275,18 +275,22 @@ errout:
        __xattr_check_inode((inode), (header), (end), __func__, __LINE__)
 
 static int
-ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index,
-                     const char *name, int sorted)
+xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
+                void *end, int name_index, const char *name, int sorted)
 {
-       struct ext4_xattr_entry *entry;
+       struct ext4_xattr_entry *entry, *next;
        size_t name_len;
        int cmp = 1;
 
        if (name == NULL)
                return -EINVAL;
        name_len = strlen(name);
-       entry = *pentry;
-       for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
+       for (entry = *pentry; !IS_LAST_ENTRY(entry); entry = next) {
+               next = EXT4_XATTR_NEXT(entry);
+               if ((void *) next >= end) {
+                       EXT4_ERROR_INODE(inode, "corrupted xattr entries");
+                       return -EFSCORRUPTED;
+               }
                cmp = name_index - entry->e_name_index;
                if (!cmp)
                        cmp = name_len - entry->e_name_len;
@@ -508,6 +512,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
        struct buffer_head *bh = NULL;
        struct ext4_xattr_entry *entry;
        size_t size;
+       void *end;
        int error;
        struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
 
@@ -529,7 +534,8 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
                goto cleanup;
        ext4_xattr_block_cache_insert(ea_block_cache, bh);
        entry = BFIRST(bh);
-       error = ext4_xattr_find_entry(&entry, name_index, name, 1);
+       end = bh->b_data + bh->b_size;
+       error = xattr_find_entry(inode, &entry, end, name_index, name, 1);
        if (error)
                goto cleanup;
        size = le32_to_cpu(entry->e_value_size);
@@ -578,7 +584,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
        if (error)
                goto cleanup;
        entry = IFIRST(header);
-       error = ext4_xattr_find_entry(&entry, name_index, name, 0);
+       error = xattr_find_entry(inode, &entry, end, name_index, name, 0);
        if (error)
                goto cleanup;
        size = le32_to_cpu(entry->e_value_size);
@@ -1807,8 +1813,8 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
                bs->s.first = BFIRST(bs->bh);
                bs->s.end = bs->bh->b_data + bs->bh->b_size;
                bs->s.here = bs->s.first;
-               error = ext4_xattr_find_entry(&bs->s.here, i->name_index,
-                                             i->name, 1);
+               error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
+                                        i->name_index, i->name, 1);
                if (error && error != -ENODATA)
                        goto cleanup;
                bs->s.not_found = error;
@@ -2167,8 +2173,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
                if (error)
                        return error;
                /* Find the named attribute. */
-               error = ext4_xattr_find_entry(&is->s.here, i->name_index,
-                                             i->name, 0);
+               error = xattr_find_entry(inode, &is->s.here, is->s.end,
+                                        i->name_index, i->name, 0);
                if (error && error != -ENODATA)
                        return error;
                is->s.not_found = error;