From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from bombadil.infradead.org ([198.137.202.133]:44660 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727989AbeIJVsQ (ORCPT ); Mon, 10 Sep 2018 17:48:16 -0400 Date: Mon, 10 Sep 2018 09:53:17 -0700 From: Christoph Hellwig To: syzbot Cc: bcrl@kvack.org, linux-aio@kvack.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com, viro@zeniv.linux.org.uk, Andrea Arcangeli , akpm@linux-foundation.org Subject: Re: possible deadlock in aio_poll Message-ID: <20180910165317.GA3237@infradead.org> References: <000000000000cbb35d05757f7a3a@google.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <000000000000cbb35d05757f7a3a@google.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: On Mon, Sep 10, 2018 at 12:41:05AM -0700, syzbot wrote: > ===================================================== > WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected > 4.19.0-rc2+ #229 Not tainted > ----------------------------------------------------- > syz-executor2/9399 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: > 00000000126506e0 (&ctx->fd_wqh){+.+.}, at: spin_lock > include/linux/spinlock.h:329 [inline] > 00000000126506e0 (&ctx->fd_wqh){+.+.}, at: aio_poll+0x760/0x1420 > fs/aio.c:1747 > > and this task is already holding: > 000000002bed6bf6 (&(&ctx->ctx_lock)->rlock){..-.}, at: spin_lock_irq > include/linux/spinlock.h:354 [inline] > 000000002bed6bf6 (&(&ctx->ctx_lock)->rlock){..-.}, at: aio_poll+0x738/0x1420 > fs/aio.c:1746 > which would create a new lock dependency: > (&(&ctx->ctx_lock)->rlock){..-.} -> (&ctx->fd_wqh){+.+.} ctx->fd_wqh seems to only exist in userfaultfd, which indeed seems to do strange open coded waitqueue locking, and seems to fail to disable irqs. Something like this should fix it: diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index bfa0ec69f924..356d2b8568c1 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -1026,7 +1026,7 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait, struct userfaultfd_ctx *fork_nctx = NULL; /* always take the fd_wqh lock before the fault_pending_wqh lock */ - spin_lock(&ctx->fd_wqh.lock); + spin_lock_irq(&ctx->fd_wqh.lock); __add_wait_queue(&ctx->fd_wqh, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); @@ -1112,13 +1112,13 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait, ret = -EAGAIN; break; } - spin_unlock(&ctx->fd_wqh.lock); + spin_unlock_irq(&ctx->fd_wqh.lock); schedule(); - spin_lock(&ctx->fd_wqh.lock); + spin_lock_irq(&ctx->fd_wqh.lock); } __remove_wait_queue(&ctx->fd_wqh, &wait); __set_current_state(TASK_RUNNING); - spin_unlock(&ctx->fd_wqh.lock); + spin_unlock_irq(&ctx->fd_wqh.lock); if (!ret && msg->event == UFFD_EVENT_FORK) { ret = resolve_userfault_fork(ctx, fork_nctx, msg);