[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220414110908.124909230@linuxfoundation.org>
Date: Thu, 14 Apr 2022 15:14:12 +0200
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org, Bing-Jhong Billy Jheng <billy@...rlabs.sg>,
Pavel Begunkov <asml.silence@...il.com>
Subject: [PATCH 5.4 467/475] io_uring: fix fs->users overflow
From: Pavel Begunkov <asml.silence@...il.com>
There is a bunch of cases where we can grab req->fs but not put it, this
can be used to cause a controllable overflow with further implications.
Release req->fs in the request free path and make sure we zero the field
to be sure we don't do it twice.
Fixes: cac68d12c531 ("io_uring: grab ->fs as part of async offload")
Reported-by: Bing-Jhong Billy Jheng <billy@...rlabs.sg>
Signed-off-by: Pavel Begunkov <asml.silence@...il.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
---
fs/io_uring.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -438,6 +438,22 @@ static struct io_ring_ctx *io_ring_ctx_a
return ctx;
}
+static void io_req_put_fs(struct io_kiocb *req)
+{
+ struct fs_struct *fs = req->fs;
+
+ if (!fs)
+ return;
+
+ spin_lock(&req->fs->lock);
+ if (--fs->users)
+ fs = NULL;
+ spin_unlock(&req->fs->lock);
+ if (fs)
+ free_fs_struct(fs);
+ req->fs = NULL;
+}
+
static inline bool __io_sequence_defer(struct io_ring_ctx *ctx,
struct io_kiocb *req)
{
@@ -695,6 +711,7 @@ static void io_free_req_many(struct io_r
static void __io_free_req(struct io_kiocb *req)
{
+ io_req_put_fs(req);
if (req->file && !(req->flags & REQ_F_FIXED_FILE))
fput(req->file);
percpu_ref_put(&req->ctx->refs);
@@ -1701,16 +1718,7 @@ static int io_send_recvmsg(struct io_kio
ret = -EINTR;
}
- if (req->fs) {
- struct fs_struct *fs = req->fs;
-
- spin_lock(&req->fs->lock);
- if (--fs->users)
- fs = NULL;
- spin_unlock(&req->fs->lock);
- if (fs)
- free_fs_struct(fs);
- }
+ io_req_put_fs(req);
io_cqring_add_event(req->ctx, sqe->user_data, ret);
io_put_req(req);
return 0;
Powered by blists - more mailing lists