| From: Jan Kara <jack@suse.cz> |
| Date: Tue, 29 Jan 2013 22:48:17 -0500 |
| Subject: ext4: fix possible use-after-free with AIO |
| |
| commit 091e26dfc156aeb3b73bc5c5f277e433ad39331c upstream. |
| |
| 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. |
| |
| 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> |
| [bwh: Backported to 3.2: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| fs/ext4/inode.c | 2 +- |
| fs/ext4/page-io.c | 9 ++++----- |
| 2 files changed, 5 insertions(+), 6 deletions(-) |
| |
| --- a/fs/ext4/inode.c |
| +++ b/fs/ext4/inode.c |
| @@ -2795,9 +2795,9 @@ static void ext4_end_io_dio(struct kiocb |
| if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { |
| ext4_free_io_end(io_end); |
| out: |
| + inode_dio_done(inode); |
| if (is_async) |
| aio_complete(iocb, ret, 0); |
| - inode_dio_done(inode); |
| return; |
| } |
| |
| --- a/fs/ext4/page-io.c |
| +++ b/fs/ext4/page-io.c |
| @@ -108,14 +108,13 @@ int ext4_end_io_nolock(ext4_io_end_t *io |
| inode->i_ino, offset, size, ret); |
| } |
| |
| - if (io->iocb) |
| - aio_complete(io->iocb, io->result, 0); |
| - |
| - if (io->flag & EXT4_IO_END_DIRECT) |
| - inode_dio_done(inode); |
| /* Wake up anyone waiting on unwritten extent conversion */ |
| if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten)) |
| wake_up_all(ext4_ioend_wq(io->inode)); |
| + if (io->flag & EXT4_IO_END_DIRECT) |
| + inode_dio_done(inode); |
| + if (io->iocb) |
| + aio_complete(io->iocb, io->result, 0); |
| return ret; |
| } |
| |