+++ /dev/null
-From 5369a762c882c0b6e9599e4ebbb3a9ba9eee7e2d Mon Sep 17 00:00:00 2001
-From: Theodore Ts'o <tytso@mit.edu>
-Date: Wed, 13 Jun 2018 00:23:11 -0400
-Subject: ext4: add corruption check in ext4_xattr_set_entry()
-
-From: Theodore Ts'o <tytso@mit.edu>
-
-commit 5369a762c882c0b6e9599e4ebbb3a9ba9eee7e2d upstream.
-
-In theory this should have been caught earlier when the xattr list was
-verified, but in case it got missed, it's simple enough to add check
-to make sure we don't overrun the xattr buffer.
-
-This addresses CVE-2018-10879.
-
-https://bugzilla.kernel.org/show_bug.cgi?id=200001
-
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Reviewed-by: Andreas Dilger <adilger@dilger.ca>
-[bwh: Backported to 3.16:
- - Add inode parameter to ext4_xattr_set_entry() and update callers
- - Return -EIO instead of -EFSCORRUPTED on error
- - Adjust context]
-Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-[adjusted for 4.4 context]
-Signed-off-by: Daniel Rosenberg <drosen@google.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- fs/ext4/xattr.c | 22 ++++++++++++++--------
- 1 file changed, 14 insertions(+), 8 deletions(-)
-
---- a/fs/ext4/xattr.c
-+++ b/fs/ext4/xattr.c
-@@ -638,14 +638,20 @@ static size_t ext4_xattr_free_space(stru
- }
-
- 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 -EIO;
-+ }
- if (!last->e_value_block && last->e_value_size) {
- size_t offs = le16_to_cpu(last->e_value_offs);
- if (offs < min_offs)
-@@ -825,7 +831,7 @@ ext4_xattr_block_set(handle_t *handle, s
- ce = NULL;
- }
- 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, s
- 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)
-@@ -1037,7 +1043,7 @@ int ext4_xattr_ibody_inline_set(handle_t
-
- 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)) {
-@@ -1049,7 +1055,7 @@ int ext4_xattr_ibody_inline_set(handle_t
- 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;
-@@ -1075,7 +1081,7 @@ static int ext4_xattr_ibody_set(handle_t
-
- 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));