From d7b69a87400ba3eb3f4ec32c67e5f77a727955cb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 30 Jun 2022 15:29:51 +0200 Subject: [PATCH] 5.18-stable patches added patches: io_uring-fix-not-locked-access-to-fixed-buf-table.patch --- ...not-locked-access-to-fixed-buf-table.patch | 85 +++++++++++++++++++ queue-5.18/series | 1 + 2 files changed, 86 insertions(+) create mode 100644 queue-5.18/io_uring-fix-not-locked-access-to-fixed-buf-table.patch diff --git a/queue-5.18/io_uring-fix-not-locked-access-to-fixed-buf-table.patch b/queue-5.18/io_uring-fix-not-locked-access-to-fixed-buf-table.patch new file mode 100644 index 00000000000..9d6eda86824 --- /dev/null +++ b/queue-5.18/io_uring-fix-not-locked-access-to-fixed-buf-table.patch @@ -0,0 +1,85 @@ +From 05b538c1765f8d14a71ccf5f85258dcbeaf189f7 Mon Sep 17 00:00:00 2001 +From: Pavel Begunkov +Date: Thu, 9 Jun 2022 08:34:35 +0100 +Subject: io_uring: fix not locked access to fixed buf table + +From: Pavel Begunkov + +commit 05b538c1765f8d14a71ccf5f85258dcbeaf189f7 upstream. + +We can look inside the fixed buffer table only while holding +->uring_lock, however in some cases we don't do the right async prep for +IORING_OP_{WRITE,READ}_FIXED ending up with NULL req->imu forcing making +an io-wq worker to try to resolve the fixed buffer without proper +locking. + +Move req->imu setup into early req init paths, i.e. io_prep_rw(), which +is called unconditionally for rw requests and under uring_lock. + +Fixes: 634d00df5e1cf ("io_uring: add full-fledged dynamic buffers support") +Signed-off-by: Pavel Begunkov +Signed-off-by: Greg Kroah-Hartman +--- + fs/io_uring.c | 34 ++++++++++++++++++---------------- + 1 file changed, 18 insertions(+), 16 deletions(-) + +--- a/fs/io_uring.c ++++ b/fs/io_uring.c +@@ -3187,6 +3187,21 @@ static int io_prep_rw(struct io_kiocb *r + int ret; + + kiocb->ki_pos = READ_ONCE(sqe->off); ++ /* used for fixed read/write too - just read unconditionally */ ++ req->buf_index = READ_ONCE(sqe->buf_index); ++ req->imu = NULL; ++ ++ if (req->opcode == IORING_OP_READ_FIXED || ++ req->opcode == IORING_OP_WRITE_FIXED) { ++ struct io_ring_ctx *ctx = req->ctx; ++ u16 index; ++ ++ if (unlikely(req->buf_index >= ctx->nr_user_bufs)) ++ return -EFAULT; ++ index = array_index_nospec(req->buf_index, ctx->nr_user_bufs); ++ req->imu = ctx->user_bufs[index]; ++ io_req_set_rsrc_node(req, ctx, 0); ++ } + + ioprio = READ_ONCE(sqe->ioprio); + if (ioprio) { +@@ -3199,11 +3214,9 @@ static int io_prep_rw(struct io_kiocb *r + kiocb->ki_ioprio = get_current_ioprio(); + } + +- req->imu = NULL; + req->rw.addr = READ_ONCE(sqe->addr); + req->rw.len = READ_ONCE(sqe->len); + req->rw.flags = READ_ONCE(sqe->rw_flags); +- req->buf_index = READ_ONCE(sqe->buf_index); + return 0; + } + +@@ -3335,20 +3348,9 @@ static int __io_import_fixed(struct io_k + static int io_import_fixed(struct io_kiocb *req, int rw, struct iov_iter *iter, + unsigned int issue_flags) + { +- struct io_mapped_ubuf *imu = req->imu; +- u16 index, buf_index = req->buf_index; +- +- if (likely(!imu)) { +- struct io_ring_ctx *ctx = req->ctx; +- +- if (unlikely(buf_index >= ctx->nr_user_bufs)) +- return -EFAULT; +- io_req_set_rsrc_node(req, ctx, issue_flags); +- index = array_index_nospec(buf_index, ctx->nr_user_bufs); +- imu = READ_ONCE(ctx->user_bufs[index]); +- req->imu = imu; +- } +- return __io_import_fixed(req, rw, iter, imu); ++ if (WARN_ON_ONCE(!req->imu)) ++ return -EFAULT; ++ return __io_import_fixed(req, rw, iter, req->imu); + } + + static void io_ring_submit_unlock(struct io_ring_ctx *ctx, bool needs_lock) diff --git a/queue-5.18/series b/queue-5.18/series index 680a72db6c6..0c7475526ea 100644 --- a/queue-5.18/series +++ b/queue-5.18/series @@ -3,3 +3,4 @@ clocksource-drivers-ixp4xx-drop-boardfile-probe-path.patch bcache-memset-on-stack-variables-in-bch_btree_check-and-bch_sectors_dirty_init.patch hinic-replace-memcpy-with-direct-assignment.patch powerpc-ftrace-remove-ftrace-init-tramp-once-kernel-init-is-complete.patch +io_uring-fix-not-locked-access-to-fixed-buf-table.patch -- 2.47.3