From: Jens Axboe axboe@kernel.dk
mainline inclusion from mainline-5.6-rc1 commit 1a417f4e618e05fba29ba222f1e8555c302376ce category: feature bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=27 CVE: NA ---------------------------
We punt close to async for the final fput(), but we log the completion even before that even in that case. We rely on the request not having a files table assigned to detect what the final async close should do. However, if we punt the async queue to __io_queue_sqe(), we'll get ->files assigned and this makes io_close_finish() think it should both close the filp again (which does no harm) AND log a new CQE event for this request. This causes duplicate CQEs.
Queue the request up for async manually so we don't grab files needlessly and trigger this condition.
Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: yangerkun yangerkun@huawei.com Reviewed-by: zhangyi (F) yi.zhang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- fs/io_uring.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c index e21e647ae30a..5c16c1edc40f 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2795,16 +2795,13 @@ static void io_close_finish(struct io_wq_work **workptr) int ret;
ret = filp_close(req->close.put_file, req->work.files); - if (ret < 0) { + if (ret < 0) req_set_fail_links(req); - } io_cqring_add_event(req, ret); }
fput(req->close.put_file);
- /* we bypassed the re-issue, drop the submission reference */ - io_put_req(req); io_put_req_find_next(req, &nxt); if (nxt) io_wq_assign_next(workptr, nxt); @@ -2846,7 +2843,13 @@ static int io_close(struct io_kiocb *req, struct io_kiocb **nxt,
eagain: req->work.func = io_close_finish; - return -EAGAIN; + /* + * Do manual async queue here to avoid grabbing files - we don't + * need the files, and it'll cause io_close_finish() to close + * the file again and cause a double CQE entry for this request + */ + io_queue_async_work(req); + return 0; }
static int io_prep_sfr(struct io_kiocb *req, const struct io_uring_sqe *sqe)