Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ext4: fix possible use-after-free with AIO

Running AIO is pinning inode in memory using file reference. Once AIO
is completed using aio_complete(), file reference is put and inode can
be freed from memory. So we have to be sure that calling aio_complete()
is the last thing we do with the inode.

CC: stable@vger.kernel.org
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Acked-by: Jeff Moyer <jmoyer@redhat.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

authored by

Jan Kara and committed by
Theodore Ts'o
091e26df b1deefc9

+5 -6
+1 -1
fs/ext4/inode.c
··· 2850 2850 if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { 2851 2851 ext4_free_io_end(io_end); 2852 2852 out: 2853 + inode_dio_done(inode); 2853 2854 if (is_async) 2854 2855 aio_complete(iocb, ret, 0); 2855 - inode_dio_done(inode); 2856 2856 return; 2857 2857 } 2858 2858
+4 -5
fs/ext4/page-io.c
··· 102 102 "(inode %lu, offset %llu, size %zd, error %d)", 103 103 inode->i_ino, offset, size, ret); 104 104 } 105 - if (io->iocb) 106 - aio_complete(io->iocb, io->result, 0); 107 - 108 - if (io->flag & EXT4_IO_END_DIRECT) 109 - inode_dio_done(inode); 110 105 /* Wake up anyone waiting on unwritten extent conversion */ 111 106 if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten)) 112 107 wake_up_all(ext4_ioend_wq(inode)); 108 + if (io->flag & EXT4_IO_END_DIRECT) 109 + inode_dio_done(inode); 110 + if (io->iocb) 111 + aio_complete(io->iocb, io->result, 0); 113 112 return ret; 114 113 } 115 114