mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-09 18:19:06 +00:00
ext4: avoid running out of journal credits when appending to an inline file
commit 8bc1379b82
upstream.
Use a separate journal transaction if it turns out that we need to
convert an inline file to use an data block. Otherwise we could end
up failing due to not having journal credits.
This addresses CVE-2018-10883.
https://bugzilla.kernel.org/show_bug.cgi?id=200071
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8a9ef17c0d
commit
02945e49dc
3 changed files with 3 additions and 57 deletions
|
@ -3049,9 +3049,6 @@ extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode,
|
|||
extern int ext4_inline_data_fiemap(struct inode *inode,
|
||||
struct fiemap_extent_info *fieinfo,
|
||||
int *has_inline, __u64 start, __u64 len);
|
||||
extern int ext4_try_to_evict_inline_data(handle_t *handle,
|
||||
struct inode *inode,
|
||||
int needed);
|
||||
extern int ext4_inline_data_truncate(struct inode *inode, int *has_inline);
|
||||
|
||||
extern int ext4_convert_inline_data(struct inode *inode);
|
||||
|
|
|
@ -893,11 +893,11 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
|
|||
flags |= AOP_FLAG_NOFS;
|
||||
|
||||
if (ret == -ENOSPC) {
|
||||
ext4_journal_stop(handle);
|
||||
ret = ext4_da_convert_inline_data_to_extent(mapping,
|
||||
inode,
|
||||
flags,
|
||||
fsdata);
|
||||
ext4_journal_stop(handle);
|
||||
if (ret == -ENOSPC &&
|
||||
ext4_should_retry_alloc(inode->i_sb, &retries))
|
||||
goto retry_journal;
|
||||
|
@ -1865,42 +1865,6 @@ int ext4_inline_data_fiemap(struct inode *inode,
|
|||
return (error < 0 ? error : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called during xattr set, and if we can sparse space 'needed',
|
||||
* just create the extent tree evict the data to the outer block.
|
||||
*
|
||||
* We use jbd2 instead of page cache to move data to the 1st block
|
||||
* so that the whole transaction can be committed as a whole and
|
||||
* the data isn't lost because of the delayed page cache write.
|
||||
*/
|
||||
int ext4_try_to_evict_inline_data(handle_t *handle,
|
||||
struct inode *inode,
|
||||
int needed)
|
||||
{
|
||||
int error;
|
||||
struct ext4_xattr_entry *entry;
|
||||
struct ext4_inode *raw_inode;
|
||||
struct ext4_iloc iloc;
|
||||
|
||||
error = ext4_get_inode_loc(inode, &iloc);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
raw_inode = ext4_raw_inode(&iloc);
|
||||
entry = (struct ext4_xattr_entry *)((void *)raw_inode +
|
||||
EXT4_I(inode)->i_inline_off);
|
||||
if (EXT4_XATTR_LEN(entry->e_name_len) +
|
||||
EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) {
|
||||
error = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = ext4_convert_inline_data_nolock(handle, inode, &iloc);
|
||||
out:
|
||||
brelse(iloc.bh);
|
||||
return error;
|
||||
}
|
||||
|
||||
int ext4_inline_data_truncate(struct inode *inode, int *has_inline)
|
||||
{
|
||||
handle_t *handle;
|
||||
|
|
|
@ -2211,23 +2211,8 @@ 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, handle, inode, false /* is_block */);
|
||||
if (error) {
|
||||
if (error == -ENOSPC &&
|
||||
ext4_has_inline_data(inode)) {
|
||||
error = ext4_try_to_evict_inline_data(handle, inode,
|
||||
EXT4_XATTR_LEN(strlen(i->name) +
|
||||
EXT4_XATTR_SIZE(i->value_len)));
|
||||
if (error)
|
||||
return error;
|
||||
error = ext4_xattr_ibody_find(inode, i, is);
|
||||
if (error)
|
||||
return error;
|
||||
error = ext4_xattr_set_entry(i, s, handle, inode,
|
||||
false /* is_block */);
|
||||
}
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
if (error)
|
||||
return error;
|
||||
header = IHDR(inode, ext4_raw_inode(&is->iloc));
|
||||
if (!IS_LAST_ENTRY(s->first)) {
|
||||
header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
|
||||
|
|
Loading…
Reference in a new issue