lkml.org 
[lkml]   [2018]   [Nov]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 077/366] ext4: check if in-inode xattr is corrupted in ext4_expand_extra_isize_ea()
    3.16.61-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Theodore Ts'o <tytso@mit.edu>

    commit 9e92f48c34eb2b9af9d12f892e2fe1fce5e8ce35 upstream.

    We aren't checking to see if the in-inode extended attribute is
    corrupted before we try to expand the inode's extra isize fields.

    This can lead to potential crashes caused by the BUG_ON() check in
    ext4_xattr_shift_entries().

    Signed-off-by: Theodore Ts'o <tytso@mit.edu>
    [bwh: Backported to 3.16: s/EFSCORRUPTED/EIO/]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    fs/ext4/xattr.c | 32 ++++++++++++++++++++++++++++----
    1 file changed, 28 insertions(+), 4 deletions(-)

    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -243,6 +243,27 @@ ext4_xattr_check_block(struct inode *ino
    return error;
    }

    +static int
    +__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
    + void *end, const char *function, unsigned int line)
    +{
    + struct ext4_xattr_entry *entry = IFIRST(header);
    + int error = -EIO;
    +
    + if (((void *) header >= end) ||
    + (header->h_magic != le32_to_cpu(EXT4_XATTR_MAGIC)))
    + goto errout;
    + error = ext4_xattr_check_names(entry, end, entry);
    +errout:
    + if (error)
    + __ext4_error_inode(inode, function, line, 0,
    + "corrupted in-inode xattr");
    + return error;
    +}
    +
    +#define xattr_check_inode(inode, header, end) \
    + __xattr_check_inode((inode), (header), (end), __func__, __LINE__)
    +
    static inline int
    ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size)
    {
    @@ -368,7 +389,7 @@ ext4_xattr_ibody_get(struct inode *inode
    header = IHDR(inode, raw_inode);
    entry = IFIRST(header);
    end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
    - error = ext4_xattr_check_names(entry, end, entry);
    + error = xattr_check_inode(inode, header, end);
    if (error)
    goto cleanup;
    error = xattr_find_entry(inode, &entry, end, name_index, name,
    @@ -506,7 +527,7 @@ ext4_xattr_ibody_list(struct dentry *den
    raw_inode = ext4_raw_inode(&iloc);
    header = IHDR(inode, raw_inode);
    end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
    - error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header));
    + error = xattr_check_inode(inode, header, end);
    if (error)
    goto cleanup;
    error = ext4_xattr_list_entries(dentry, IFIRST(header),
    @@ -1038,8 +1059,7 @@ int ext4_xattr_ibody_find(struct inode *
    is->s.here = is->s.first;
    is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
    if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
    - error = ext4_xattr_check_names(IFIRST(header), is->s.end,
    - IFIRST(header));
    + error = xattr_check_inode(inode, header, is->s.end);
    if (error)
    return error;
    /* Find the named attribute. */
    @@ -1319,6 +1339,10 @@ retry:
    last = entry;
    total_ino = sizeof(struct ext4_xattr_ibody_header);

    + error = xattr_check_inode(inode, header, end);
    + if (error)
    + goto cleanup;
    +
    free = ext4_xattr_free_space(last, &min_offs, base, &total_ino);
    if (free >= new_extra_isize) {
    entry = IFIRST(header);
    \
     
     \ /
      Last update: 2018-11-11 21:12    [W:4.249 / U:1.240 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site