From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f50.google.com (mail-pj1-f50.google.com [209.85.216.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C03DB472782 for ; Thu, 13 Aug 2026 13:38:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.50 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786628340; cv=none; b=Owz/BJyN7OD4T7cemD1QCJWA2+R2kLeCumPRppgQQDcq+sd25biw7cnCzuhovydcO5xl91PAI5KKUIrGDXIb4LqZ0mtB83sN0+DYjBV7SvN3EB7TrqhipD+1g6TLx98Rg6klFxfanPXxxnOeDYDx4Fc+VFV8gaKWgnZjUS7TNwY= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786628340; c=relaxed/simple; bh=IVA4PnY1Zr29q/abnNB/XGGpoMYb+1RRhpB2XE7q/iA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=fRxW7SHL8KTtfw3NmoIpEk2/IqYB4pxdPmII+qXs7+6oZ878JCfwv7at+B7HR4/td4K9DCN5n3r/d9Ddgw9jRgfUmQ6JEhDwStdWYQT2wP0DOMZVe35vGYbFyxn+6TtbsnF8M616201diay0LkHLf0OWnNkWoLtzepV9CGos+H4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Glt0eJ78; arc=none smtp.client-ip=209.85.216.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Glt0eJ78" Received: by mail-pj1-f50.google.com with SMTP id 98e67ed59e1d1-38e7109321dso1813479a91.3 for ; Thu, 13 Aug 2026 06:38:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786628338; x=1787233138; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=cr9H9LdtxT2Z/rLHgl1Kyq8OxZYrKX/vRWeV8VtNQOg=; b=Glt0eJ78IQlzTSPhjbVHDoliJa3olvKuzAioxJ1RWazOTSc1KJhcNfighm2kN9JLAJ CV8qDzmmbZY+JNdl6dhP654Moynli6peXlRMNM5eCqEaNdCdAORev7Gvc2eJ/GHNEOR1 hyP/iYbgv+nYTG9H+KTbQuVAUdpw3VGjQTWWRKYrJpNpTM/h4SXWpr6vp28hrxWOxb4Z ADEoJdVOvCWjb5sxxxGKFWxWzswBRkeFURdbEJ664YkbJXdrOJlFkkkUrxqNtMZPxx5x PIVVnDKtwTPz5x14zrDlzSfQlOLtkC1QP4C4q8Nh8rqZX1lSapDPTgGbZiSaDQjXbrdD uiAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786628338; x=1787233138; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=cr9H9LdtxT2Z/rLHgl1Kyq8OxZYrKX/vRWeV8VtNQOg=; b=p/kXtcMGCylajwydGo5vwe2J+oDktDKlKlz82TQ0B+HErkuieHkOORxASnZ7qU8+KI iB7YJyK91fCPI/seLFR29UcpUM4ptgm3C8gLAcf6UfYPY0ajyn5XPk2qv5rNZD+fUL17 /Hkv52G/4U+F5U3y7GRBIOg0LIKYTzqwuK7nTSQi68ViXHzS9A2zNpQN+ErMjKQQN0Au XMgUX17suEj+PykbQpPXAs2DdO6Rdt9xFiAdHejThn/MNRLeXeLHom0Kch7FAFwuP0QK rFil6XxVYbWIMJACBtQvJ5LOkG9Zu3N4yXovGRoXQfVbFU192+VS38mtNX+iJYYrJcAZ YgTA== X-Forwarded-Encrypted: i=1; AHgh+RpXYUoWKnE4gIeFfPSCkJbnKZi401fukPcbUKiBp/lwB4iDAV5RBLKa/A+uzFUBre71/0YvzSaIQQ/vxYI=@vger.kernel.org X-Gm-Message-State: AOJu0YwIo1vkWyObrL0H4ck1YwhzHqXIs8F1U3Eg/t/9spE0/v2C/1MK xtjHf76+DLIMZX1DhPaV9D/8+pTQIWvIWh9rRbFCJyvD2Wq8twf+sgWo X-Gm-Gg: AR+sD13Fcb+hx9HHFtSwwfpEMe2KWG+gT1cMn8ADCQjJznZb5MHvTNfQkmg+ctXfi28 KlmAZhHblcxVQdyuq/ExJXYblqixC8mR62UotlJf/6sfItvn06+TH3x7omqHFunRyWYv02SZxXS uYtT7dW1qAajZGo2R2vdK7EHjj9pEnATyFe1EH158/F6osgrUbpJEx/lGRmaX54AxE1O0gcax0H EzRvdAjDkTRTv1B39Nabto2zEndoPxILSAZhIvjNO2w5tGNByLiOXmo/jCdDbrtXMf89ynrf2xW OsreQjAW7gT97Tucrf7F+vYGpMhnMcyf7DYExPbyscl//pUik7CsIZL+B9z5rZ8tjCg45WKkr0Y VvbxTmOweljeIsO8BOINvH+rSppVFWfHAh87uXGW0RNovuhqzNFrSRdliJdB9zl39tyxEuYcjF/ doqU8taYRYWNjwZY4VFfDNgtOY3HG80NYC9bJ5Uit3KV6zYlT5doXENT6V9X311cOcDSYwWgX+ X-Received: by 2002:a17:90b:52cf:b0:380:21b7:e727 with SMTP id 98e67ed59e1d1-3931e29780bmr6383848a91.14.1786628337839; Thu, 13 Aug 2026 06:38:57 -0700 (PDT) Received: from ancienth-X870E-Nova-WiFi ([125.186.72.2]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3931f44ddf3sm3319475a91.14.2026.08.13.06.38.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Aug 2026 06:38:57 -0700 (PDT) From: Daehyeon Ko <4ncienth@gmail.com> To: Benjamin LaHaise , linux-aio@kvack.org Cc: Alexander Viro , Christian Brauner , Jan Kara , Jens Axboe , Eric Biggers , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Daehyeon Ko <4ncienth@gmail.com> Subject: [PATCH] aio: prevent eventfd/epoll recursion on poll Date: Thu, 13 Aug 2026 22:38:43 +0900 Message-ID: <20260813133843.2933127-1-4ncienth@gmail.com> X-Mailer: git-send-email 2.54.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit aio_poll_wake() can complete a keyed poll request inline while the provider waitqueue lock is held. If the polled file is an epoll instance and the AIO result eventfd is watched by that same instance, signaling the result can feed back into epoll and try to take the provider waitqueue lock again. For example, a timerfd wake can follow this path: timerfd -> ep_poll_callback -> aio_poll_wake -> aio_complete -> eventfd_signal -> ep_poll_callback -> ep_poll_safewake The second ep_poll_safewake() recursively acquires ep->poll_wait.lock. eventfd_signal_allowed() does not prevent this because the wake chain did not begin in eventfd, so the task's eventfd recursion bit is still clear when aio_poll_wake() decides to complete inline. An unprivileged process can construct this graph and make a CPU spin on the recursive lock. DEBUG_SPINLOCK reports "BUG: spinlock recursion", and lockdep reports the same epoll waitqueue lock as both held and requested. Always defer eventfd-backed poll completions through the existing aio_poll_put_work() path. At this point the request has already been detached from the waitqueue and active request list, so the work item can publish the completion after the provider callback releases its lock. Poll completions without a result eventfd remain inline. Fixes: e8693bcfa0b4 ("aio: allow direct aio poll comletions for keyed wakeups") Cc: stable@vger.kernel.org Signed-off-by: Daehyeon Ko <4ncienth@gmail.com> --- fs/aio.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/aio.c b/fs/aio.c index f57fa21a250353..ef801781da08c0 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1869,7 +1869,12 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, list_del_init(&req->wait.entry); list_del(&iocb->ki_list); iocb->ki_res.res = mangle_poll(mask); - if (iocb->ki_eventfd && !eventfd_signal_allowed()) { + /* + * We hold an arbitrary provider waitqueue lock here. Signaling a + * result eventfd can feed back through epoll and try to take the same + * lock again. Defer all eventfd-backed poll completions. + */ + if (iocb->ki_eventfd) { iocb = NULL; INIT_WORK(&req->work, aio_poll_put_work); schedule_work(&req->work); -- 2.54.0