Commit 690e5325 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

block: fix use after free in __blkdev_direct_IO

We can't dereference the dio structure after submitting the last bio for
this request, as I/O completion might have happened before the code is
run. Introduce a local is_sync variable instead.

Fixes: 542ff7bf ("block: new direct I/O implementation")
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reported-by: default avatarMatias Bjørling <m@bjorling.me>
Tested-by: default avatarMatias Bjørling <m@bjorling.me>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent a4685d2f
...@@ -331,7 +331,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages) ...@@ -331,7 +331,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
struct blk_plug plug; struct blk_plug plug;
struct blkdev_dio *dio; struct blkdev_dio *dio;
struct bio *bio; struct bio *bio;
bool is_read = (iov_iter_rw(iter) == READ); bool is_read = (iov_iter_rw(iter) == READ), is_sync;
loff_t pos = iocb->ki_pos; loff_t pos = iocb->ki_pos;
blk_qc_t qc = BLK_QC_T_NONE; blk_qc_t qc = BLK_QC_T_NONE;
int ret; int ret;
...@@ -344,7 +344,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages) ...@@ -344,7 +344,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
bio_get(bio); /* extra ref for the completion handler */ bio_get(bio); /* extra ref for the completion handler */
dio = container_of(bio, struct blkdev_dio, bio); dio = container_of(bio, struct blkdev_dio, bio);
dio->is_sync = is_sync_kiocb(iocb); dio->is_sync = is_sync = is_sync_kiocb(iocb);
if (dio->is_sync) if (dio->is_sync)
dio->waiter = current; dio->waiter = current;
else else
...@@ -398,7 +398,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages) ...@@ -398,7 +398,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
} }
blk_finish_plug(&plug); blk_finish_plug(&plug);
if (!dio->is_sync) if (!is_sync)
return -EIOCBQUEUED; return -EIOCBQUEUED;
for (;;) { for (;;) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment