• Jan Kara's avatar
    ext4: Avoid freeing inodes on dirty list · ceff86fd
    Jan Kara authored
    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: default avatarJan Kara <jack@suse.cz>
    Link: https://lore.kernel.org/r/20200421085445.5731-4-jack@suse.czSigned-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
    ceff86fd
inode.c 174 KB