[Devel] [PATCH rh7 1/2] ms/ext4: Avoid freeing inodes on dirty list

Konstantin Khorenko khorenko at virtuozzo.com
Wed Feb 3 18:40:52 MSK 2021


Oops, disregard this one,
wrong patch sent.

--
Best regards,

Konstantin Khorenko,
Virtuozzo Linux Kernel Team

On 02/03/2021 06:37 PM, Konstantin Khorenko wrote:
> From: Jan Kara <jack at suse.cz>
>
> When we are evicting inode with journalled data, we may race with
> transaction commit in the following way:
>
> CPU0					CPU1
> jbd2_journal_commit_transaction()	evict(inode)
> 					  inode_io_list_del()
> 					  inode_wait_for_writeback()
>   process BJ_Forget list
>     __jbd2_journal_insert_checkpoint()
>     __jbd2_journal_refile_buffer()
>       __jbd2_journal_unfile_buffer()
>         if (test_clear_buffer_jbddirty(bh))
>           mark_buffer_dirty(bh)
> 	    __mark_inode_dirty(inode)
> 					  ext4_evict_inode(inode)
> 					    frees the inode
>
> This results in use-after-free issues in the writeback code (or
> the assertion added in the previous commit triggering).
>
> Fix the problem by removing inode from writeback lists once all the page
> cache is evicted and so inode cannot be added to writeback lists again.
>
> Signed-off-by: Jan Kara <jack at suse.cz>
> Link: https://lore.kernel.org/r/20200421085445.5731-4-jack@suse.cz
> Signed-off-by: Theodore Ts'o <tytso at mit.edu>
>
> (cherry picked from commit ceff86fddae8748fe00d4f2d249cb02cae62ad84)
> Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
> ---
>  fs/ext4/inode.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index f89fdb951aee..1c8e0cb64116 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -232,6 +232,16 @@ void ext4_evict_inode(struct inode *inode)
>  		ext4_begin_ordered_truncate(inode, 0);
>  	truncate_inode_pages_final(&inode->i_data);
>
> +	/*
> +	 * For inodes with journalled data, transaction commit could have
> +	 * dirtied the inode. Flush worker is ignoring it because of I_FREEING
> +	 * flag but we still need to remove the inode from the writeback lists.
> +	 */
> +	if (!list_empty_careful(&inode->i_io_list)) {
> +		WARN_ON_ONCE(!ext4_should_journal_data(inode));
> +		inode_io_list_del(inode);
> +	}
> +
>  	/*
>  	 * Protect us against freezing - iput() caller didn't have to have any
>  	 * protection against it
>


More information about the Devel mailing list