ext4: add corruption check in ext4_xattr_set_entry()
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 Change-Id: Ib3eef201f697e999e5ad81b40a01d878835b5847 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> Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
parent
219e0e0024
commit
d81084a8cc
|
@ -615,14 +615,20 @@ struct ext4_xattr_search {
|
|||
};
|
||||
|
||||
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)
|
||||
|
@ -791,7 +797,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
|
|||
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),
|
||||
|
@ -843,7 +849,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 == -EIO)
|
||||
goto bad_block;
|
||||
if (error)
|
||||
|
@ -1017,7 +1023,7 @@ 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));
|
||||
|
|
Loading…
Reference in New Issue