Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp3691733ybv; Mon, 10 Feb 2020 04:48:10 -0800 (PST) X-Google-Smtp-Source: APXvYqxGVbchrwc1+uErl0Mbtz2yBbvpaDpWV3JiO2xRdjQSxYKXKD8OJA8HJE7vGJjeEBSa7xbb X-Received: by 2002:a05:6830:1049:: with SMTP id b9mr990582otp.100.1581338890434; Mon, 10 Feb 2020 04:48:10 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1581338890; cv=none; d=google.com; s=arc-20160816; b=0ce2m+2+yRii6pmZB26Dhq5IDaHhOtUbbpTxnP8wXilfIYfymfNMMnh54ZnLoTapIt +PqxQKjRzyYWg9LrrdEmyGoVE+OaFN7oSztGkBcYun7fPCu0vnH6XP+Zt680b7iW1D6V pbZtq98P7z6nXlY6LJg19/l1VabvSgFOYIOS8kJYaJ7B2SnbxuAWUMHv0QQrmbzWKZat 6XDzRfMUYAsPvtbbkWGlWRsjimGIIkxl/Hq/xz9RYMOHhx20evzZc06bxcJcOem3WcNA w0SywcnROVHzpoa9vOJ1MqI3ulerYLxkIDJiTUHAO1Jkx+YFvf8afc9lQnfjh8IFBAzY Hwhw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=84TvUbpdCvhETfHr34G5YYWffRJwNT7wAul/HdWU5Gs=; b=J4lS+phnKD2u9J0FtHVRGU7Z9kSn6Mn+B5LCazO/KGM5ANAvpiYVHTUuZ/F5w/Hwmk gmCTGvqN9NqeK6N53kEt71MMnbEHn9ug35xkk59u83XY6mxtYe42bCGgYmRF/Qm5BQ+q CQSdfHp3W9J+WtumJWi5op89o2N7ZoD7/Aae7O3Kh1GqoWSkRHKIVDiEy4WKbyxlytYL xGVqawctmWSVlS9WVOWPAvKvOKKBop+ZyynfidU+XTHLd9pniDKHTZMDZFFOBPI3uwJj ma2dhxMvSfCWoLpkIzdanSQiV8uiYsBw+P6ZieHGZ6dYLmcYjgZJhKzA5uz4PIb3ra8V ocxQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=EJab2h2B; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c67si120541oib.276.2020.02.10.04.47.59; Mon, 10 Feb 2020 04:48:10 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=EJab2h2B; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730592AbgBJMrZ (ORCPT + 99 others); Mon, 10 Feb 2020 07:47:25 -0500 Received: from mail.kernel.org ([198.145.29.99]:45926 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730176AbgBJMmL (ORCPT ); Mon, 10 Feb 2020 07:42:11 -0500 Received: from localhost (unknown [209.37.97.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 154B924649; Mon, 10 Feb 2020 12:42:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581338531; bh=bs7zV+hgjNQ75C7vmQpMka+XTmvJdnhnoCWjM+jttnk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EJab2h2BhRcawG/MEAFlgU1iTecBzIwSMotP9CuGjSb2ASH+fPDqCdppf383outUC a4+3h05WqtGXSunYn3eckEhljD3zJWc4Cs1odk13VhDlOkA+v4uH4q6GgJJJ5JqU2f iGHvjDWk9VNBtWfgY8nt2jT20FIu80Lh6hIDzFIc= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jens Axboe , Sasha Levin Subject: [PATCH 5.5 355/367] io_uring: prevent potential eventfd recursion on poll Date: Mon, 10 Feb 2020 04:34:28 -0800 Message-Id: <20200210122455.231348976@linuxfoundation.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200210122423.695146547@linuxfoundation.org> References: <20200210122423.695146547@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jens Axboe [ Upstream commit f0b493e6b9a8959356983f57112229e69c2f7b8c ] If we have nested or circular eventfd wakeups, then we can deadlock if we run them inline from our poll waitqueue wakeup handler. It's also possible to have very long chains of notifications, to the extent where we could risk blowing the stack. Check the eventfd recursion count before calling eventfd_signal(). If it's non-zero, then punt the signaling to async context. This is always safe, as it takes us out-of-line in terms of stack and locking context. Cc: stable@vger.kernel.org # 5.1+ Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- fs/io_uring.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 131087782bec9..f470fb21467e4 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -738,21 +738,28 @@ static struct io_uring_cqe *io_get_cqring(struct io_ring_ctx *ctx) static inline bool io_should_trigger_evfd(struct io_ring_ctx *ctx) { + if (!ctx->cq_ev_fd) + return false; if (!ctx->eventfd_async) return true; return io_wq_current_is_worker() || in_interrupt(); } -static void io_cqring_ev_posted(struct io_ring_ctx *ctx) +static void __io_cqring_ev_posted(struct io_ring_ctx *ctx, bool trigger_ev) { if (waitqueue_active(&ctx->wait)) wake_up(&ctx->wait); if (waitqueue_active(&ctx->sqo_wait)) wake_up(&ctx->sqo_wait); - if (ctx->cq_ev_fd && io_should_trigger_evfd(ctx)) + if (trigger_ev) eventfd_signal(ctx->cq_ev_fd, 1); } +static void io_cqring_ev_posted(struct io_ring_ctx *ctx) +{ + __io_cqring_ev_posted(ctx, io_should_trigger_evfd(ctx)); +} + /* Returns true if there are no backlogged entries after the flush */ static bool io_cqring_overflow_flush(struct io_ring_ctx *ctx, bool force) { @@ -2645,6 +2652,14 @@ static void io_poll_complete_work(struct io_wq_work **workptr) io_wq_assign_next(workptr, nxt); } +static void io_poll_trigger_evfd(struct io_wq_work **workptr) +{ + struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work); + + eventfd_signal(req->ctx->cq_ev_fd, 1); + io_put_req(req); +} + static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, void *key) { @@ -2667,13 +2682,21 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, * for finalizing the request, mark us as having grabbed that already. */ if (mask && spin_trylock_irqsave(&ctx->completion_lock, flags)) { + bool trigger_ev; + hash_del(&req->hash_node); io_poll_complete(req, mask, 0); - req->flags |= REQ_F_COMP_LOCKED; - io_put_req(req); + trigger_ev = io_should_trigger_evfd(ctx); + if (trigger_ev && eventfd_signal_count()) { + trigger_ev = false; + req->work.func = io_poll_trigger_evfd; + } else { + req->flags |= REQ_F_COMP_LOCKED; + io_put_req(req); + req = NULL; + } spin_unlock_irqrestore(&ctx->completion_lock, flags); - - io_cqring_ev_posted(ctx); + __io_cqring_ev_posted(ctx, trigger_ev); } else { io_queue_async_work(req); } -- 2.20.1