f2fs: sanity check of xattr entry size
commit 64beba0558fce7b59e9a8a7afd77290e82a22163 upstream. There is a security report where f2fs_getxattr() has a hole to expose wrong memory region when the image is malformed like this. f2fs_getxattr: entry->e_name_len: 4, size: 12288, buffer_size: 16384, len: 4 Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> [bwh: Backported to 4.14: Keep using kzalloc()] Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
88266a5413
commit
ec236cd6a2
@ -287,7 +287,7 @@ static int read_xattr_block(struct inode *inode, void *txattr_addr)
|
||||
static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
|
||||
unsigned int index, unsigned int len,
|
||||
const char *name, struct f2fs_xattr_entry **xe,
|
||||
void **base_addr)
|
||||
void **base_addr, int *base_size)
|
||||
{
|
||||
void *cur_addr, *txattr_addr, *last_addr = NULL;
|
||||
nid_t xnid = F2FS_I(inode)->i_xattr_nid;
|
||||
@ -298,8 +298,8 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
|
||||
if (!size && !inline_size)
|
||||
return -ENODATA;
|
||||
|
||||
txattr_addr = kzalloc(inline_size + size + XATTR_PADDING_SIZE,
|
||||
GFP_F2FS_ZERO);
|
||||
*base_size = inline_size + size + XATTR_PADDING_SIZE;
|
||||
txattr_addr = kzalloc(*base_size, GFP_F2FS_ZERO);
|
||||
if (!txattr_addr)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -311,8 +311,10 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
|
||||
|
||||
*xe = __find_inline_xattr(txattr_addr, &last_addr,
|
||||
index, len, name);
|
||||
if (*xe)
|
||||
if (*xe) {
|
||||
*base_size = inline_size;
|
||||
goto check;
|
||||
}
|
||||
}
|
||||
|
||||
/* read from xattr node block */
|
||||
@ -462,6 +464,7 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name,
|
||||
int error = 0;
|
||||
unsigned int size, len;
|
||||
void *base_addr = NULL;
|
||||
int base_size;
|
||||
|
||||
if (name == NULL)
|
||||
return -EINVAL;
|
||||
@ -472,7 +475,7 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name,
|
||||
|
||||
down_read(&F2FS_I(inode)->i_xattr_sem);
|
||||
error = lookup_all_xattrs(inode, ipage, index, len, name,
|
||||
&entry, &base_addr);
|
||||
&entry, &base_addr, &base_size);
|
||||
up_read(&F2FS_I(inode)->i_xattr_sem);
|
||||
if (error)
|
||||
return error;
|
||||
@ -486,6 +489,11 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name,
|
||||
|
||||
if (buffer) {
|
||||
char *pval = entry->e_name + entry->e_name_len;
|
||||
|
||||
if (base_size - (pval - (char *)base_addr) < size) {
|
||||
error = -ERANGE;
|
||||
goto out;
|
||||
}
|
||||
memcpy(buffer, pval, size);
|
||||
}
|
||||
error = size;
|
||||
|
Loading…
x
Reference in New Issue
Block a user