| From foo@baz Fri Jun 3 03:29:03 PM CEST 2022 |
| From: Pavel Begunkov <asml.silence@gmail.com> |
| Date: Fri, 3 Jun 2022 13:17:05 +0100 |
| Subject: io_uring: fix using under-expanded iters |
| To: stable@vger.kernel.org |
| Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Jens Axboe <axboe@kernel.dk>, asml.silence@gmail.com |
| Message-ID: <5d1530f17820142cfe98a8fff6d425d47c4b18ca.1654258554.git.asml.silence@gmail.com> |
| |
| From: Pavel Begunkov <asml.silence@gmail.com> |
| |
| [ upstream commit cd65869512ab5668a5d16f789bc4da1319c435c4 ] |
| |
| The issue was first described and addressed in |
| 89c2b3b7491820 ("io_uring: reexpand under-reexpanded iters"), but |
| shortly after reimplemented as. |
| cd65869512ab56 ("io_uring: use iov_iter state save/restore helpers"). |
| |
| Here we follow the approach from the second patch but without in-callback |
| resubmissions, fixups for not yet supported in 5.10 short read retries |
| and replacing iov_iter_state with iter copies to not pull even more |
| dependencies, and because it's just much simpler. |
| |
| Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/io_uring.c | 8 ++++++-- |
| 1 file changed, 6 insertions(+), 2 deletions(-) |
| |
| --- a/fs/io_uring.c |
| +++ b/fs/io_uring.c |
| @@ -3389,6 +3389,7 @@ static int io_read(struct io_kiocb *req, |
| struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; |
| struct kiocb *kiocb = &req->rw.kiocb; |
| struct iov_iter __iter, *iter = &__iter; |
| + struct iov_iter iter_cp; |
| struct io_async_rw *rw = req->async_data; |
| ssize_t io_size, ret, ret2; |
| bool no_async; |
| @@ -3399,6 +3400,7 @@ static int io_read(struct io_kiocb *req, |
| ret = io_import_iovec(READ, req, &iovec, iter, !force_nonblock); |
| if (ret < 0) |
| return ret; |
| + iter_cp = *iter; |
| io_size = iov_iter_count(iter); |
| req->result = io_size; |
| ret = 0; |
| @@ -3434,7 +3436,7 @@ static int io_read(struct io_kiocb *req, |
| if (req->file->f_flags & O_NONBLOCK) |
| goto done; |
| /* some cases will consume bytes even on error returns */ |
| - iov_iter_revert(iter, io_size - iov_iter_count(iter)); |
| + *iter = iter_cp; |
| ret = 0; |
| goto copy_iov; |
| } else if (ret < 0) { |
| @@ -3517,6 +3519,7 @@ static int io_write(struct io_kiocb *req |
| struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; |
| struct kiocb *kiocb = &req->rw.kiocb; |
| struct iov_iter __iter, *iter = &__iter; |
| + struct iov_iter iter_cp; |
| struct io_async_rw *rw = req->async_data; |
| ssize_t ret, ret2, io_size; |
| |
| @@ -3526,6 +3529,7 @@ static int io_write(struct io_kiocb *req |
| ret = io_import_iovec(WRITE, req, &iovec, iter, !force_nonblock); |
| if (ret < 0) |
| return ret; |
| + iter_cp = *iter; |
| io_size = iov_iter_count(iter); |
| req->result = io_size; |
| |
| @@ -3587,7 +3591,7 @@ done: |
| } else { |
| copy_iov: |
| /* some cases will consume bytes even on error returns */ |
| - iov_iter_revert(iter, io_size - iov_iter_count(iter)); |
| + *iter = iter_cp; |
| ret = io_setup_async_rw(req, iovec, inline_vecs, iter, false); |
| if (!ret) |
| return -EAGAIN; |