OSDN Git Service

Merge 4.4.162 into android-4.4
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / fs / ext4 / xattr.c
index 4d0365a..cfb546e 100644 (file)
@@ -639,14 +639,20 @@ static size_t ext4_xattr_free_space(struct ext4_xattr_entry *last,
 }
 
 static int
-ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s)
+ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s,
+                    struct inode *inode)
 {
-       struct ext4_xattr_entry *last;
+       struct ext4_xattr_entry *last, *next;
        size_t free, min_offs = s->end - s->base, name_len = strlen(i->name);
 
        /* Compute min_offs and last. */
        last = s->first;
-       for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
+       for (; !IS_LAST_ENTRY(last); last = next) {
+               next = EXT4_XATTR_NEXT(last);
+               if ((void *)next >= s->end) {
+                       EXT4_ERROR_INODE(inode, "corrupted xattr entries");
+                       return -EFSCORRUPTED;
+               }
                if (!last->e_value_block && last->e_value_size) {
                        size_t offs = le16_to_cpu(last->e_value_offs);
                        if (offs < min_offs)
@@ -829,7 +835,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
                        mb2_cache_entry_delete_block(ext4_mb_cache, hash,
                                                     bs->bh->b_blocknr);
                        ea_bdebug(bs->bh, "modifying in-place");
-                       error = ext4_xattr_set_entry(i, s);
+                       error = ext4_xattr_set_entry(i, s, inode);
                        if (!error) {
                                if (!IS_LAST_ENTRY(s->first))
                                        ext4_xattr_rehash(header(s->base),
@@ -875,7 +881,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
                s->end = s->base + sb->s_blocksize;
        }
 
-       error = ext4_xattr_set_entry(i, s);
+       error = ext4_xattr_set_entry(i, s, inode);
        if (error == -EFSCORRUPTED)
                goto bad_block;
        if (error)
@@ -1063,7 +1069,7 @@ int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
 
        if (EXT4_I(inode)->i_extra_isize == 0)
                return -ENOSPC;
-       error = ext4_xattr_set_entry(i, s);
+       error = ext4_xattr_set_entry(i, s, inode);
        if (error) {
                if (error == -ENOSPC &&
                    ext4_has_inline_data(inode)) {
@@ -1075,7 +1081,7 @@ int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
                        error = ext4_xattr_ibody_find(inode, i, is);
                        if (error)
                                return error;
-                       error = ext4_xattr_set_entry(i, s);
+                       error = ext4_xattr_set_entry(i, s, inode);
                }
                if (error)
                        return error;
@@ -1101,7 +1107,7 @@ static int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
 
        if (EXT4_I(inode)->i_extra_isize == 0)
                return -ENOSPC;
-       error = ext4_xattr_set_entry(i, s);
+       error = ext4_xattr_set_entry(i, s, inode);
        if (error)
                return error;
        header = IHDR(inode, ext4_raw_inode(&is->iloc));